/** | |
******************************************************************************** | |
* Copyright (c) 2017 Robert Bosch GmbH and others. | |
* | |
* This program and the accompanying materials are made | |
* available under the terms of the Eclipse Public License 2.0 | |
* which is available at https://www.eclipse.org/legal/epl-2.0/ | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
* Contributors: | |
* Robert Bosch GmbH - initial API and implementation | |
******************************************************************************** | |
*/ | |
package org.eclipse.app4mc.sca2amalthea.llvm.headless; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.List; | |
import java.util.Locale; | |
import java.util.Map; | |
import org.eclipse.app4mc.amalthea.model.Amalthea; | |
import org.eclipse.app4mc.sca.amalthea.serializer.AMALTHEAResourceSerializer; | |
import org.eclipse.app4mc.sca.logging.manager.LogFactory.Severity; | |
import org.eclipse.app4mc.sca.logging.manager.Logmanager; | |
import org.eclipse.app4mc.sca.logging.util.LogUtil; | |
import org.eclipse.app4mc.sca.scheduling.loader.model.OSConfModel; | |
import org.eclipse.app4mc.sca.scheduling.loader.model.SchedulingInformationLoader; | |
import org.eclipse.app4mc.sca.util.App4mcToolConstants; | |
import org.eclipse.app4mc.sca.util.util.SCAToolsDirectoryType; | |
import org.eclipse.app4mc.sca.util.util.SCAUtils; | |
import org.eclipse.app4mc.sca.util.workspaces.WorkspaceOperations; | |
import org.eclipse.app4mc.sca2amalthea.exporter.SCAToAmaltheaExporter; | |
import org.eclipse.app4mc.sca2amalthea.exporter.locks.LockDefinition; | |
import org.eclipse.app4mc.sca2amalthea.exporter.util.LLVMLogUtil; | |
import org.eclipse.app4mc.sca2amalthea.ir.loader.SCAIRLoader; | |
import org.eclipse.app4mc.sca2amalthea.llvm.Activator; | |
import org.eclipse.app4mc.sca2amalthea.llvm.srcfiles.support.BuildCommandLogFileParser; | |
import org.eclipse.app4mc.sca2amalthea.llvm.srcfiles.support.PathsToListConverter; | |
import org.eclipse.app4mc.sca2amalthea.llvm.starter.GenerateTraverseAstOutput; | |
import org.eclipse.app4mc.sca2amalthea.llvm.starter.LLVMStarterProperties; | |
import org.eclipse.app4mc.sca2amalthea.llvm.util.ManipulateAmalthea; | |
import org.eclipse.app4mc.sca2amalthea.scairmodelenricher.SCAIRModelEnrichmentUtils; | |
import org.eclipse.app4mc.sca2amalthea.serialization.SCAResource; | |
import org.eclipse.app4mc.sca2amalthea.utils.UtilityForProcessHandling; | |
import org.eclipse.app4mc.sca2amalthea.utils.constants.SCA2AmaltheaConstants; | |
import org.eclipse.emf.common.util.URI; | |
/** | |
*/ | |
public class GenerateAmaltheaModelFromLLVM { | |
private final SCA2AMALTHEAStarterProperties sca2amProperties; | |
/** | |
* Generates amalthea model from the given properties. The given properties are used to populate the ast model and | |
* from the ast model the intermediate representation. The intermdediate representation is inturn used to generate the | |
* amalthea model | |
* | |
* @param llvmProperties {@link LLVMStarterProperties} | |
*/ | |
public GenerateAmaltheaModelFromLLVM(final SCA2AMALTHEAStarterProperties llvmProperties) { | |
super(); | |
this.sca2amProperties = llvmProperties; | |
} | |
/** | |
* @param llvmProperties LLVM properties | |
* @param fcbcInFo given FC BC infos | |
*/ | |
public GenerateAmaltheaModelFromLLVM(final SCA2AMALTHEAStarterProperties llvmProperties, | |
final Map<String, Map.Entry<String, String>> fcbcInFo) { | |
this(llvmProperties); | |
} | |
/** | |
* @param projectDir The project dir PVER | |
* @param outDir The output directory where the amalthea model representation is being generation | |
* @param astParser The ast parser location | |
* @param taskInfoFile Task info file | |
* @param hDirList H files directory | |
* @param buildLogFile Build log file | |
* @param lockinfoFile Lock Information | |
* @param isStructMemberEnabled boolean giving the information if the struct members should be present in the model or | |
* not | |
* @param componentModelFcBc boolean value which tells whether the component model is fc/bc based or c/h file based. | |
*/ | |
public GenerateAmaltheaModelFromLLVM(final String projectDir, final String outDir, final String astParser, | |
final String taskInfoFile, final String hDirList, final String buildLogFile, final String lockinfoFile,final boolean isStructMemberEnabled) { | |
this.sca2amProperties = new SCA2AMALTHEAStarterProperties(astParser, outDir, taskInfoFile, 8, projectDir, hDirList, | |
buildLogFile, lockinfoFile, isStructMemberEnabled); | |
} | |
/** | |
* @throws IOException IOException | |
* @throws InterruptedException InterruptedException | |
* @return int status of the amalthea model generation | |
*/ | |
public int run() throws IOException, InterruptedException { | |
int returnCode = 0; | |
long startTime = 0; | |
try { | |
validateConsolidatedLLVMOptions(); | |
} | |
catch (IllegalArgumentException e) { | |
Logmanager.getInstance().logException(getClass(), e, Activator.PLUGIN_ID); | |
LogUtil.log(LLVMLogUtil.LOG_MSG_ID, Severity.ERROR, | |
"Aborting the amalthea generation, see exception log: " + e.getMessage(), this.getClass(), | |
Activator.PLUGIN_ID); | |
returnCode = 1; | |
return returnCode; | |
} | |
try { | |
if (returnCode == 0) { | |
applyFallBackStrategy(); | |
parseBlogAndHDirListOptions(); | |
startTime = System.currentTimeMillis(); | |
LogUtil.log(LLVMLogUtil.LOG_MSG_ID, Severity.INFO, | |
"Starting sca2amalthea export... [start time " + startTime + "]", this.getClass(), Activator.PLUGIN_ID); | |
GenerateTraverseAstOutput llvmStarter = | |
new GenerateTraverseAstOutput(this.sca2amProperties.getLlvmStarterProperties()); | |
llvmStarter.runTraverseAst(); | |
} | |
} | |
catch (Exception possibleException) { | |
LogUtil.logException(LLVMLogUtil.LOG_MSG_ID, possibleException.getClass(), possibleException, | |
Activator.PLUGIN_ID); | |
possibleException.printStackTrace(); | |
returnCode = 1; | |
} | |
if ((returnCode == 0) && (UtilityForProcessHandling.getCurrentRunningProcess().exitValue() == 0)) { | |
LogUtil.log(LLVMLogUtil.LOG_MSG_ID, Severity.INFO, | |
"Transforming the intermediate representation to amalthea model", this.getClass(), Activator.PLUGIN_ID); | |
try { | |
convertXMLToAmaltheaModel(); | |
} | |
catch (Exception possibleException) { | |
LogUtil.logException(LLVMLogUtil.LOG_MSG_ID, possibleException.getClass(), possibleException, | |
Activator.PLUGIN_ID); | |
returnCode = 1; | |
} | |
long duration = (System.currentTimeMillis() - startTime) / 1000; // in seconds | |
LogUtil.log(LLVMLogUtil.LOG_MSG_ID, Severity.INFO, | |
"Export of AMALTHEA model completed. [duration=" + duration + " seconds]", this.getClass(), | |
Activator.PLUGIN_ID); | |
WorkspaceOperations.refreshWorkspace(this.sca2amProperties.getcProjectPath(), "_bin/sca2amalthea"); | |
WorkspaceOperations.refreshWorkspace(this.sca2amProperties.getcProjectPath(), "_log/sca2amalthea"); | |
WorkspaceOperations.refreshWorkspace(this.sca2amProperties.getcProjectPath(), "_gen/sca2amalthea"); | |
} | |
else { | |
returnCode = 1; | |
LogUtil.log(LLVMLogUtil.LOG_MSG_ID, Severity.INFO, "AMALTHEA model generation aborted.", this.getClass(), | |
Activator.PLUGIN_ID); | |
} | |
return returnCode; | |
} | |
/** | |
* @throws IllegalArgumentException if a given path of the properties does not exist | |
*/ | |
private void validateConsolidatedLLVMOptions() throws IllegalArgumentException { | |
if (!new File(this.sca2amProperties.getcProjectPath()).exists()) { | |
throw new IllegalArgumentException( | |
"The project path provided is not valid: " + this.sca2amProperties.getcProjectPath()); | |
} | |
if ((this.sca2amProperties.getTraverseAstFile() != null) && !this.sca2amProperties.getTraverseAstFile().isEmpty() && | |
!new File(this.sca2amProperties.getTraverseAstFile()).exists()) { | |
throw new IllegalArgumentException( | |
"The traverse ast path provided is not valid: " + this.sca2amProperties.getTraverseAstFile()); | |
} | |
if ((this.sca2amProperties.getOutPutPath() != null) && !this.sca2amProperties.getOutPutPath().isEmpty() && | |
!this.sca2amProperties.getOutPutPath() | |
.equals(SCA2AmaltheaConstants.getPreferenceStore().getDefaultString(SCA2AmaltheaConstants.OUTPUT_PATH))) { | |
checkFilePathExists(this.sca2amProperties.getOutPutPath(), "output path"); | |
} | |
checkFilePathExists(this.sca2amProperties.getTaskListFile(), "tasklist file path"); | |
checkFilePathExists(this.sca2amProperties.getBuildLogFile(), "build log file path"); | |
if ((this.sca2amProperties.gethDirFilePath() != null) && !this.sca2amProperties.gethDirFilePath().isEmpty()) { | |
String[] paths = this.sca2amProperties.gethDirFilePath().split(";"); | |
for (String s : paths) { | |
checkFilePathExists(s, "h dir path"); | |
} | |
} | |
checkFilePathExists(this.sca2amProperties.getLockinfoFile(), "lock info file path"); | |
} | |
/** | |
* @param filePath to be checked | |
* @param filePathName description | |
*/ | |
private void checkFilePathExists(final String filePath, final String filePathName) { | |
if ((filePath != null) && !filePath.isEmpty() && !new File(filePath).exists()) { | |
throw new IllegalArgumentException("The " + filePathName + " provided is not valid: " + filePath); | |
} | |
} | |
private void convertXMLToAmaltheaModel() { | |
OSConfModel osConfModel = null; | |
URI createURI = | |
URI.createFileURI(this.sca2amProperties.getLlvmStarterProperties().getGenDirectory() + "/XMLCalltree.xml"); | |
SCAResource resource = new SCAIRLoader().load(createURI); | |
if ((this.sca2amProperties.getTaskListFile() != null) && !this.sca2amProperties.getTaskListFile().isEmpty()) { | |
SchedulingInformationLoader schedInfoLoader = new SchedulingInformationLoader(); | |
osConfModel = schedInfoLoader.getTasksInformation(this.sca2amProperties.getTaskListFile()); | |
if (osConfModel != null) { | |
SCAIRModelEnrichmentUtils.markTasksIsrsRunnablesInModel(resource, osConfModel.getTaskISRInfoAsMap()); | |
} | |
} | |
LockDefinition lockDefinition=null; | |
if ((this.sca2amProperties.getLockinfoFile() != null) && !this.sca2amProperties.getLockinfoFile().isEmpty()) { | |
lockDefinition = new LockDefinition(this.sca2amProperties.getLockinfoFile()); | |
lockDefinition.readLockDefinitionFromFile(); | |
} | |
Amalthea amaltheaModel = new SCAToAmaltheaExporter().amaltheaTransformation(resource, lockDefinition, osConfModel); | |
ManipulateAmalthea.markIniTasksInAmaltheaModel(amaltheaModel, osConfModel); | |
ManipulateAmalthea manipulatorCaller = new ManipulateAmalthea(); | |
manipulatorCaller.manipulates(this.sca2amProperties, amaltheaModel); | |
AMALTHEAResourceSerializer amResSerializer = new AMALTHEAResourceSerializer(); | |
amResSerializer.saveAmaltheaModel(this.sca2amProperties.getBinDirectory() + "/amaltheaModelFromLLVM", | |
amaltheaModel); | |
} | |
/** | |
* Method that provides the fall back strategy if the user has not provided the necessary parameters | |
*/ | |
private void applyFallBackStrategy() { | |
if ((this.sca2amProperties.getOutPutPath() == null) || this.sca2amProperties.getOutPutPath().isEmpty() || | |
this.sca2amProperties.getOutPutPath() | |
.equals(SCA2AmaltheaConstants.getPreferenceStore().getDefaultString(SCA2AmaltheaConstants.OUTPUT_PATH))) { | |
this.sca2amProperties.setBinDirectory(SCAUtils.getSCARootDirectory( | |
this.sca2amProperties.getcProjectPath(), SCAToolsDirectoryType.SCA_BIN, | |
App4mcToolConstants.SCA2AMALTHEA_TOOL_ID.toLowerCase(Locale.getDefault()))); | |
this.sca2amProperties.getLlvmStarterProperties() | |
.setGenDirectory(SCAUtils.getSCARootDirectory(this.sca2amProperties.getcProjectPath(), | |
SCAToolsDirectoryType.SCA_GEN, | |
App4mcToolConstants.SCA2AMALTHEA_TOOL_ID.toLowerCase(Locale.getDefault()))); | |
this.sca2amProperties.getLlvmStarterProperties() | |
.setLogDirecotry(SCAUtils.getSCARootDirectory(this.sca2amProperties.getcProjectPath(), | |
SCAToolsDirectoryType.SCA_LOG, | |
App4mcToolConstants.SCA2AMALTHEA_TOOL_ID.toLowerCase(Locale.getDefault()))); | |
} | |
else { | |
this.sca2amProperties.setBinDirectory(this.sca2amProperties.getOutPutPath()); | |
this.sca2amProperties.getLlvmStarterProperties().setGenDirectory(this.sca2amProperties.getOutPutPath()); | |
this.sca2amProperties.getLlvmStarterProperties().setLogDirecotry(this.sca2amProperties.getOutPutPath()); | |
} | |
} | |
/** | |
* This method checks if the user has provided the build_cmd.log file and the header directories. If so it reads them | |
* and generates the clist and hlist and if not it uses the MDF to get the clist and hlist. | |
*/ | |
private void parseBlogAndHDirListOptions() { | |
List<String> hdList; | |
List<String> cList; | |
if ((this.sca2amProperties.getBuildLogFile() != null) && !this.sca2amProperties.getBuildLogFile().isEmpty()) { | |
BuildCommandLogFileParser cListProvider = new BuildCommandLogFileParser(this.sca2amProperties.getBuildLogFile(), | |
this.sca2amProperties.getcProjectPath()); | |
cList = cListProvider.generateSourceFileList(); | |
hdList = cListProvider.generateHashDefineList(); | |
this.sca2amProperties.setcFilesList(cList); | |
this.sca2amProperties.setHashDefineList(hdList); | |
} | |
List<String> hList; | |
if ((this.sca2amProperties.gethDirFilePath() != null) && !this.sca2amProperties.gethDirFilePath().isEmpty()) { | |
String hFilePathList = this.sca2amProperties.gethDirFilePath(); | |
// create h file list | |
hList = new PathsToListConverter(hFilePathList, ".h").generateSourceFileList(); | |
this.sca2amProperties.sethFilesList(hList); | |
} | |
} | |
} |