blob: a0869d715efb0cf0120cf87c2b1baa23345d422e [file] [log] [blame]
/**
********************************************************************************
* 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);
}
}
}