/*
*
*
* 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.
*
* AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
* 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();
}