blob: 764d501023a653af578897eaf9f06b1c546866a5 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2018-2021 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.amalthea.converters090.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import org.eclipse.app4mc.amalthea.converters.common.ServiceConstants;
import org.eclipse.app4mc.amalthea.converters.common.base.ICache;
import org.eclipse.app4mc.amalthea.converters.common.base.IConverter;
import org.eclipse.app4mc.amalthea.converters.common.converter.AbstractConverter;
import org.eclipse.app4mc.amalthea.converters.common.utils.AmaltheaNamespaceRegistry;
import org.eclipse.app4mc.amalthea.converters.common.utils.HelperUtil;
import org.eclipse.app4mc.amalthea.converters.common.utils.ModelVersion;
import org.eclipse.app4mc.amalthea.converters090.utils.HWCacheBuilder;
import org.eclipse.app4mc.amalthea.converters090.utils.HWTransformationCache;
import org.eclipse.app4mc.util.sessionlog.SessionLogger;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* This class is responsible for converting the HW Model elements from 0.8.3 to 0.9.0 version format of AMALTHEA model
*
* @author zmeer
*
*/
@Component(
property = {
ServiceConstants.INPUT_MODEL_VERSION_PROPERTY + "=0.8.3",
ServiceConstants.OUTPUT_MODEL_VERSION_PROPERTY + "=0.9.0",
"service.ranking:Integer=90"},
service = IConverter.class)
public class HwConverter extends AbstractConverter {
private static final String AM = "am";
private static final String XSI = "xsi";
private static final String AMLT_PREFIX = "amlt:/#";
private static final String TYPE = "type";
private static final String NAME = "name";
private static final String VALUE = "value";
private static final String DEFINITION = "definition";
private static final String DEFINITIONS = "definitions";
private static final String STRUCTURES = "structures";
private static final String STRUCTURE_TYPE = "structureType";
@Reference
SessionLogger logger;
private HWTransformationCache hwTransformationCache;
@Override
@Activate
protected void activate(Map<String, Object> properties) {
super.activate(properties);
}
/*-
* As in 0.9.0, there is a major restructuring of HW data model ->
* all model files HW data is transformed at once and its content is stored only inside a single HW model
*/
@Override
public void convert(File targetFile, Map<File, Document> fileDocumentMapping, List<ICache> caches) {
logger.info("Migration from 0.8.3 to 0.9.0 : Executing HW model converter for model file : {0}",
targetFile.getName());
/*-getting the cache object */
this.hwTransformationCache = getHWTransformationCache(caches);
final Document root = fileDocumentMapping.get(targetFile);
if (root == null) return;
final Element rootElement = root.getRootElement();
Element oldHWModelElement = rootElement.getChild("hwModel");
migrateHWModel(rootElement, oldHWModelElement);
}
/**
* This method is used for the migration of HwModel element inside AMALTHEA model file.
* Contents of HwModel from 0.8.3 are extracted and are transformed into valid HwModel contents as per 0.9.0.
* <br><b>Note</b>: If multiple AMALTHEA models have HwModel elements, then their contents are extracted and and the below contents are cummilatively stored inside a first HwModel:
* <ol>
* <li>MemoryType</li>
* <li>Quartz</li>
* </ol>
*
*
* @param rootElement
* @param oldHWModelElement
*/
private void migrateHWModel(final Element rootElement, Element oldHWModelElement) {
if (oldHWModelElement == null) return;
final Element newHWModelElement = new Element("hwModel");
migrateAllMemoryTypes_modelscope(newHWModelElement);
migrateCoreTypes(oldHWModelElement, newHWModelElement);
migrateNetworkTypes(oldHWModelElement, newHWModelElement);
Element oldHWSystem = oldHWModelElement.getChild("system");
if (oldHWSystem != null) {
migrateSystem(newHWModelElement, oldHWSystem);
}
migrateLatencyAccessPath(oldHWModelElement, newHWModelElement);
int indexOf = rootElement.indexOf(oldHWModelElement);
/*-removal of 0.8.3 HWModel content from AMALTHEA model */
rootElement.removeContent(oldHWModelElement);
/*-adding newly created hwModel -> 0.9.0 compatible into the AMALTHEA model file */
rootElement.addContent(indexOf, newHWModelElement);
/*-Migrating custom properties */
migrateCustomProperties(oldHWModelElement, newHWModelElement);
}
/**
* This method is used to migrate all the MemoryType elements from 0.8.3 hwModel file to 0.9.0 hwModel
*
* <br>Before invocation of HwConverter, HwCacheBuilder is invoked and it has collected all the MemoryType objects across various HwModel's
*
* @param newHWModelElement Element. 0.9.0 compatible HwModel element
*/
private void migrateAllMemoryTypes_modelscope(Element newHWModelElement) {
Collection<Element> oldHW_MemoryType_definitions = hwTransformationCache.getOldMemoryTypesDefinitionMap().values();
for (Element oldHWModelElement : oldHW_MemoryType_definitions) {
migrateMemoryTypes(oldHWModelElement, newHWModelElement);
}
}
/**
* This method is used to migrate the LatencyAccessPath elements from 0.8.3 to 0.9.0.
*
* Equivalent element of LatencyAccessPath in 0.9.0 is : HwAccessElement.
*
* <br><b>Note:</b>For HwAccessElement :<ul>
*
* <li>source is ProcessingUnit which is containing this HwAccessElement</li>
* <li>destination is HwDestination element -> which can be either Memory or ProcessingUnit </li>
* </ul>
*
* @param oldHWModelElement Element. JDOM Element equivalent to 0.8.3 HwModel
* @param newHWModelElement Element. JDOM Element equivalent to 0.9.0 HwModel
*/
private void migrateLatencyAccessPath(Element oldHWModelElement, Element newHWModelElement) {
List<Element> oldHWAccessPaths= oldHWModelElement.getChildren("accessPaths");
for (Element oldHWAccessPath : oldHWAccessPaths) {
String oldHWAccessPath_name = oldHWAccessPath.getAttributeValue(NAME);
String oldHW_AccessPath_Type = oldHWAccessPath.getAttributeValue(TYPE, AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
if(oldHW_AccessPath_Type!=null && oldHW_AccessPath_Type.equals("am:LatencyAccessPath")) {
Entry<String, String> oldHW_Source = HelperUtil.getSingleElementsNameandTypeFromAttributeOrChildeElement("source", oldHWAccessPath);
Entry<String, String> oldHW_Target = HelperUtil.getSingleElementsNameandTypeFromAttributeOrChildeElement("target", oldHWAccessPath);
Element newHW_AccessElements=null;
if(oldHW_Source!=null) {
String oldHW_element_key = oldHW_Source.getKey();
String oldHW_element_type = oldHW_Source.getValue();
if (oldHW_element_type.equals("Core")) {
Element newHW_Core_ProcessingUnit = hwTransformationCache.getNewCoresMap().get(oldHW_element_key);
if (newHW_Core_ProcessingUnit != null) {
newHW_AccessElements = new Element("accessElements");
newHW_AccessElements.setAttribute(NAME, oldHWAccessPath_name != null ? oldHWAccessPath_name : "");
newHW_Core_ProcessingUnit.addContent(newHW_AccessElements);
}
} else {
logger.warn("Unable to migrate LatencyAccessPath from 0.8.3, as the Source type is : {0}. Migration is supported only if source element is of type Core", oldHW_element_type);
}
}
if (oldHW_Target != null) {
Element newHW_AccessElements_Destination = new Element("destination");
String oldHW_element_name = oldHW_Target.getKey();
String oldHW_element_type = oldHW_Target.getValue();
if (oldHW_element_type.equals("Memory")) {
newHW_AccessElements_Destination.setAttribute(TYPE, "am:Memory", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
newHW_AccessElements_Destination.setAttribute("href", "amlt://#"+HelperUtil.encodeNameForReference(oldHW_element_name)+"?type=Memory" );
} else if (oldHW_element_type.equals("Core")) {
newHW_AccessElements_Destination.setAttribute(TYPE, "am:ProcessingUnit", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
newHW_AccessElements_Destination.setAttribute("href", "amlt://#" + HelperUtil.encodeNameForReference(oldHW_element_name) + "?type=ProcessingUnit");
} else {
logger.warn("Unable to migrate LatencyAccessPath destination from 0.8.3 successfully, as the destination type is : {0}. Migration is supported only if target element is of type Memory or Core", oldHW_element_type);
}
if (newHW_AccessElements != null) {
newHW_AccessElements.addContent(newHW_AccessElements_Destination);
}
}
//now adding latencies
if (newHW_AccessElements != null) {
List<Element> oldHW_Latencies = oldHWAccessPath.getChildren("latencies");
for (Element oldHW_Latency : oldHW_Latencies) {
String oldHW_Latency_AccessType = oldHW_Latency.getAttributeValue("accessType");
if (oldHW_Latency_AccessType != null) {
List<Element> newHWLatencies = new ArrayList<>();
if (oldHW_Latency_AccessType.equals("R")) {
newHWLatencies.add(new Element("readLatency"));
} else if (oldHW_Latency_AccessType.equals("W")) {
newHWLatencies.add(new Element("writeLatency"));
} else if (oldHW_Latency_AccessType.equals("RW")) {
newHWLatencies.add(new Element("readLatency"));
newHWLatencies.add(new Element("writeLatency"));
} else {
continue;
}
for (Element newHW_Latency : newHWLatencies) {
/*- adding latency to HWAccessElement */
newHW_AccessElements.addContent(newHW_Latency);
String oldHW_Latency_Type = oldHW_Latency.getAttributeValue(TYPE, AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
if (oldHW_Latency_Type != null) {
if (oldHW_Latency_Type.equals("am:LatencyConstant")) {
newHW_Latency.setAttribute(TYPE, "am:LatencyConstant", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
String oldHW_Latency_Value = oldHW_Latency.getAttributeValue(VALUE);
if (oldHW_Latency_Value != null) {
newHW_Latency.setAttribute("cycles", oldHW_Latency_Value);
}
} else if (oldHW_Latency_Type.equals("am:LatencyDeviation")) {
newHW_Latency.setAttribute(TYPE, "am:LatencyDeviation", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
Element oldHW_Latency_Deviation = oldHW_Latency.getChild("deviation");
if (oldHW_Latency_Deviation != null) {
oldHW_Latency_Deviation = oldHW_Latency_Deviation.clone();
oldHW_Latency_Deviation.detach();
oldHW_Latency_Deviation.setName("cycles");
newHW_Latency.addContent(oldHW_Latency_Deviation);
}
}
}
}
}
}
}
}
}
}
/**
* This method is used to migrate NetworkType element from 0.8.3 to ConnectionHandlerDefinition element as per 0.9.0
*
* @param oldHWModelElement
* Element. JDOM Element equivalent to 0.8.3 HwModel
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 HwModel
*/
private void migrateNetworkTypes(Element oldHWModelElement, final Element newHWModelElement) {
List<Element> oldHWNetworkTypes = oldHWModelElement.getChildren("networkTypes");
for (Element oldHWNetworkType : oldHWNetworkTypes) {
String oldHWNetworkType_name=oldHWNetworkType.getAttributeValue(NAME);
Element newHWNetworkType=new Element(DEFINITIONS);
/*-adding newly created element to the hwmodel*/
newHWModelElement.addContent(newHWNetworkType);
newHWNetworkType.setAttribute(TYPE, "am:ConnectionHandlerDefinition", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
if (oldHWNetworkType_name != null) {
newHWNetworkType.setAttribute(NAME, oldHWNetworkType_name);
}
String oldHWNetworkType_schedPolicy = oldHWNetworkType.getAttributeValue("schedPolicy");
if (oldHWNetworkType_schedPolicy != null) {
String policy="_undefined_";
if (oldHWNetworkType_schedPolicy.equals("RROBIN")) {
policy = "RoundRobin";
} else if (oldHWNetworkType_schedPolicy.equals("PRIORITY")) {
policy = "PriorityBased";
}
newHWNetworkType.setAttribute("policy", policy);
}
/*-migrating custom properties */
migrateCustomProperties(oldHWNetworkType, newHWNetworkType);
}
}
/**
* This method is used to migrate CoreType element from 0.8.3 to ProcessingUnitDefinition element as per 0.9.0
*
* <b>Note:</b> value of InstructionsPerCycle is converted as HwFeatureCategory and HwFeature#s
* and the corresponding HwFeature is linked to the ProcessingUnitDefinition
*
* @param oldHWModelElement
* Element. JDOM Element equivalent to 0.8.3 HwModel
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 HwModel
*/
private void migrateCoreTypes(Element oldHWModelElement, final Element newHWModelElement) {
List<Element> oldHWCoreTypes = oldHWModelElement.getChildren("coreTypes");
for (Element oldHWCoreType : oldHWCoreTypes) {
String oldHWCoreType_name=oldHWCoreType.getAttributeValue(NAME);
Element newHWCoreType=new Element(DEFINITIONS);
/*-adding newly created element to the hwmodel*/
newHWModelElement.addContent(newHWCoreType);
newHWCoreType.setAttribute(TYPE, "am:ProcessingUnitDefinition", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
if (oldHWCoreType_name != null) {
newHWCoreType.setAttribute(NAME, oldHWCoreType_name);
}
newHWCoreType.setAttribute("puType", "CPU");
Attribute oldHWCoreType_Classifiers = oldHWCoreType.getAttribute("classifiers");
if (oldHWCoreType_Classifiers != null) {
newHWCoreType.setAttribute(oldHWCoreType_Classifiers.clone());
} else {
List<Element> oldCoreType_Classifiers_List = oldHWCoreType.getChildren("classifiers");
for (Element oldCoreType_Classifier : oldCoreType_Classifiers_List) {
newHWCoreType.addContent(oldCoreType_Classifier.clone());
}
}
String oldCoreType_ipc = oldHWCoreType.getAttributeValue("instructionsPerCycle");
if (oldCoreType_ipc != null) {
String ipc_value = oldCoreType_ipc;
oldCoreType_ipc = "IPC_" + ipc_value;
String newHWFeatureCategoryName = "Instructions";
Element newHWFeatureCategories = new Element("featureCategories");
newHWFeatureCategories.setAttribute(NAME, newHWFeatureCategoryName);
if (hwTransformationCache.getNewFeatureCategoriesMap().containsKey(newHWFeatureCategoryName)) {
newHWFeatureCategories = hwTransformationCache.getNewFeatureCategoriesMap().get(newHWFeatureCategoryName);
} else {
newHWModelElement.addContent(newHWFeatureCategories);
}
newHWFeatureCategories.setAttribute("featureType", "performance");
//TODO: Add docu here. In new_feature_literals_Map key is the literal name with convention as : FeatureName/LiteralName
if (!hwTransformationCache.getNewFeaturesMap().containsKey(newHWFeatureCategoryName + "/" + oldCoreType_ipc)) {
Element newHWFeatureElement=new Element("features");
newHWFeatureElement.setAttribute(NAME, oldCoreType_ipc);
newHWFeatureElement.setAttribute(VALUE, ipc_value);
newHWFeatureCategories.addContent(newHWFeatureElement);
hwTransformationCache.getNewFeaturesMap().put(newHWFeatureCategoryName+"/"+oldCoreType_ipc, newHWFeatureElement);
}
hwTransformationCache.getNewFeatureCategoriesMap().put(newHWFeatureCategoryName, newHWFeatureCategories);
//Adding HwFeature as a part of ProcessingUnitDefinition
{
Element newHwFeaturesElement=new Element("features");
newHwFeaturesElement.setAttribute("href", AMLT_PREFIX + (newHWFeatureCategoryName) + "/" + (oldCoreType_ipc) + "?type=HwFeature");
newHWCoreType.addContent(newHwFeaturesElement);
}
}
/*-migrating custom properties */
migrateCustomProperties(oldHWCoreType, newHWCoreType);
}
}
/**
* This method is used to migrate MemoryType element from 0.8.3 to MemoryDefinition element as per 0.9.0
*
* <b>Note:</b>If the type of MemoryType element is CACHE, then during the migration CacheDefinition object is created instead of MemoryDefinition
*
* @param oldHWModelElement_MemoryType
* Element. JDOM Element equivalent to 0.8.3 MemoryType
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 HwModel
*/
private void migrateMemoryTypes(Element oldHWModelElement_MemoryType, final Element newHWModelElement) {
String oldHWMemoryType_name=oldHWModelElement_MemoryType.getAttributeValue(NAME);
String oldHWMemoryType_type=oldHWModelElement_MemoryType.getAttributeValue(TYPE);
Element newHWMemoryType=new Element(DEFINITIONS);
/*-adding newly created element to the hwmodel*/
newHWModelElement.addContent(newHWMemoryType);
if (oldHWMemoryType_type != null && oldHWMemoryType_type.equals("CACHE")) {
newHWMemoryType.setAttribute(TYPE, "am:CacheDefinition", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
hwTransformationCache.getNewCacheTypesDefinitionMap().put(HelperUtil.encodeName(oldHWMemoryType_name), newHWMemoryType);
} else {
newHWMemoryType.setAttribute(TYPE, "am:MemoryDefinition", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
hwTransformationCache.getNewMemoryTypesDefinitionMap().put(HelperUtil.encodeName(oldHWMemoryType_name), newHWMemoryType);
Attribute oldHWMemoryType_Classifiers = oldHWModelElement_MemoryType.getAttribute("classifiers");
if (oldHWMemoryType_Classifiers != null) {
newHWMemoryType.setAttribute(oldHWMemoryType_Classifiers.clone());
} else {
List<Element> oldMemoryType_Classifiers_List = oldHWModelElement_MemoryType.getChildren("classifiers");
for (Element oldMemoryType_Classifier : oldMemoryType_Classifiers_List) {
newHWMemoryType.addContent(oldMemoryType_Classifier.clone());
}
}
}
if (oldHWMemoryType_name != null) {
newHWMemoryType.setAttribute(NAME, oldHWMemoryType_name);
}
Element oldMemoryType_size = oldHWModelElement_MemoryType.getChild("size");
if (oldMemoryType_size != null) {
newHWMemoryType.addContent(oldMemoryType_size.clone());
}
/*-migrating custom properties */
migrateCustomProperties(oldHWModelElement_MemoryType, newHWMemoryType);
}
/**
* This method is used to migrate HwSystem element from 0.8.3 to HwStructure element as per 0.9.0
* Below are the direct sub-elements of HwSystem which are migrated:
*
* <ul>
* <li>Quartz migrated as FrequencyDomain</li>
* <li>ECU migrated as HwStructure with type as ECU</li>
* <li>Memory objects migrated as Memory and Cache based on the type of MemoryDefinition linked to it</li>
* <li>Network objects migrated as ConnectionHandlers</li>
* <li>Port objects migrated as HwPort</li>
* </ul>
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 HwModel
* @param oldHWSystem
* Element. JDOM Element equivalent to 0.8.3 HwSystem
*/
private void migrateSystem(final Element newHWModelElement, Element oldHWSystem) {
String oldHWSystem_name = oldHWSystem.getAttributeValue(NAME);
Element newHWSystem = new Element(STRUCTURES);
if (oldHWSystem_name != null) {
newHWSystem.setAttribute(NAME, oldHWSystem_name);
}
newHWSystem.setAttribute(STRUCTURE_TYPE, "System");
newHWModelElement.addContent(newHWSystem);
hwTransformationCache.getNewSystemsMap().put(HelperUtil.encodeName(oldHWSystem_name), newHWSystem);
migrateAllQuartzes_modelscope(newHWModelElement);
List<Element> oldHWecus = oldHWSystem.getChildren("ecus");
for (Element oldHWEcu : oldHWecus) {
migrateECU(newHWSystem, oldHWEcu);
}
/*-migrating memories*/
migrateMemoriesAndCaches(oldHWSystem, newHWSystem,true,true);
/*-migrating networks*/
migrateNetworks(oldHWSystem, newHWSystem);
/*-migrate ports*/
migratePorts(oldHWSystem, newHWSystem);
/*-migrating custom properties */
migrateCustomProperties(oldHWSystem, newHWSystem);
}
/**
* This method is used to migrate HwPort, ComplexPort element from 0.8.3 to HwPort element as per 0.9.0
*
* @param oldHWModelElement
* Element. JDOM Element equivalent to 0.8.3 Core or ECU
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 ProcessingUnit or HwStructure( with type as ECU)
*/
private void migratePorts(Element oldHWElement, Element newHWElement) {
List<Element> oldHW_ports = oldHWElement.getChildren("ports");
for (Element oldHWPort : oldHW_ports) {
Element newHWPort = new Element("ports");
String oldHWPort_name = oldHWPort.getAttributeValue(NAME);
String oldHWPort_bitWidth = oldHWPort.getAttributeValue("bitWidth");
String oldHWPort_master = oldHWPort.getAttributeValue("master");
if (oldHWPort_name != null) {
newHWPort.setAttribute(NAME, oldHWPort_name);
}
if (oldHWPort_bitWidth != null) {
newHWPort.setAttribute("bitWidth", oldHWPort_bitWidth);
}
if (oldHWPort_master != null) {
if (Boolean.valueOf(oldHWPort_master.trim())) {
newHWPort.setAttribute("portType", "initiator");
} else {
newHWPort.setAttribute("portType", "responder");
}
}
newHWElement.addContent(newHWPort);
/*-migrating custom properties */
migrateCustomProperties(oldHWPort, newHWPort);
}
}
/**
* This method is used to migrate Memory element from 0.8.3 to Memory element or Cache element as per 0.9.0
*
* Based on the type of MemoryType element (in 0.8.3) -> either Cache element or Memory element are generated in 0.9.0
*
* -- If type is CACHE, then Cache element is generated. For other types, Memory element is generated
*
*
* Inside Memory element (of 0.8.3) accordingly, PreScaler and HwPort elements are migrated to appropriate elements in 0.9.0
*
* @param oldHWModelElement
* Element. JDOM Element equivalent to 0.8.3 Core or ECU or MicroController or System
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 ProcessingUnit or HwStructure (with type as ECU or MicroController or System)
*/
private void migrateMemoriesAndCaches(Element oldHWElement, Element newHWStructure_or_PU_Element, boolean migrateCache, boolean migrateMemory) {
List<Element> oldHW_Memories = getAllMemories(oldHWElement);
for (Element oldHW_Memory : oldHW_Memories) {
Element newHW_Memory_Element=new Element("modules");
String oldHW_Memory_Name = oldHW_Memory.getAttributeValue(NAME);
if(oldHW_Memory_Name!=null) {
newHW_Memory_Element.setAttribute(NAME, oldHW_Memory_Name);
}
String hw_memory_typeDefinitionName=HelperUtil.getSingleElementNameFromAttributeOrChildeElement(TYPE,oldHW_Memory);
String newHW_definitions_type_amalthea_element="MemoryDefinition";
boolean isElementAddedToTheParent=false;
if(hw_memory_typeDefinitionName!=null) {
if (migrateCache) {
if (hwTransformationCache.getNewCacheTypesDefinitionMap().containsKey(hw_memory_typeDefinitionName)) {
newHW_definitions_type_amalthea_element="CacheDefinition";
if (migrateCache && !migrateMemory) {
// In this scenario, Core object is being migrated
newHW_Memory_Element.setName("caches");
}
newHW_Memory_Element.setAttribute(TYPE, "am:Cache", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
hwTransformationCache.getNewCachesMap().put(HelperUtil.encodeName(oldHW_Memory_Name), newHW_Memory_Element);
//Adding memory object to newHW
newHWStructure_or_PU_Element.addContent(newHW_Memory_Element);
isElementAddedToTheParent=true;
}
}
if (migrateMemory) {
if (hwTransformationCache.getNewMemoryTypesDefinitionMap().containsKey(hw_memory_typeDefinitionName)) {
newHW_Memory_Element.setAttribute(TYPE, "am:Memory", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
hwTransformationCache.getNewMemoriesMap().put(HelperUtil.encodeName(oldHW_Memory_Name), newHW_Memory_Element);
//Adding memory object to newHW
newHWStructure_or_PU_Element.addContent(newHW_Memory_Element);
isElementAddedToTheParent=true;
}
}
} else {
if (migrateMemory) {
newHW_Memory_Element.setAttribute(TYPE, "am:Memory", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
hwTransformationCache.getNewMemoriesMap().put(HelperUtil.encodeName(oldHW_Memory_Name), newHW_Memory_Element);
//Adding memory object to newHW
newHWStructure_or_PU_Element.addContent(newHW_Memory_Element);
isElementAddedToTheParent=true;
}
}
// TODO When should the following loop be executed ?
if (isElementAddedToTheParent) {
List<Element> newHWMemoryDefinitions = migrateAttributeorElementData(oldHW_Memory, TYPE, DEFINITION, newHW_definitions_type_amalthea_element);
for (Element newHWMemoryDefinition : newHWMemoryDefinitions) {
newHW_Memory_Element.addContent(newHWMemoryDefinition);
}
migratePrescaler(oldHW_Memory, newHW_Memory_Element);
/*-migrate ports*/
migratePorts(oldHW_Memory, newHW_Memory_Element);
/*-migrating custom properties */
migrateCustomProperties(oldHW_Memory, newHW_Memory_Element);
}
}
}
/**
* This method is used to migrate Network element from 0.8.3 to ConnectionHandler element as per 0.9.0
*
* Inside Memory element (of 0.8.3) accordingly, PreScaler and HwPort elements are migrated to appropriate elements in 0.9.0
*
* @param oldHWModelElement
* Element. JDOM Element equivalent to 0.8.3 ECU or MicroController or System
* @param newHWModelElement
* Element. JDOM Element equivalent to 0.9.0 HwStructure( with type as ECU or MicroController or System)
*/
private void migrateNetworks(Element oldHWElement, Element newHWStructure) {
List<Element> oldHW_Networks = getAllNetworks(oldHWElement);
for (Element oldHW_network : oldHW_Networks) {
Element newHW_network=new Element("modules");
String oldHW_network_Name = oldHW_network.getAttributeValue(NAME);
if(oldHW_network_Name!=null) {
newHW_network.setAttribute(NAME, oldHW_network_Name);
}
newHW_network.setAttribute(TYPE, "am:ConnectionHandler", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
List<Element> newHWNetworkTypeDefinitions = migrateAttributeorElementData(oldHW_network, TYPE,
DEFINITION, "ConnectionHandlerDefinition");
for (Element newHWNetworkTypeDefinition : newHWNetworkTypeDefinitions) {
newHW_network.addContent(newHWNetworkTypeDefinition);
}
migratePrescaler(oldHW_network, newHW_network);
/*-migrate ports*/
migratePorts(oldHW_network, newHW_network);
//Adding network object to newHW
newHWStructure.addContent(newHW_network);
/*-migrating custom properties */
migrateCustomProperties(oldHW_network, newHW_network);
}
}
/**
* This method is used to fetch all the Network elements inside a ComplexNode of AMALTHEA 0.8.3 - > recursively
* @param oldHW_ComplexNode Element compatible to Network (as per 0.8.3)
* @return List<Element> elements of Network (as per 0.8.3)
*/
private List<Element> getAllNetworks(Element oldHW_ComplexNode) {
List<Element> oldHW_Networks=new ArrayList<>();
List<Element> oldHW_ComplexNodeElements = oldHW_ComplexNode.getChildren("networks");
oldHW_Networks.addAll(oldHW_ComplexNodeElements);
populateAllSubNetworks(oldHW_Networks, oldHW_ComplexNode.getChildren("networks"));
populateAllSubNetworks(oldHW_Networks, oldHW_ComplexNode.getChildren("memories"));
populateAllSubNetworks(oldHW_Networks, oldHW_ComplexNode.getChildren("components"));
return oldHW_Networks;
}
/**
* This method is used to fetch all the Memory elements inside a ComplexNode of AMALTHEA 0.8.3 - > recursively
* @param oldHW_ComplexNode Element compatible to Memory (as per 0.8.3)
* @return List<Element> elements of Memory (as per 0.8.3)
*/
private List<Element> getAllMemories(Element oldHW_ComplexNode) {
List<Element> oldHW_Memories = new ArrayList<>();
List<Element> oldHW_ComplexNodeElements = oldHW_ComplexNode.getChildren("memories");
oldHW_Memories.addAll(oldHW_ComplexNodeElements);
populateAllSubMemories(oldHW_Memories, oldHW_ComplexNode.getChildren("memories"));
populateAllSubMemories(oldHW_Memories, oldHW_ComplexNode.getChildren("networks"));
populateAllSubMemories(oldHW_Memories, oldHW_ComplexNode.getChildren("components"));
return oldHW_Memories;
}
/**
* This method is used to fetch all the Sub Memory elements inside a complex node (as per 0.8.3) -> recursively
* @param oldHW_Memories
* @param oldHW_ComplexNodeElements
*/
private void populateAllSubMemories(List<Element> oldHW_Memories, List<Element> oldHW_ComplexNodeElements) {
for (Element oldHWMemory : oldHW_ComplexNodeElements) {
final StringBuilder xpathBufferForMemoryDefinitions = new StringBuilder();
xpathBufferForMemoryDefinitions.append("./memories");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//components/memories");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//nestedComponents/memories");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//memories/memories");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//networks/memories");
final List<Element> memoryElements = HelperUtil.getXpathResult(
oldHWMemory,
xpathBufferForMemoryDefinitions.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI),
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._090, AM) );
oldHW_Memories.addAll(memoryElements);
}
}
/**
* This method is used to recursively fetch all Network elements (compatible as per 0.8.3)
* @param oldHW_Networks
* @param oldHW_ComplexNodeElements
*/
private void populateAllSubNetworks(List<Element> oldHW_Networks, List<Element> oldHW_ComplexNodeElements) {
for (Element oldHWNetwork : oldHW_ComplexNodeElements) {
final StringBuilder xpathBufferForMemoryDefinitions = new StringBuilder();
xpathBufferForMemoryDefinitions.append("./networks");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//components/networks");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//nestedComponents/networks");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//memories/networks");
xpathBufferForMemoryDefinitions.append("|");
xpathBufferForMemoryDefinitions.append(".//networks/networks");
final List<Element> networkElements = HelperUtil.getXpathResult(
oldHWNetwork,
xpathBufferForMemoryDefinitions.toString(),
Element.class,
AmaltheaNamespaceRegistry.getGenericNamespace(XSI),
AmaltheaNamespaceRegistry.getNamespace(ModelVersion._090, AM) );
oldHW_Networks.addAll(networkElements);
}
}
/**
* This method is used to migrate all Quartz elements present in the model scope to FrequencyDomain elements as per 0.9.0
*
* @param newHWModel JDOM element ->equivalent to HwModel element of 0.9.0
*/
private void migrateAllQuartzes_modelscope(Element newHWModel) {
Collection<Element> oldHWQuartzElements = hwTransformationCache.getOldHwQuartzsMap().values();
for (Element oldHWQuartzElement : oldHWQuartzElements) {
Element newHWFrequencyDomain=new Element("domains");
newHWFrequencyDomain.setAttribute(TYPE, "am:FrequencyDomain",AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
String oldHWQuartz_name = oldHWQuartzElement.getAttributeValue(NAME);
if(oldHWQuartz_name!=null) {
newHWFrequencyDomain.setAttribute(NAME, oldHWQuartz_name);
}
Element oldHWElement_Frequency = oldHWQuartzElement.getChild("frequency");
if(oldHWElement_Frequency!=null) {
Element newHWFrequency_defaultValue = oldHWElement_Frequency.clone();
newHWFrequency_defaultValue.detach();
newHWFrequency_defaultValue.setName("defaultValue");
newHWFrequencyDomain.addContent(newHWFrequency_defaultValue);
}
newHWModel.addContent(newHWFrequencyDomain);
/*-migration of custom properties */
migrateCustomProperties(oldHWQuartzElement, newHWFrequencyDomain);
hwTransformationCache.getNewHwQuartzsFrequencyDomainMap().put(HelperUtil.encodeName(oldHWQuartz_name), newHWFrequencyDomain);
}
}
/**
* This method is used to migrate the ECU elements to HwStructure with type as ECU(as per 0.9.0)
*
* During the migration, below elements contained by the ECU are also migrated:
* <ul>
* <li>Memory to Cache/Memory as per 0.9.0</li>
* <li>Network to ConnectionHandler as per 0.9.0</li>
* <li>HwPort, ComplexPort to hwPort as per 0.9.0</li>
* <li>MicroController to HwStructure as per 0.9.0</li>
* </ul>
* @param newHWSystem
* @param oldHWEcu
*/
private void migrateECU(Element newHWSystem, Element oldHWEcu) {
String oldHWEcu_name=oldHWEcu.getAttributeValue(NAME);
hwTransformationCache.getOldEcusMap().put(HelperUtil.encodeName(oldHWEcu_name), oldHWEcu);
Element newHWEcu=new Element(STRUCTURES);
if(oldHWEcu_name!=null) {
newHWEcu.setAttribute(NAME, oldHWEcu_name);
}
newHWEcu.setAttribute(STRUCTURE_TYPE, "ECU");
newHWSystem.addContent(newHWEcu);
hwTransformationCache.getNewEcusMap().put(HelperUtil.encodeName(oldHWEcu_name), newHWEcu);
/*-migrating memories*/
migrateMemoriesAndCaches(oldHWEcu, newHWEcu,true,true);
/*-migrating networks*/
migrateNetworks(oldHWEcu, newHWEcu);
/*-migrate ports*/
migratePorts(oldHWEcu, newHWEcu);
List<Element> oldHWMicroControllers = oldHWEcu.getChildren("microcontrollers");
for (Element oldHWMicroController : oldHWMicroControllers) {
migrateMicroController(newHWEcu, oldHWMicroController);
}
/*-migration of custom properties */
migrateCustomProperties(oldHWEcu, newHWEcu);
}
/**
* This method is used to migrate the MicroController to HwStructure with type as MicroController(as per 0.9.0)
*
* During the migration, below elements contained by the ECU are also migrated:
* <ul>
* <li>Memory to Cache/Memory as per 0.9.0</li>
* <li>Network to ConnectionHandler as per 0.9.0</li>
* <li>HwPort, ComplexPort to hwPort as per 0.9.0</li>
* <li>MicroController to HwStructure as per 0.9.0</li>
* <li>Core to ProcessingUnit as per 0.9.0</li>
* </ul>
* @param newHWSystem
* @param oldHWEcu
*/
private void migrateMicroController(Element newHWEcu, Element oldHWMicroController) {
String oldHWMicroController_name=oldHWMicroController.getAttributeValue(NAME);
hwTransformationCache.getOldMicroControllersMap().put(HelperUtil.encodeName(oldHWMicroController_name), oldHWMicroController);
Element newHWMicroController=new Element(STRUCTURES);
if(oldHWMicroController_name!=null) {
newHWMicroController.setAttribute(NAME, oldHWMicroController_name);
}
newHWMicroController.setAttribute(STRUCTURE_TYPE, "Microcontroller");
newHWEcu.addContent(newHWMicroController);
hwTransformationCache.getNewMicroControllersMap().put(HelperUtil.encodeName(oldHWMicroController_name), newHWMicroController);
/*-migrating memories*/
migrateMemoriesAndCaches(oldHWMicroController, newHWMicroController,true,true);
/*-migrating networks*/
migrateNetworks(oldHWMicroController, newHWMicroController);
/*-migrate ports*/
migratePorts(oldHWMicroController, newHWMicroController);
/*if (!hasProcessedCores) {
hasProcessedCores = true;
migrateAllCores_modelscope(newHWMicroController);
}
*/
List<Element> oldHWCores = oldHWMicroController.getChildren("cores");
for (Element oldHWCore : oldHWCores) {
/*migrating cores belonging to specific Microcontroller*/
migrateCore(newHWMicroController, oldHWCore);
/*-migrating memories*/
//TODO: cross check : As in case of new HW Model, core can not contain memories, corresponding memories of core are added to the HWStructure (microcontroller type)
migrateMemoriesAndCaches(oldHWCore, newHWMicroController,false,true);
/*-migrating networks*/
migrateNetworks(oldHWCore, newHWMicroController);
}
/*-migration of custom properties */
migrateCustomProperties(oldHWMicroController, newHWMicroController);
}
/**
* This method is used to migrate Core as ProcessingUnit.
* During the migration process, based on the ClockRation of the PreScaler -> appropriate FrequencyDomain is referred to the ProcessingUnit element
*
* @param newHWMicroController
* @param oldHWCore
*/
private void migrateCore(Element newHWMicroController, Element oldHWCore) {
Element newHWCore=new Element("modules");
newHWMicroController.addContent(newHWCore);
newHWCore.setAttribute(TYPE, "am:ProcessingUnit", AmaltheaNamespaceRegistry.getGenericNamespace(XSI));
String oldHWCore_name = oldHWCore.getAttributeValue(NAME);
if(oldHWCore_name!=null) {
newHWCore.setAttribute(NAME, oldHWCore_name);
}
List<Element> newHWProcessingUnits = migrateAttributeorElementData(oldHWCore, "coreType", DEFINITION, "ProcessingUnitDefinition");
for (Element newHWProcessingUnit : newHWProcessingUnits) {
newHWCore.addContent(newHWProcessingUnit);
}
migratePrescaler(oldHWCore, newHWCore);
/*-migrate ports*/
migratePorts(oldHWCore, newHWCore);
// TODO PROBLEM
// if local memory of a core is transformed
// then link to definition is empty
migrateMemoriesAndCaches(oldHWCore, newHWCore, true, false);
hwTransformationCache.getNewCoresMap().put(HelperUtil.encodeName(oldHWCore_name), newHWCore);
/*-migration of custom properties */
migrateCustomProperties(oldHWCore, newHWCore);
}
/**
* This method is used to migrate a PreScaler to FrequencyDomain.
* -- ClockRatio of the PreScaler is used to refer appropriate FrequencyDomain
* @param oldHWElement e.g: Core, Memory
* @param newHWElement
*/
private void migratePrescaler(Element oldHWElement, Element newHWElement) {
Element oldHWPrescaler = oldHWElement.getChild("prescaler");
if(oldHWPrescaler!=null) {
String oldHW_quartz_name = HelperUtil.getSingleElementNameFromAttributeOrChildeElement("quartz", oldHWPrescaler);
if(oldHW_quartz_name!=null) {
String clockRatio = oldHWPrescaler.getAttributeValue("clockRatio");
if(clockRatio==null) {
clockRatio="0.0";
}
String newHW_frequencyDomain_name ="";
if (clockRatio.trim().equals("1.0")) {
newHW_frequencyDomain_name = oldHW_quartz_name;
} else {
//As the clock ratio is not 1.0, in this case -> cloning standard FrequencyDomain and setting the updated Frequency
newHW_frequencyDomain_name= oldHW_quartz_name+"__"+clockRatio;
}
Element newHW_FrequencyDomain = hwTransformationCache.getNewHwQuartzsFrequencyDomainMap().get(newHW_frequencyDomain_name);
if(newHW_FrequencyDomain==null) {
Element newHW_FrequencyDomain_baseFrequency_from_Quartz = hwTransformationCache.getNewHwQuartzsFrequencyDomainMap().get(oldHW_quartz_name);
if(newHW_FrequencyDomain_baseFrequency_from_Quartz!=null) {
/*-getting parent element of existing FrequencyDomain -> HWModel */
Element parentElement = newHW_FrequencyDomain_baseFrequency_from_Quartz.getParentElement();
newHW_FrequencyDomain= newHW_FrequencyDomain_baseFrequency_from_Quartz.clone();
newHW_FrequencyDomain.detach();
newHW_frequencyDomain_name = oldHW_quartz_name+"__"+clockRatio;
newHW_FrequencyDomain.setAttribute(NAME, newHW_frequencyDomain_name);
/*-Adding newly created FrequencyDomain to HWModel*/
parentElement.addContent(newHW_FrequencyDomain);
hwTransformationCache.getNewHwQuartzsFrequencyDomainMap().put((newHW_frequencyDomain_name),newHW_FrequencyDomain);
Element newHW_frequency = newHW_FrequencyDomain.getChild("defaultValue");
if(newHW_frequency!=null) {
Attribute newHW_frequency_value_attribute = newHW_frequency.getAttribute(VALUE);
if(newHW_frequency_value_attribute!=null) {
try {
String value = newHW_frequency_value_attribute.getValue();
String newHW_frequency_value=Double.parseDouble(value)*Double.parseDouble(clockRatio)+"";
newHW_frequency_value_attribute.setValue(newHW_frequency_value);
} catch (Exception e) {
logger.error("Exception occured during creation of new FrequencyDomain : {0}",newHW_FrequencyDomain.getAttributeValue(NAME));
}
}
}
}
}
//updating reference
if(newHW_FrequencyDomain!=null) {
Element newHW_frequencyDoamin_reference=new Element("frequencyDomain");
newHW_frequencyDoamin_reference.setAttribute("href", AMLT_PREFIX+HelperUtil.encodeNameForReference(newHW_FrequencyDomain.getAttributeValue(NAME))+"?type=FrequencyDomain");
newHWElement.addContent(newHW_frequencyDoamin_reference);
}
}
}
}
private List<Element> migrateAttributeorElementData(Element oldHWElement, String attributeOrChildElementName, String newChildElementName, String newChildElementType){
List<Element> newHWElements=new ArrayList<>();
Attribute oldHWAttribute = oldHWElement.getAttribute(attributeOrChildElementName);
if(oldHWAttribute!=null) {
String oldHWRefElementsValue = oldHWAttribute.getValue();
StringTokenizer stk=new StringTokenizer(oldHWRefElementsValue);
while(stk.hasMoreTokens()) {
String nextToken = stk.nextToken();
String newHWRefElementName=updateReferenceStringWithNewType(nextToken, newChildElementType);
Element newHWRefElement=new Element(newChildElementName);
newHWRefElement.setAttribute("href", AMLT_PREFIX+ (newHWRefElementName));
newHWElements.add(newHWRefElement);
}
}else {
List<Element> oldHWChildElements = oldHWElement.getChildren(attributeOrChildElementName);
for (Element oldHWChildElement : oldHWChildElements) {
String oldHWhrefValue = oldHWChildElement.getAttributeValue("href");
if(oldHWhrefValue!=null) {
String newHWRefElementName=updateReferenceStringWithNewType(oldHWhrefValue, newChildElementType);
Element newHWRefElement=new Element(newChildElementName);
newHWRefElement.setAttribute("href", newHWRefElementName);
newHWElements.add(newHWRefElement);
}
}
}
oldHWElement.removeAttribute(attributeOrChildElementName);
oldHWElement.removeChildren(attributeOrChildElementName);
return newHWElements;
}
private String updateReferenceStringWithNewType(String inputString, String newType) {
if (inputString != null) {
int startIndex = inputString.indexOf("?type=");
if (startIndex != -1) {
String oldHWRefElementName = inputString.substring(0, startIndex);
return (oldHWRefElementName) + "?type=" + newType;
}
return inputString;
}
return inputString;
}
private void migrateCustomProperties(Element oldHwElement, Element newHwElement) {
List<Element> customProperties = oldHwElement.getChildren("customProperties");
for (Element customProperty : customProperties) {
Element newHwCustomProperty = customProperty.clone();
newHwCustomProperty.detach();
newHwElement.addContent(newHwCustomProperty);
}
}
/**
* This method is used to get the HWCacheBuilder object
*
* @param caches The list of all caches.
* @return HWCacheBuilder
*/
private HWTransformationCache getHWTransformationCache(List<ICache> caches) {
if (caches == null) return null;
for (final ICache cache : caches) {
if (cache instanceof HWCacheBuilder) {
Map<File, Map<String, Object>> cacheMap = cache.getCacheMap();
if (cacheMap != null && cacheMap.size() > 0) {
Map<String, Object> map = cacheMap.values().iterator().next();
if (map != null) {
Object object = map.get("globalCache");
return (HWTransformationCache) object;
}
}
}
}
return new HWTransformationCache();
}
}