#!/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 os import sys import time import zlib import glob import re import datetime import socket import iecommon import fesaTemplates import iefiles from iecommon import * from model.Register import DesignRegister from model.Block import DesignBlock from model.Class import DesignClass import libxml2 def findBlockServerSetActionName(fesaRoot, propName): properties = fesaRoot.xpathEval("/equipment-model/interface/device-interface/*/*[@name='" + propName + "']") for property in properties: return property.xpathEval("set-action/server-action-ref")[0].prop("server-action-name-ref") raise Exception("Error: Server Action for Property '" + propName + "' not found") #------------------------------------------------------------------------- # Generates the H source file containing general methods # to synchronise the FESA fields and related PLC registers # of the FESA server #------------------------------------------------------------------------- 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(): if block.isAcquisition(): source += fesaTemplates.genHBlock('RO', block.name,block.getFesaName() ) elif block.isCommand(): source += fesaTemplates.genHBlock('WO', block.name,block.getFesaName()) else: # Setting source += fesaTemplates.genHBlock('RW', block.name,block.getFesaName()) source += fesaTemplates.genHBottom(className) for block in designClass.getDesignBlocks(): source += fesaTemplates.genHDeclBlocks(block.name) source += fesaTemplates.genHClosing(className) # Create output directory if necessary if not os.path.exists(sourcePath): os.makedirs(sourcePath) iecommon.logDebug("Create directory %s" %sourcePath, logTopics) # Write to file and save sourceFile = sourcePath + "/"+ className + ".h" iecommon.logInfo("Generate header file: " + sourceFile, logTopics) fdesc = open(sourceFile, "w") fdesc.write(source) fdesc.close() iecommon.logInfo('Header file for '+className+' generated successfully', logTopics) #------------------------------------------------------------------------- # Generates the C++ source file containing general # methods to synchronise the FESA fields and related PLC # registers of the FESA server #------------------------------------------------------------------------- def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): designClass = DesignClass.getDesignClassFromRootNode(silecsRoot) finalSource = fesaTemplates.genCTop(className) blockList = designClass.getDesignBlocks() for block in blockList: finalSource += fesaTemplates.genCGlobal(className, block.name) finalSource += fesaTemplates.genCPart1(className) for block in blockList: 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.genCPart4(className) for block in blockList: if block.isReadable(): finalSource += fesaTemplates.genCCommonGet(block.name,className) finalSource += '\n' finalSource += fesaTemplates.cRecv for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCGetStringReg(register) elif register.valueType == 'stringArray': finalSource += fesaTemplates.genCGetStringArrayReg(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.genCGetScalarReg(register) elif register.valueType == 'array': finalSource += fesaTemplates.genCGetArrayReg(register) elif register.valueType == 'array2D': finalSource += fesaTemplates.genCGetArray2DReg(register) finalSource += '\n }\n' if block.isWritable(): finalSource += fesaTemplates.genCCommonSet(block.name,className) for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCSetStringReg(register) elif register.valueType == 'stringArray': finalSource += fesaTemplates.genCSetStringArrayReg(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.genCSetScalarReg(register) elif register.valueType == 'array': finalSource += fesaTemplates.genCSetArrayReg(register) elif register.valueType == 'array2D': finalSource += fesaTemplates.genCSetArray2DReg(register) finalSource += fesaTemplates.cSend finalSource += ' }\n' finalSource += fesaTemplates.genCDatatypeSet(block.name,block.getFesaName(), className) for register in block.getDesignRegisters(): if register.valueType == 'string': finalSource += fesaTemplates.genCSetStringRegData(register) elif register.valueType == 'stringArray': finalSource += fesaTemplates.genCSetStringArrayRegData(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 == 'array2D': finalSource += fesaTemplates.genCSetArray2DRegData(register) elif register.valueType == 'array': finalSource += fesaTemplates.genCSetArrayRegData(register) elif register.valueType == 'scalar': finalSource += fesaTemplates.genCSetScalarRegData(register) finalSource += fesaTemplates.cSend finalSource += '\n }\n' # closing bracket for block finalSource += '\n}\n' # closing bracket for class # Write to file and save sourceFile = sourcePath + "/" + className + ".cpp" iecommon.logInfo("Generate source file: " + sourceFile, logTopics) fdesc = open(sourceFile, "w") fdesc.write(finalSource) fdesc.close() iecommon.logInfo('Source file for '+className+' generated successfully', logTopics) def genCppFiles(className, workspacePath, silecsDesignFilePath,logTopics={'errorlog': True}): generatedCodeFolder = workspacePath + '/' + className + '/generated-silecs/cpp/' + className + '/GeneratedCode' generatedCodeFolderNorm = os.path.normpath(generatedCodeFolder) iecommon.logInfo("generated code folder:" + generatedCodeFolderNorm,logTopics) if not os.path.exists(generatedCodeFolderNorm ): os.makedirs(generatedCodeFolderNorm) silecsDesignFilePath = iefiles.getSilecsDesignFilePath(workspacePath,className) fesaDesignFilePath = workspacePath + "/" + className + "/src/" + className + ".design" silecsRoot = libxml2.parseFile(silecsDesignFilePath) fesaRoot = libxml2.parseFile(fesaDesignFilePath) genHSource(className, silecsRoot, fesaRoot, generatedCodeFolderNorm,logTopics) genCppSource(className, silecsRoot, fesaRoot, generatedCodeFolderNorm,logTopics)