From 10a6f0ee35d01ddeb53a47c1dbdea06ecbcfb3f2 Mon Sep 17 00:00:00 2001
From: aschwinn <al.schwinn@gsi.de>
Date: Mon, 24 Jul 2017 11:33:35 +0200
Subject: [PATCH] [SIL-231] Generate C++ code for virtual SIMATIC S7 controller

---
 silecs-codegen/src/xml/genparam.py            |   8 +-
 silecs-codegen/src/xml/genplcsrc.py           | 217 +++++++++--
 silecs-codegen/src/xml/iefiles.py             |  21 ++
 .../src/xml/model/Deploy/Controller.py        |  18 +-
 .../src/xml/test/AllTypesDU.silecsdeploy      |   4 +-
 silecs-codegen/src/xml/virtualS7Template.py   | 341 ++++++++----------
 silecs-model/src/xml/DeploySchema.xsd         |   7 +-
 7 files changed, 376 insertions(+), 240 deletions(-)

diff --git a/silecs-codegen/src/xml/genparam.py b/silecs-codegen/src/xml/genparam.py
index 9aa31a1..67bee41 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 3f54f47..4852296 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 32376c9..951c8cc 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 341bfa1..4f3fea1 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 d0ed2d4..ccf5e18 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 abdd3fa..88903d0 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 7e027cf..d1789ea 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>
-- 
GitLab