/* * INTEL CONFIDENTIAL * Copyright © 2011 Intel * Corporation All Rights Reserved. * * The source code contained or described herein and all documents related to * the source code ("Material") are owned by Intel Corporation or its suppliers * or licensors. Title to the Material remains with Intel Corporation or its * suppliers and licensors. The Material contains trade secrets and proprietary * and confidential information of Intel or its suppliers and licensors. The * Material is protected by worldwide copyright and trade secret laws and * treaty provisions. No part of the Material may be used, copied, reproduced, * modified, published, uploaded, posted, transmitted, distributed, or * disclosed in any way without Intel’s prior express written permission. * * No license under any patent, copyright, trade secret or other intellectual * property right is granted to or conferred upon you by disclosure or delivery * of the Materials, either expressly, by implication, inducement, estoppel or * otherwise. Any license under such intellectual property rights must be * express and approved by Intel in writing. * * CREATED: 2011-06-01 * UPDATED: 2011-07-27 */ #include "Subsystem.h" #include "ComponentLibrary.h" #include "InstanceDefinition.h" #include "XmlParameterSerializingContext.h" #include "ParameterAccessContext.h" #include "ConfigurationAccessContext.h" #include "SubsystemObjectCreator.h" #include #define base CConfigurableElement CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false) { // Note: A subsystem contains instance components // InstanceDefintion and ComponentLibrary objects are then not chosen to be children // They'll be delt with locally } CSubsystem::~CSubsystem() { // Remove subsystem objects SubsystemObjectListIterator subsystemObjectIt; for (subsystemObjectIt = _subsystemObjectList.begin(); subsystemObjectIt != _subsystemObjectList.end(); ++subsystemObjectIt) { delete *subsystemObjectIt; } // Remove susbsystem creators uint32_t uiIndex; for (uiIndex = 0; uiIndex < _subsystemObjectCreatorArray.size(); uiIndex++) { delete _subsystemObjectCreatorArray[uiIndex]; } // Order matters! delete _pInstanceDefinition; delete _pComponentLibrary; } string CSubsystem::getKind() const { return "Subsystem"; } // Susbsystem Endianness bool CSubsystem::isBigEndian() const { return _bBigEndian; } // From IXmlSink bool CSubsystem::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) { // Context CXmlParameterSerializingContext& parameterBuildContext = static_cast(serializingContext); // Install temporary component library for further component creation parameterBuildContext.setComponentLibrary(_pComponentLibrary); CXmlElement childElement; // XML populate ComponentLibrary xmlElement.getChildElement("ComponentLibrary", childElement); if (!_pComponentLibrary->fromXml(childElement, serializingContext)) { return false; } // XML populate InstanceDefintion xmlElement.getChildElement("InstanceDefintion", childElement); if (!_pInstanceDefinition->fromXml(childElement, serializingContext)) { return false; } // Create components _pInstanceDefinition->createInstances(this); // Execute mapping to create subsystem mapping entities string strError; if (!mapSubsystemElements(strError)) { serializingContext.setError(strError); return false; } // Endianness _bBigEndian = xmlElement.getAttributeBoolean("Endianness", "Big"); return true; } // XML configuration settings parsing bool CSubsystem::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const { // Fix Endianness configurationAccessContext.setBigEndianSubsystem(_bBigEndian); return base::serializeXmlSettings(xmlConfigurationSettingsElementContent, configurationAccessContext); } bool CSubsystem::mapSubsystemElements(string& strError) { // Default mapping context _contextStack.push(CMappingContext(_contextMappingKeyArray.size())); // Map all instantiated subelements in subsystem uint32_t uiNbChildren = getNbChildren(); uint32_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { CInstanceConfigurableElement* pInstanceConfigurableChildElement = static_cast(getChild(uiChild)); if (!pInstanceConfigurableChildElement->map(*this, strError)) { return false; } } return true; } // Parameter access bool CSubsystem::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const { // Deal with Endianness parameterAccessContext.setBigEndianSubsystem(_bBigEndian); return base::accessValue(pathNavigator, strValue, bSet, parameterAccessContext); } void CSubsystem::logValue(string& strValue, CErrorContext& errorContext) const { CParameterAccessContext& parameterAccessContext = static_cast(errorContext); // Deal with Endianness parameterAccessContext.setBigEndianSubsystem(_bBigEndian); return base::logValue(strValue, errorContext); } // Used for simulation and virtual subsystems void CSubsystem::setDefaultValues(CParameterAccessContext& parameterAccessContext) const { // Deal with Endianness parameterAccessContext.setBigEndianSubsystem(_bBigEndian); base::setDefaultValues(parameterAccessContext); } // Belonging subsystem const CSubsystem* CSubsystem::getBelongingSubsystem() const { return this; } // Subsystem context mapping keys publication void CSubsystem::addContextMappingKey(const string& strMappingKey) { _contextMappingKeyArray.push_back(strMappingKey); } // Subsystem object creator publication (strong reference) void CSubsystem::addSubsystemObjectFactory(CSubsystemObjectCreator* pSubsystemObjectCreator) { _subsystemObjectCreatorArray.push_back(pSubsystemObjectCreator); } // Mapping generic context handling bool CSubsystem::handleMappingContext(const CInstanceConfigurableElement* pInstanceConfigurableElement, CMappingContext& context, string& strError) { // Feed context with found mapping data uint32_t uiItem; for (uiItem = 0; uiItem < _contextMappingKeyArray.size(); uiItem++) { string strKey = _contextMappingKeyArray[uiItem]; const string* pStrValue; if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) { // Assign item to context if (!context.setItem(uiItem, pStrValue)) { getMappingError(strError, strKey, "Already set", pInstanceConfigurableElement); return false; } } } return true; } // Creation handling bool CSubsystem::handleSubsystemObjectCreation(CInstanceConfigurableElement* pInstanceConfigurableElement, CMappingContext& context, string& strError) { uint32_t uiItem; for (uiItem = 0; uiItem < _subsystemObjectCreatorArray.size(); uiItem++) { const CSubsystemObjectCreator* pSubsystemObjectCreator = _subsystemObjectCreatorArray[uiItem]; // Mapping key string strKey = pSubsystemObjectCreator->getMappingKey(); // Object id const string* pStrValue; if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) { // First check context consistency (required ancestors must have been set prior to object creation) uint32_t uiAncestorKey; uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask(); for (uiAncestorKey = 0; uiAncestorKey < _contextMappingKeyArray.size(); uiAncestorKey++) { if (!((1 << uiAncestorKey) & uiAncestorMask)) { // Ancestor not required continue; } // Check ancestor was provided if (!context.iSet(uiAncestorKey)) { getMappingError(strError, strKey, _contextMappingKeyArray[uiAncestorKey] + " not set", pInstanceConfigurableElement); return false; } } // Then check configurable element size is correct if (pInstanceConfigurableElement->getFootPrint() > pSubsystemObjectCreator->getMaxConfigurableElementSize()) { string strSizeError = "Size should not exceed " + pSubsystemObjectCreator->getMaxConfigurableElementSize(); getMappingError(strError, strKey, strSizeError, pInstanceConfigurableElement); return false; } // Do create object and keep its track _subsystemObjectList.push_back(pSubsystemObjectCreator->objectCreate(*pStrValue, pInstanceConfigurableElement, context)); // Done return true; } } getMappingError(strError, "Mapping key", "Not found", pInstanceConfigurableElement); return false; } // Generic error handling from derived subsystem classes void CSubsystem::getMappingError(string& strError, const string& strKey, const string& strMessage, const CInstanceConfigurableElement* pInstanceConfigurableElement) { strError = getName() + " " + getKind() + " mapping:\n" + strKey + " error: \"" + strMessage + "\" for element " + pInstanceConfigurableElement->getPath(); } // From IMapper bool CSubsystem::mapBegin(CInstanceConfigurableElement* pInstanceConfigurableElement, bool& bKeepDiving, string& strError) { // Get current context CMappingContext context = _contextStack.top(); switch(pInstanceConfigurableElement->getType()) { case CInstanceConfigurableElement::EComponent: if (!handleMappingContext(pInstanceConfigurableElement, context, strError)) { return false; } // Push context _contextStack.push(context); // Keep diving bKeepDiving = true; return true; case CInstanceConfigurableElement::EParameterBlock: case CInstanceConfigurableElement::EBitParameterBlock: case CInstanceConfigurableElement::EParameter: case CInstanceConfigurableElement::EStringParameter: if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context, strError)) { return false; } // Done bKeepDiving = false; return true; default: assert(0); return false; } } void CSubsystem::mapEnd() { // Unstack context _contextStack.pop(); }