diff --git a/silecs-codegen/src/xml/genparam.py b/silecs-codegen/src/xml/genparam.py index 9aa31a1c988326ea475e07b4cb30a284dc2c08d1..67bee41216964481d5613c1979fb6a7565c10c1a 100644 --- a/silecs-codegen/src/xml/genparam.py +++ b/silecs-codegen/src/xml/genparam.py @@ -492,8 +492,8 @@ whichBaseAlignment = { # even if the first register of the block is a 16bit data. 'Rabbit_RCM_4010' : '16', 'Rabbit_RCM_2000' : '16', - 'S7_virtual_controller' : '16', - 'MODBUS_virtual_controller' : '16', + 'Linux_x64' : '16', + 'Linux_i386' : '16', 'BC9020' : '16', 'CX9020' : '32' } @@ -538,8 +538,8 @@ whichRegAddressFunction = { 'Other_Support_CNV' : alignCNVRegAddress, 'Rabbit_RCM_4010' : alignPCLikeRegAddress, 'Rabbit_RCM_2000' : alignPCLikeRegAddress, - 'S7_virtual_controller' : alignSimaticRegAddress, - 'MODBUS_virtual_controller' : alignPCLikeRegAddress, + 'Linux_x64' : alignSimaticRegAddress, + 'Linux_i386' : alignSimaticRegAddress, 'BC9020' : alignBCxxRegAddress, 'CX9020' : alignCXxxRegAddress } diff --git a/silecs-codegen/src/xml/genplcsrc.py b/silecs-codegen/src/xml/genplcsrc.py index 3f54f475c950f6ae4bc76c8f74d28592001a60ce..4852296131ab12edfd36d6b1fa1078e6557e2a96 100644 --- a/silecs-codegen/src/xml/genplcsrc.py +++ b/silecs-codegen/src/xml/genplcsrc.py @@ -378,7 +378,125 @@ def generateRabbitSources(paramDOM,sourceFolderPath,logTopics): # ---------------------------------------------------- def generatePCLikeSources(paramDOM,sourceFolderPath,logTopics): + deviceLabel = '' + deploy = getDeploymentInformation(paramDOM) + + # Prepare the source (<.h> file) with its diagnostic data-block header + cCodeString = PCLikeTemplate.cHeader(deploy.baseAddress) + cTypeDefinitions = '' + cDataAllocation = PCLikeTemplate.cAllocationComment(deploy.plcProtocol) + + blockList = '' + classList = '' + NBdeviceDefinitionList = '' + + # Generate sources for each class that is deployed in the PLC + for paramClass in ParamClass.getParamClassesFromRootNode(paramDOM): + + deviceNumber = len(deviceDOMList) + + #==== Generate the Blocks definition ==== + for blockIndex, blockDOM in enumerate(blockDOMList): + registerList = '' + blockName = blockDOM.getAttribute('name') + registerDOMList = blockDOM.getElementsByTagName("Register") # get Registers of the current block + for registerIndex, registerDOM in enumerate(registerDOMList): + registerName = registerDOM.getAttribute('name') + registerFormat = registerDOM.getAttribute('format') + registerDimension1 = long(registerDOM.getAttribute('array-dim1')) + registerDimension2 = long(registerDOM.getAttribute('array-dim2')) + + # If PLC does not supports this register format abort this generation and log the error + if(registerFormat in ['float64']): + iecommon.logError('ERROR: In register '+registerName+', '+registerFormat+' format not supported for current controller model.', True,logTopics) + + if(registerFormat == 'string'): + registerList += PCLikeTemplate.cRegister(registerName, registerFormat, registerDimension1, registerDimension2, long(registerDOM.getAttribute('string-len'))) + else: + registerList += PCLikeTemplate.cRegister(registerName, registerFormat, registerDimension1, registerDimension2) + + cTypeDefinitions += PCLikeTemplate.cBlockUDT(className, classVersion, blockName, 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.getAttribute('name') + blockList += PCLikeTemplate.cDeviceModeBlockInstantiation(className, blockName) + # instantiate for deviceList / deviceNumber + if withDeviceList == True: + # DeviceList + deviceList = '' + for deviceDOM in deviceDOMList: + deviceLabel = className + "_" + deviceDOM.getAttribute('label') + deviceList += deviceLabel + ', '; + deviceList = deviceList[:-2] # remove last comma space + classList += PCLikeTemplate.cDeviceModeClass_deviceList(blockList, deviceList) + else : + # DeviceNumber + classList += PCLikeTemplate.cDeviceModeClass_deviceNumber(className, blockList) + NBdeviceDefinitionList += PCLikeTemplate.cNBdeviceDefinition(className,deviceNumber) + + else: # BLOCK_MODE + # Generate the List of block in the class + for blockIndex, blockDOM in enumerate(blockDOMList): + # create instantation for current block + blockName = blockDOM.getAttribute('name') + if withDeviceList == True: + # DeviceList + deviceList = '' + for deviceDOM in deviceDOMList: + deviceLabel = deviceDOM.getAttribute('label') + deviceList +=PCLikeTemplate.cBlockModeDeviceInstantiation_deviceList(className, blockName, deviceLabel) + else: + # DeviceNumber + deviceList = PCLikeTemplate.cBlockModeDeviceInstantiation_deviceNumber(className, blockName) + + # allocation is the same with device list or device number + blockList += PCLikeTemplate.cBlockModeBlockInstantiation(deviceList, className, blockName) + + if withDeviceList == False: + NBdeviceDefinitionList += PCLikeTemplate.cNBdeviceDefinition(className,deviceNumber) + + # Predefine number of devices constant + cDataAllocation += NBdeviceDefinitionList + + if deploy.plcProtocol == 'DEVICE_MODE': + cDataAllocation += PCLikeTemplate.cDeviceModeDataInstantiation(classList) + cInitFunction = PCLikeTemplate.cInitDeviceMode(ieglobal.version,deploy.checksumRef,deploy.owner) + else: + cDataAllocation += PCLikeTemplate.cBlockModeDataInstantiation(blockList) + cInitFunction = PCLikeTemplate.cInitBlockMode(ieglobal.version,deploy.checksumRef,deploy.owner) + + + # Append data definitions + cCodeString += cTypeDefinitions + + # Append data allocation + cCodeString += cDataAllocation + + # Append initialization function + cCodeString += cInitFunction + + # Generate and append sample example + cCodeString += PCLikeTemplate.cExample(deploy.plcProtocol,withDeviceList,className, blockName, registerName, deviceLabel) + + # Finally, write the String C generated code into the temporal output file + sourcesPath = iefiles.getControllerSourcesDirectory(workspacePath, deploy.plcName, deploy.deployVersion) + sourcesFile = os.path.normpath(sourcesPath + "/%s.h" % deploy.plcName) + iecommon.logInfo("Generate PLC sources: %s" %sourcesFile,logTopics); + fdesc = open(sourcesFile, "w") + fdesc.write(cCodeString) + fdesc.close() + + # Clean-up the memory before return + deployDOM.unlink() + +# ---------------------------------------------------- +def generateVirtualS7Sources(deployDOM, classDOCList, deploy, workspacePath,logTopics): + includeDesign = '' allocDesign = '' deleteDesign = '' @@ -386,12 +504,11 @@ def generatePCLikeSources(paramDOM,sourceFolderPath,logTopics): protocolMode = 'BlockMode'; if deploy.plcProtocol == 'DEVICE_MODE': - protocolMode = 'DeviceMode'; - duConstructor = virtualS7Template.vs7DuConstructor(deploy.plcName, protocolMode, deploy.address) + protocolMode = 'DeviceMode'; + duConstructor = virtualS7Template.vs7DuConstructor(deploy.plcName, deploy.deployVersion, protocolMode, deploy.baseAddress) # Generate sources for each class that is deployed in the PLC - for paramClass in ParamClass.getParamClassesFromRootNode(paramDOM): - + for classDOC in classDOCList: blocksCodeString = '' createBlockCodeString = '' @@ -401,17 +518,21 @@ def generatePCLikeSources(paramDOM,sourceFolderPath,logTopics): createDeviceCodeString = '' deleteDeviceCodeString = '' designCodeString = '' + + classDOM = classDOC.getElementsByTagName("SILECS-Class")[0] #only one SILECS-Class node is expected + blockDOMList = classDOC.getElementsByTagName("Block") # get Blocks elements of that class - deviceDOMList = paramClass.getDeviceInstanceNodes() # get Device instances of that class + className = classDOM.getAttribute('name') + classVersion = classDOM.getAttribute('version') #DEPLOY-UNIT code generation ============================ - includeDesign += virtualS7Template.vs7DuDesignInclude(paramClass.name, paramClass.version) - allocDesign += virtualS7Template.vs7DuDesignAlloc(paramClass.name, paramClass.version) - deleteDesign += virtualS7Template.vs7DuDesignDelete(paramClass.name) - getDesign += virtualS7Template.vs7DuDesignGet(paramClass.name, paramClass.version) + includeDesign += virtualS7Template.vs7DuDesignInclude(className, classVersion) + allocDesign += virtualS7Template.vs7DuDesignAlloc(className, classVersion) + deleteDesign += virtualS7Template.vs7DuDesignDelete(className) + getDesign += virtualS7Template.vs7DuDesignGet(className, classVersion) #CLASSES code generation ================================ - for block in paramClass.getParamBlocks(): + for blockIndex, blockDOM in enumerate(blockDOMList): getSetCodeString = '' dimsCodeString = '' dataCodeString = '' @@ -419,51 +540,73 @@ def generatePCLikeSources(paramDOM,sourceFolderPath,logTopics): currentRegisterAddress = 0 #used to compute even/odd adress and insert align data by adding dummy registers previousRegisterMemSize = 0 #... dummyIndex = 0; + + blockName = blockDOM.getAttribute('name') + blockOffset = blockDOM.getAttribute('address') + registerDOMList = blockDOM.getElementsByTagName("Register") # get Registers of the current block - createBlockCodeString += virtualS7Template.vs7ClassCreateBlock(paramClass.name, block.name) - deleteBlockCodeString += virtualS7Template.vs7ClassDeleteBlock(paramClass.name, block.name) + createBlockCodeString += virtualS7Template.vs7ClassCreateBlock(className, blockName) + deleteBlockCodeString += virtualS7Template.vs7ClassDeleteBlock(className, blockName) - 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) + for registerIndex, registerDOM in enumerate(registerDOMList): + registerName = registerDOM.getAttribute('name') + registerFormat = registerDOM.getAttribute('format') + registerDimension1 = long(registerDOM.getAttribute('array-dim1')) + registerDimension2 = long(registerDOM.getAttribute('array-dim2')) + registerMemSize = long(registerDOM.getAttribute('mem-size')) #store the reigster mem-size for next iteration + + registerLength = 1 #in case string + if(registerFormat == 'string'): + registerLength = long(registerDOM.getAttribute('string-len')) + + getSetCodeString += virtualS7Template.vs7ClassGetSet(registerName, registerFormat, registerDimension1, registerDimension2,registerLength) + dimsCodeString += virtualS7Template.vs7ClassDimension(registerName, registerFormat, registerDimension1, registerDimension2,registerLength) #Specific code to force 16bit alignment if not scalar 8bit register (==> insert dummy register if needed) - dummyCodeString = virtualS7Template.vs7ClassDummyRegister(currentRegisterAddress, previousRegisterMemSize, register.memSize, dummyIndex) + dummyCodeString = virtualS7Template.vs7ClassDummyRegister(currentRegisterAddress, previousRegisterMemSize, registerMemSize, dummyIndex) dataCodeString += dummyCodeString - currentRegisterAddress += register.memSize + currentRegisterAddress += registerMemSize if dummyCodeString != "": dummyIndex += 1 currentRegisterAddress += 1 #and now insert the normal data register - dataCodeString += virtualS7Template.vs7ClassDataRegister(register.name, register.format, register.dim1, register.dim2, register.stringLength) - previousRegisterMemSize = register.memSize + dataCodeString += virtualS7Template.vs7ClassDataRegister(registerName, registerFormat, registerDimension1, registerDimension2, registerLength) + previousRegisterMemSize = registerMemSize - blocksCodeString += virtualS7Template.vs7ClassBlock(deploy.silecsVersion, deploy.owner, deploy.checksum, paramClass.name, block.name, getSetCodeString, block.address, dimsCodeString, dataCodeString) - + blocksCodeString += virtualS7Template.vs7ClassBlock(ieglobal.version, deploy.owner, deploy.checksumRef, className, blockName, getSetCodeString, blockOffset, dimsCodeString, dataCodeString) + + deviceDOMList = classDOC.getElementsByTagName("Instance") # get Device instances of that class for deviceIndex, deviceDOM in enumerate(deviceDOMList): - deviceLabel = deviceDOM.prop('label') - createDeviceCodeString += virtualS7Template.vs7ClassCreateDevice(paramClass.name, deviceLabel, deviceIndex) - deleteDeviceCodeString += virtualS7Template.vs7ClassDeleteDevice(paramClass.name, deviceLabel) + deviceLabel = deviceDOM.getAttribute('label') + createDeviceCodeString += virtualS7Template.vs7ClassCreateDevice(className, deviceLabel, deviceIndex) + deleteDeviceCodeString += virtualS7Template.vs7ClassDeleteDevice(className, deviceLabel) deviceCodeString = virtualS7Template.vs7ClassDevice(createBlockCodeString, deleteBlockCodeString) - designCodeString = virtualS7Template.vs7ClassDesign(paramClass.name, paramClass.version, createDeviceCodeString, deleteDeviceCodeString) + designCodeString = virtualS7Template.vs7ClassDesign(className, classVersion, createDeviceCodeString, deleteDeviceCodeString) - classCodeString = virtualS7Template.vs7ClassHeader(paramClass.name, paramClass.version, blocksCodeString, deviceCodeString, designCodeString) + classCodeString = virtualS7Template.vs7ClassHeader(className, classVersion, blocksCodeString, deviceCodeString, designCodeString) - # write the CLASS generated code into the temporal output file - generateControllerFiles(sourceFolderPath,deploy, "." + paramClass.name + ".h",classCodeString,logTopics); + # Finally, write the CLASS generated code into the temporal output file + sourcesPath = iefiles.getControllerSourcesDirectory(workspacePath, deploy.plcName, deploy.deployVersion) + sourcesFile = os.path.normpath(sourcesPath + "/%s_%s.h" % (className, classVersion)) + iecommon.logInfo("Generate PLC sources: %s" %sourcesFile,logTopics); + fdesc = open(sourcesFile, "w") + fdesc.write(classCodeString) + fdesc.close() # Prepare the source (<.h> file) with its diagnostic data-block header - duCodeString = virtualS7Template.vs7DuHeader(deploy.plcName, duConstructor, includeDesign, allocDesign, deleteDesign, getDesign) + duCodeString = virtualS7Template.vs7DuHeader(deploy.plcName, deploy.deployVersion, duConstructor, includeDesign, allocDesign, deleteDesign, getDesign) - # Write the DEPLOY-UNIT generated code into the temporal output file - generateControllerFiles(sourceFolderPath,deploy,".h",duCodeString,logTopics); + # Finally, write the DEPLOY-UNIT generated code into the temporal output file + sourcesPath = iefiles.getControllerSourcesDirectory(workspacePath, deploy.plcName, deploy.deployVersion) + sourcesFile = os.path.normpath(sourcesPath + "/%s_%s.h" % (deploy.plcName, deploy.deployVersion)) + iecommon.logInfo("Generate PLC sources: %s" %sourcesFile,logTopics); + fdesc = open(sourcesFile, "w") + fdesc.write(duCodeString) + fdesc.close() - # Prepare the source (<.h> file) with its diagnostic data-block header - mainCodeString = virtualS7Template.vs7MainCode(deploy.plcName) - - # write the DEPLOY-UNIT generated code into the temporal output file - generateControllerFiles(sourceFolderPath,deploy,".cpp",mainCodeString,logTopics); + # Clean-up the memory before return + deployDOM.unlink() # ---------------------------------------------------- def generateBeckhoffRegisters(paramClass, deviceDOM, block, deviceIndex, deploy, logTopics): @@ -592,6 +735,8 @@ def generateControllerCode(controller, paramsFile, sourceFolderPath, logTopics={ generateSiemensSources(paramDOM,sourceFolderPath,logTopics) elif controller.plcNode.get_name() == 'PC-Controller': generatePCLikeSources(paramDOM,sourceFolderPath,logTopics) + elif controller.plcNode.get_name() == 'VirtualS7': + generateVirtualS7Sources(paramDOM,sourceFolderPath,logTopics) elif controller.plcNode.get_name() == 'Schneider-PLC': generateSchneiderSources(paramDOM,sourceFolderPath,logTopics) elif controller.plcNode.get_name() == 'Rabbit-uC': diff --git a/silecs-codegen/src/xml/iefiles.py b/silecs-codegen/src/xml/iefiles.py index 32376c9da639aca71830390419205a7b72492390..951c8cc703d3016d02e402b3e9ac02af052f7b3c 100644 --- a/silecs-codegen/src/xml/iefiles.py +++ b/silecs-codegen/src/xml/iefiles.py @@ -126,6 +126,27 @@ def getDuWrapperFile(workspacePath, deployName, controllerName ): def getDuDesignWrapperFile(workspacePath, deployName, designName): return os.path.join(getDuWrapperSourceDirectory(workspacePath, deployName), getDuWrapperFileName(designName)) + +#--- DU VIRTUAL-S7 --- +def getDuVirtualS7FileName(deployName, deployVersion): + str = iecommon.capitalizeString(deployName) + "_" + deployVersion + return str.replace(".", "_") + ".h" + +def getDuVirtualS7SourceDirectory(workspacePath, deployName, deployVersion): + controllerPath = workspacePath + '/' + getDeployDirectoryName(deployName, deployVersion) + '/' \ + + ieglobal.generatedDir + '/' + ieglobal.controllerDir + controllerNorm = os.path.normpath(controllerPath) + return controllerNorm + +def getDuVirtualS7File(workspacePath, deployName, deployVersion): + return getDuVirtualS7SourceDirectory(workspacePath, deployName, deployVersion) + "/" \ + + getDuVirtualS7FileName(deployName, deployVersion) + +def getDuDesignVirtualS7File(workspacePath, deployName, deployVersion, designName, designVersion): + return getDuVirtualS7SourceDirectory(workspacePath, deployName, deployVersion) + "/" \ + + getDuVirtualS7FileName(designName, designVersion) + +#--- General --- def getFesa3CommonDirectory(workspacePath, designName): fesa3ClassPath = workspacePath + '/' + designName + '/src/' + designName + '/Common' fesa3ClassPathNorm = os.path.normpath(fesa3ClassPath) diff --git a/silecs-codegen/src/xml/model/Deploy/Controller.py b/silecs-codegen/src/xml/model/Deploy/Controller.py index 341bfa1169aceb30377ef7a350aed55628e2ae4d..4f3fea107f0fbfe4e957973000b4e1ccbdc4c53d 100644 --- a/silecs-codegen/src/xml/model/Deploy/Controller.py +++ b/silecs-codegen/src/xml/model/Deploy/Controller.py @@ -96,7 +96,7 @@ class Controller(object): elif type == "NI-Controller": return NIController(controllerNode) elif type == "PC-Controller": - return PCController(controllerNode) + return VirtualS7Controller(controllerNode) else: raise Exception( "Controller-Type " + type + " not supported" ) @@ -140,12 +140,18 @@ class RabbitController(Controller): self.baseAddress = long(self.plcNode.prop('base-address')) self.baseAddress = self.baseAddress * self.addressFactor -class PCController(Controller): +class VirtualS7Controller(Controller): + addressFactor = 1 def __init__(self, xmlNode): - super(PCController, self).__init__(xmlNode) - self.addressFactor = 2 #default - if self.system == "S7 virtual controller": - self.addressFactor = 1 + super(VirtualS7Controller, self).__init__(xmlNode) + self.brand = "SIEMENS" + self.baseAddress = long(self.plcNode.prop('base-address')) + self.baseAddress = self.baseAddress * self.addressFactor + +class VirtualModbusController(Controller): + addressFactor = 2 + def __init__(self, xmlNode): + super(VirtualModbusController, self).__init__(xmlNode) self.brand = "PCLike" self.baseAddress = long(self.plcNode.prop('base-address')) self.baseAddress = self.baseAddress * self.addressFactor diff --git a/silecs-codegen/src/xml/test/AllTypesDU.silecsdeploy b/silecs-codegen/src/xml/test/AllTypesDU.silecsdeploy index d0ed2d44065fd5b00326c3ec8f0c068fd7f26364..ccf5e18e1095386cfcecb0997ac38e3aa8474075 100644 --- a/silecs-codegen/src/xml/test/AllTypesDU.silecsdeploy +++ b/silecs-codegen/src/xml/test/AllTypesDU.silecsdeploy @@ -37,14 +37,14 @@ </Controller> <Controller host-name="Virtual_SiemensDevice"> - <PC-Controller model="S7_virtual_controller" system="S7 virtual controller" protocol="DEVICE_MODE" base-address="0"> + <PC-Controller model="Linux_x64" system="S7 virtual controller" protocol="DEVICE_MODE" base-address="0"> <Device silecs-design-ref="AllTypes" silecs-device-label="testDevice1" /> <Device silecs-design-ref="AllTypes" silecs-device-label="testDevice2" /> </PC-Controller> </Controller> <Controller host-name="Virtual_SiemensBlock"> - <PC-Controller model="S7_virtual_controller" system="S7 virtual controller" protocol="BLOCK_MODE" base-address="0"> + <PC-Controller model="Linux_x64" system="S7 virtual controller" protocol="BLOCK_MODE" base-address="0"> <Device silecs-design-ref="AllTypes" silecs-device-label="testDevice1" /> <Device silecs-design-ref="AllTypes" silecs-device-label="testDevice2" /> </PC-Controller> diff --git a/silecs-codegen/src/xml/virtualS7Template.py b/silecs-codegen/src/xml/virtualS7Template.py index abdd3fadd84c5d1ed104a260c58e7721437e8978..88903d072ae4562a3216e8adc83397a2b16eb6c8 100644 --- a/silecs-codegen/src/xml/virtualS7Template.py +++ b/silecs-codegen/src/xml/virtualS7Template.py @@ -14,7 +14,11 @@ # 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 +# Author: F.Locci/ BE-CO +# Date: August 2012 +# Last modification: Jannuary 2015 +# # Description: # This module implement the methods to build each components of the sources. # A component source consists of one 'parameterizable' text that can @@ -29,26 +33,26 @@ import iecommon # Hash-Table whichRegisterFormat = { - 'uint8' : 'uint8_t', - 'int8' : 'int8_t', - 'uint16' : 'uint16_t', - 'int16' : 'int16_t', - 'uint32' : 'uint32_t', - 'int32' : 'int32_t', - 'float32' : 'float', - 'uint64' : 'uint64_t', - 'int64' : 'int64_t', + 'uint8' : 'uint8_t', + 'int8' : 'int8_t', + 'uint16' : 'uint16_t', + 'int16' : 'int16_t', + 'uint32' : 'uint32_t', + 'int32' : 'int32_t', + 'float32' : 'float', + 'uint64' : 'uint64_t', + 'int64' : 'int64_t', 'string' : 'string', - 'float64' : 'double', - 'date' : 'double', - 'char' :'int8_t', - 'byte' :'uint8_t', - 'word' :'uint16_t', - 'dword' :'uint32_t', - 'int' :'int16_t', - 'dint' :'int32_t', - 'real' :'float', - 'dt' :'double' + 'float64' : 'double', + 'date' : 'double', + 'char' :'int8_t', + 'byte' :'uint8_t', + 'word' :'uint16_t', + 'dword' :'uint32_t', + 'int' :'int16_t', + 'dint' :'int32_t', + 'real' :'float', + 'dt' :'double' } #========================================================================= @@ -58,20 +62,20 @@ whichRegisterFormat = { duDesignInclude = """#include "%s_%s.h" """ -duConstructor = """DeployUnit() : SilecsServer::DeployUnit("%s", SilecsServer::S7Protocol, SilecsServer::%s, %s) +duConstructor = """DeployUnit() : SilecsServer::DeployUnit("%s", "%s", SilecsServer::S7Protocol, SilecsServer::%s, %s) """ -duDesignAlloc = """ mapDesigns_["%s"] = new %s_%s::Design(); +duDesignAlloc = """ mapDesigns_["%s"] = new %s_%s::Design(); """ -duDesignDelete = """ delete mapDesigns_["%s"]; +duDesignDelete = """ delete mapDesigns_["%s"]; """ -duDesignGet = """ %s_%s::Design* get%s() - { - return dynamic_cast<%s_%s::Design*>(mapDesigns_["%s"]); - } - +duDesignGet = """ %s_%s::Design* get%s() + { + return dynamic_cast<%s_%s::Design*>(mapDesigns_["%s"]); + } + """ duHeader = """ @@ -91,19 +95,19 @@ duHeader = """ #include <silecs-virtual-controller/interface/Design.h> %s -namespace %s +namespace %s_%s { class DeployUnit : public SilecsServer::DeployUnit { public: - %s { - %s } + %s { + %s } ~DeployUnit() { - %s } + %s } %s}; @@ -112,143 +116,107 @@ public: #endif """ -mainCode = """ -#include <stdio.h> -#include <stdlib.h> -#include <cstring> -#include <iostream> - -#include <silecs-virtual-controller/core/SilecsSnap7Server.h> -#include "%s.h" - -class UserSnap7Server : public SilecsServer::SilecsSnap7Server -{ -public: - UserSnap7Server(%s::DeployUnit* du) : SilecsSnap7Server(du, true) {} - virtual ~UserSnap7Server() {} - - virtual void userFunction() +#========================================================================= +# Virtual S7 CLASS template +#========================================================================= +classScalarGetSet = """ + /*! + * \\brief Get %s register. + * \\return value. + */ + %s get%s() const { - // Implement the specific process control here! - // Look at SILECS Wikis: 'Create a virtual controller' chapter + return structData_.%s; } -}; -int main(int argc, char*argv[]) -{ - %s::DeployUnit du; - UserSnap7Server server(&du); - if (server.startServer() < 0) + /*! + * \\brief Set %s register. + * \\param value to be set. + */ + void set%s(%s value) { - std::cout << "Failed to start the VC server: " << du.getName() << std::endl; - return -1; + structData_.%s = value; } - return 0; -} """ +classArrayGetSet = """ + /*! + * \\brief Get array %s register. + * \\return value. + */ + void get%s(%s* value) const + { + memcpy(value, &structData_.%s, %sDim1_ * %sDim2_ * sizeof(%s)); + } -#========================================================================= -# Virtual S7 CLASS template -#========================================================================= -classScalarGetSet = """ - /*! - * \\brief Get %s register. - * \\return value. - */ - %s get%s() const - { - return structData_.%s; - } - - /*! - * \\brief Set %s register. - * \\param value to be set. - */ - void set%s(%s value) - { - structData_.%s = value; - } + /*! + * \\brief Set array %s register. + * \\param value to be set. + */ + void set%s(%s* value) + { + memcpy(&structData_.%s, value, %sDim1_ * %sDim2_ * sizeof(%s)); + } """ -classArrayGetSet = """ - /*! - * \\brief Get array %s register. - * \\return value. - */ - void get%s(%s* value) const - { - memcpy(value, &structData_.%s, %sDim1_ * %sDim2_ * sizeof(%s)); - } - - /*! - * \\brief Set array %s register. - * \\param value to be set. - */ - void set%s(%s* value) - { - memcpy(&structData_.%s, value, %sDim1_ * %sDim2_ * sizeof(%s)); - } -""" +classScalarStringGetSet = """ + /*! + * \\brief Get %s register. + * \\return value. + */ + std::string get%s() const + { + size_t len = (size_t)structData_.%s[1]; + return std::string((char*)&(structData_.%s[2]), len); + } -classScalarStringGetSet = """ - /*! - * \\brief Get %s register. - * \\return value. - */ - std::string get%s() const - { - size_t len = (size_t)structData_.%s[1]; - return std::string((char*)&(structData_.%s[2]), len); - } - - /*! - * \\brief Set %s register. - * \\param value to be set. - */ - void set%s(const std::string &value) - { - size_t len = (value.length() < %sLen_) ? value.length() : %sLen_; - memcpy((char*)&(structData_.%s[2]), value.c_str(), len); - structData_.%s[0] = char(0); - structData_.%s[1] = char(len); - } + /*! + * \\brief Set %s register. + * \\param value to be set. + */ + void set%s(const std::string &value) + { + size_t len = (value.length() < %sLen_) ? value.length() : %sLen_; + memcpy((char*)&(structData_.%s[2]), value.c_str(), len); + structData_.%s[0] = char(0); + structData_.%s[1] = char(len); + } """ -classArrayStringGetSet = """ - /*! - * \\brief Get std::string %s register. - * \\param value buffer where the value will be stored. - */ - void get%s(std::string* value) const - { - for (std::size_t i = 0; i < %sDim1_; i++) - { - size_t len = (size_t)structData_.%s[i][1]; - value[i].assign(&(structData_.%s[i][2]), len); - } - } - - /*! - * \\brief Set std::string %s register. - * \\param value to be set. - */ - void set%s(std::string* value) - { - for (std::size_t i = 0; i < %sDim1_; i++) - { - size_t len = (value[i].length() < %sLen_) ? value[i].length() : %sLen_; - memcpy(&(structData_.%s[i][2]), value[i].c_str(), len); - structData_.%s[i][0] = char(0); - structData_.%s[i][1] = char(len); - } - } +classArrayStringGetSet = """ + /*! + * \\brief Get std::string %s register. + * \\param value buffer where the value will be stored. + */ + void get%s(std::string* value) const + { + for (std::size_t i = 0; i < %sDim1_; i++) + { + size_t len = (size_t)structData_.%s[i][1]; + value[i].assign(&(structData_.%s[i][2]), len); + } + } + + /*! + * \\brief Set std::string %s register. + * \\param value to be set. + */ + void set%s(std::string* value) + { + for (std::size_t i = 0; i < %sDim1_; i++) + { + size_t len = (value[i].length() < %sLen_) ? value[i].length() : %sLen_; + memcpy(&(structData_.%s[i][2]), value[i].c_str(), len); + structData_.%s[i][0] = char(0); + structData_.%s[i][1] = char(len); + } + } """ -classHeaderInit = """ set_version("%s"); - set_checksum(%s); - set_user("%s"); - set_date(0.0);""" +classHeaderInit = """ set_version("%s"); + set_checksum(%s); + set_user("%s"); + set_date(0.0);""" classBlock = """ class %s : public SilecsServer::Block @@ -266,22 +234,22 @@ public: { } %s - virtual inline size_t getSize() const - { - return sizeof(structData_); - } + virtual inline size_t getSize() const + { + return sizeof(structData_); + } - virtual void getData(unsigned char * data) const - { - memcpy(data, &structData_, this->getSize()); - } + virtual void getData(unsigned char * data) const + { + memcpy(data, &structData_, this->getSize()); + } - virtual void setData(unsigned char * data) - { - memcpy(&structData_, data, this->getSize()); - } + virtual void setData(unsigned char * data) + { + memcpy(&structData_, data, this->getSize()); + } - virtual inline size_t getOffset() const { return %s; } + virtual inline size_t getOffset() const { return %s; } %s private: @@ -292,29 +260,29 @@ private: %s } structData_; #pragma pack(pop) - + }; """ -classArrayDim = """ static const std::size_t %sDim1_ = %s; - static const std::size_t %sDim2_ = %s; +classArrayDim = """ static const std::size_t %sDim1_ = %s; + static const std::size_t %sDim2_ = %s; """ -classStringLen = """ static const std::size_t %sLen_ = %s; +classStringLen = """ static const std::size_t %sLen_ = %s; """ classCreateBlock = """ - blockMap_["%s:%s"] = new %s();""" + blockMap_["%s:%s"] = new %s();""" classDeleteBlock = """ - delete (blockMap_["%s:%s"]);""" + delete (blockMap_["%s:%s"]);""" classDevice = """ class Device : public SilecsServer::Device { public: Device(const std::string& label, size_t number):SilecsServer::Device(label, number) - { %s + { %s } ~Device() @@ -323,10 +291,10 @@ public: };""" classCreateDevice = """ - deviceMap_["%s:%s"] = new Device("%s:%s", %s);""" + deviceMap_["%s:%s"] = new Device("%s:%s", %s);""" classDeleteDevice = """ - delete(deviceMap_["%s:%s"]);""" + delete(deviceMap_["%s:%s"]);""" classDesign = """ class Design : public SilecsServer::Design @@ -392,19 +360,16 @@ class Design; # Virtual S7 generation Sub-function #========================================================================= -# SERVER MAIN code generation --------------------------------------------- -def vs7MainCode(deployName): - return mainCode %(deployName, deployName, deployName) - # DEPLOY-UNIT generation ------------------------------------------------- -def vs7DuHeader(deployName, duConstructor, designIncludes, designAllocs, designDeletes, designGetters): - return duHeader %(deployName.upper(), deployName.upper(), designIncludes, deployName, duConstructor, designAllocs, designDeletes, designGetters) +def vs7DuHeader(deployName, deployVersion, duConstructor, designIncludes, designAllocs, designDeletes, designGetters): + deployVersion = deployVersion.replace(".", "_") + return duHeader %(deployName.upper(), deployName.upper(), designIncludes, deployName, deployVersion, duConstructor, designAllocs, designDeletes, designGetters) def vs7DuDesignInclude(designName, designVersion): return duDesignInclude %(designName, designVersion) -def vs7DuConstructor(deployName, mode, baseAddr): - return duConstructor %(deployName, mode, baseAddr) +def vs7DuConstructor(deployName, deployVersion, mode, baseAddr): + return duConstructor %(deployName, deployVersion, mode, baseAddr) def vs7DuDesignAlloc(designName, designVersion): designVersion = designVersion.replace(".", "_") @@ -437,7 +402,7 @@ def vs7ClassBlock(framework, owner, checksum, className, blockName, regsCode, bl def vs7ClassGetSet(regName, regFormat, regDim1, regDim2, regLen): RegName = iecommon.capitalizeString(regName) regFormat = whichRegisterFormat[regFormat] - if regDim1 == 1 and regDim2 == 1: # scalar + if regDim1 == 1 and regDim2 == 1: # scalar if regFormat == 'string': return classScalarStringGetSet %(regName, RegName, regName, regName, regName, RegName, regName, regName, regName, regName, regName) else: @@ -450,7 +415,7 @@ def vs7ClassGetSet(regName, regFormat, regDim1, regDim2, regLen): def vs7ClassDimension(regName, regFormat, regDim1, regDim2, regLen): dimCodeString = '' - if regDim1 > 1 or regDim2 > 1: # not a scalar ==> define dimension constants + if regDim1 > 1 or regDim2 > 1: # not a scalar ==> define dimension constants dimCodeString += classArrayDim %(regName, regDim1, regName, regDim2) if regFormat == 'string': dimCodeString += classStringLen %(regName, regLen) @@ -460,7 +425,7 @@ def vs7ClassDummyRegister(curRegAddress, prevRegMemSize, regMemSize, dummyIndex) dummyCodeString = '' if curRegAddress % 2 != 0: #is current register address an odd address? if prevRegMemSize > 1 or regMemSize > 1: #only 8bit scalar (not following array) uses 8bit alignment! - dummyCodeString = " uint8_t dummy%s;\n" %(dummyIndex) + dummyCodeString = " uint8_t dummy%s;\n" %(dummyIndex) return dummyCodeString def vs7ClassDataRegister(regName, regFormat, regDim1, regDim2, regLen): @@ -469,7 +434,7 @@ def vs7ClassDataRegister(regName, regFormat, regDim1, regDim2, regLen): if regFormat == 'string': length = "[%sLen_+2]" %(regName) regFormat = 'char' - dataCodeString = " %s %s" %(regFormat, regName) + dataCodeString = " %s %s" %(regFormat, regName) if regDim1 > 1 or regDim2 > 1: # not scalar dataCodeString += "[%sDim1_]" %(regName) if regDim2 > 1: # not scalar diff --git a/silecs-model/src/xml/DeploySchema.xsd b/silecs-model/src/xml/DeploySchema.xsd index 7e027cfaddd0eb425eafa1f88ef3e0bf7bd5370a..d1789ea44aa14218a90d2d565dc0f73ac8d50c99 100644 --- a/silecs-model/src/xml/DeploySchema.xsd +++ b/silecs-model/src/xml/DeploySchema.xsd @@ -243,8 +243,7 @@ </xs:simpleType> <xs:simpleType name="PCSystemType"> <xs:restriction base="xs:string"> - <xs:enumeration value="S7 virtual controller" /> - <xs:enumeration value="MODBUS virtual controller" /> + <xs:enumeration value="S7 virtual controller"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="NISystemType"> @@ -570,8 +569,8 @@ <xs:attribute name="model" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> - <xs:enumeration value="S7_virtual_controller" /> - <xs:enumeration value="MODBUS_virtual_controller" /> + <xs:enumeration value="Linux_x64" /> + <xs:enumeration value="Linux_i386" /> </xs:restriction> </xs:simpleType> </xs:attribute>