blob: 59b95c32396ef2d71ba9466e38dd9c7e4aa0c77c [file] [log] [blame]
Patrick Benavoli68a91282011-08-31 11:23:23 +02001/* <auto_header>
2 * <FILENAME>
3 *
4 * INTEL CONFIDENTIAL
5 * Copyright © 2011 Intel
6 * Corporation All Rights Reserved.
7 *
8 * The source code contained or described herein and all documents related to
9 * the source code ("Material") are owned by Intel Corporation or its suppliers
10 * or licensors. Title to the Material remains with Intel Corporation or its
11 * suppliers and licensors. The Material contains trade secrets and proprietary
12 * and confidential information of Intel or its suppliers and licensors. The
13 * Material is protected by worldwide copyright and trade secret laws and
14 * treaty provisions. No part of the Material may be used, copied, reproduced,
15 * modified, published, uploaded, posted, transmitted, distributed, or
16 * disclosed in any way without Intel’s prior express written permission.
17 *
18 * No license under any patent, copyright, trade secret or other intellectual
19 * property right is granted to or conferred upon you by disclosure or delivery
20 * of the Materials, either expressly, by implication, inducement, estoppel or
21 * otherwise. Any license under such intellectual property rights must be
22 * express and approved by Intel in writing.
23 *
24 * AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
25 * CREATED: 2011-06-01
26 * UPDATED: 2011-07-27
27 *
28 *
29 * </auto_header>
30 */
31#include "Subsystem.h"
32#include "ComponentLibrary.h"
33#include "InstanceDefinition.h"
34#include "XmlParameterSerializingContext.h"
35#include "ParameterAccessContext.h"
36#include "ConfigurationAccessContext.h"
37#include "SubsystemObjectCreator.h"
38#include <assert.h>
39
40#define base CConfigurableElement
41
42CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false)
43{
44 // Note: A subsystem contains instance components
45 // InstanceDefintion and ComponentLibrary objects are then not chosen to be children
46 // They'll be delt with locally
47}
48
49CSubsystem::~CSubsystem()
50{
51 // Remove subsystem objects
52 SubsystemObjectListIterator subsystemObjectIt;
53
54 for (subsystemObjectIt = _subsystemObjectList.begin(); subsystemObjectIt != _subsystemObjectList.end(); ++subsystemObjectIt) {
55
56 delete *subsystemObjectIt;
57 }
58
59 // Remove susbsystem creators
60 uint32_t uiIndex;
61
62 for (uiIndex = 0; uiIndex < _subsystemObjectCreatorArray.size(); uiIndex++) {
63
64 delete _subsystemObjectCreatorArray[uiIndex];
65 }
66
67 // Order matters!
68 delete _pInstanceDefinition;
69 delete _pComponentLibrary;
70}
71
72string CSubsystem::getKind() const
73{
74 return "Subsystem";
75}
76
77// Susbsystem Endianness
78bool CSubsystem::isBigEndian() const
79{
80 return _bBigEndian;
81}
82
83// From IXmlSink
84bool CSubsystem::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
85{
86 // Context
87 CXmlParameterSerializingContext& parameterBuildContext = static_cast<CXmlParameterSerializingContext&>(serializingContext);
88
89 // Install temporary component library for further component creation
90 parameterBuildContext.setComponentLibrary(_pComponentLibrary);
91
92 CXmlElement childElement;
93
94 // XML populate ComponentLibrary
95 xmlElement.getChildElement("ComponentLibrary", childElement);
96
97 if (!_pComponentLibrary->fromXml(childElement, serializingContext)) {
98
99 return false;
100 }
101
102 // XML populate InstanceDefintion
103 xmlElement.getChildElement("InstanceDefintion", childElement);
104 if (!_pInstanceDefinition->fromXml(childElement, serializingContext)) {
105
106 return false;
107 }
108
109 // Create components
110 _pInstanceDefinition->createInstances(this);
111
112 // Execute mapping to create subsystem mapping entities
113 string strError;
114 if (!mapSubsystemElements(strError)) {
115
116 serializingContext.setError(strError);
117
118 return false;
119 }
120
121 // Endianness
122 _bBigEndian = xmlElement.getAttributeBoolean("Endianness", "Big");
123
124 return true;
125}
126
127// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200128bool CSubsystem::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200129{
130 // Fix Endianness
131 configurationAccessContext.setBigEndianSubsystem(_bBigEndian);
132
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200133 return base::serializeXmlSettings(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200134}
135
136
137bool CSubsystem::mapSubsystemElements(string& strError)
138{
139 // Default mapping context
140 _contextStack.push(CMappingContext(_contextMappingKeyArray.size()));
141
142 // Map all instantiated subelements in subsystem
143 uint32_t uiNbChildren = getNbChildren();
144 uint32_t uiChild;
145
146 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
147
148 CInstanceConfigurableElement* pInstanceConfigurableChildElement = static_cast<CInstanceConfigurableElement*>(getChild(uiChild));
149
150 if (!pInstanceConfigurableChildElement->map(*this, strError)) {
151
152 return false;
153 }
154 }
155 return true;
156}
157
158// Parameter access
Patrick Benavoli065264a2011-11-20 15:46:41 +0100159bool CSubsystem::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200160{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200161 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100162 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200163
Patrick Benavoli065264a2011-11-20 15:46:41 +0100164 return base::accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200165}
166
167void CSubsystem::logValue(string& strValue, CErrorContext& errorContext) const
168{
Patrick Benavoli065264a2011-11-20 15:46:41 +0100169 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200170
171 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100172 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200173
174 return base::logValue(strValue, errorContext);
175}
176
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100177// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200178void CSubsystem::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
179{
180 // Deal with Endianness
181 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
182
183 base::setDefaultValues(parameterAccessContext);
184}
185
186// Belonging subsystem
187const CSubsystem* CSubsystem::getBelongingSubsystem() const
188{
189 return this;
190}
191
192// Subsystem context mapping keys publication
193void CSubsystem::addContextMappingKey(const string& strMappingKey)
194{
195 _contextMappingKeyArray.push_back(strMappingKey);
196}
197
198// Subsystem object creator publication (strong reference)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200199void CSubsystem::addSubsystemObjectFactory(CSubsystemObjectCreator* pSubsystemObjectCreator)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200200{
201 _subsystemObjectCreatorArray.push_back(pSubsystemObjectCreator);
202}
203
204// Mapping generic context handling
205bool CSubsystem::handleMappingContext(const CInstanceConfigurableElement* pInstanceConfigurableElement, CMappingContext& context, string& strError)
206{
207 // Feed context with found mapping data
208 uint32_t uiItem;
209
210 for (uiItem = 0; uiItem < _contextMappingKeyArray.size(); uiItem++) {
211
212 string strKey = _contextMappingKeyArray[uiItem];
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200213 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200214
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200215 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200216 // Assign item to context
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200217 if (!context.setItem(uiItem, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200218
219 getMappingError(strError, strKey, "Already set", pInstanceConfigurableElement);
220
221 return false;
222 }
223 }
224 }
225 return true;
226}
227
228// Creation handling
229bool CSubsystem::handleSubsystemObjectCreation(CInstanceConfigurableElement* pInstanceConfigurableElement, CMappingContext& context, string& strError)
230{
231 uint32_t uiItem;
232
233 for (uiItem = 0; uiItem < _subsystemObjectCreatorArray.size(); uiItem++) {
234
235 const CSubsystemObjectCreator* pSubsystemObjectCreator = _subsystemObjectCreatorArray[uiItem];
236
237 // Mapping key
238 string strKey = pSubsystemObjectCreator->getMappingKey();
239 // Object id
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200240 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200241
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200242 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200243
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100244 // First check context consistency (required ancestors must have been set prior to object creation)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200245 uint32_t uiAncestorKey;
246 uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask();
247
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200248 for (uiAncestorKey = 0; uiAncestorKey < _contextMappingKeyArray.size(); uiAncestorKey++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200249
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200250 if (!((1 << uiAncestorKey) & uiAncestorMask)) {
251 // Ancestor not required
252 continue;
253 }
254 // Check ancestor was provided
Patrick Benavoli68a91282011-08-31 11:23:23 +0200255 if (!context.iSet(uiAncestorKey)) {
256
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200257 getMappingError(strError, strKey, _contextMappingKeyArray[uiAncestorKey] + " not set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200258
259 return false;
260 }
261 }
262
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200263 // Then check configurable element size is correct
264 if (pInstanceConfigurableElement->getFootPrint() > pSubsystemObjectCreator->getMaxConfigurableElementSize()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200265
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100266 string strSizeError = "Size should not exceed " + pSubsystemObjectCreator->getMaxConfigurableElementSize();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200267
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200268 getMappingError(strError, strKey, strSizeError, pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200269
270 return false;
271 }
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200272
273 // Do create object and keep its track
274 _subsystemObjectList.push_back(pSubsystemObjectCreator->objectCreate(*pStrValue, pInstanceConfigurableElement, context));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200275
276 // Done
277 return true;
278 }
279 }
280 getMappingError(strError, "Mapping key", "Not found", pInstanceConfigurableElement);
281
282 return false;
283}
284
285// Generic error handling from derived subsystem classes
286void CSubsystem::getMappingError(string& strError, const string& strKey, const string& strMessage, const CInstanceConfigurableElement* pInstanceConfigurableElement)
287{
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100288 strError = getName() + " " + getKind() + " mapping:\n" + strKey + " error: \"" + strMessage + "\" for element " + pInstanceConfigurableElement->getPath();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200289}
290
291// From IMapper
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100292bool CSubsystem::mapBegin(CInstanceConfigurableElement* pInstanceConfigurableElement, bool& bKeepDiving, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200293{
294 // Get current context
295 CMappingContext context = _contextStack.top();
296
297 switch(pInstanceConfigurableElement->getType()) {
298
299 case CInstanceConfigurableElement::EComponent:
300
301 if (!handleMappingContext(pInstanceConfigurableElement, context, strError)) {
302
303 return false;
304 }
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100305
306 // Push context
307 _contextStack.push(context);
308
309 // Keep diving
310 bKeepDiving = true;
311
312 return true;
313
Patrick Benavoli68a91282011-08-31 11:23:23 +0200314 case CInstanceConfigurableElement::EParameterBlock:
315 case CInstanceConfigurableElement::EBitParameterBlock:
316 case CInstanceConfigurableElement::EParameter:
Patrick Benavoli1352ae52011-10-21 16:48:04 +0200317 case CInstanceConfigurableElement::EStringParameter:
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100318
Patrick Benavoli68a91282011-08-31 11:23:23 +0200319 if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context, strError)) {
320
321 return false;
322 }
Patrick Benavolid3a86bf2011-11-07 19:33:30 +0100323
324 // Done
325 bKeepDiving = false;
326
327 return true;
328
Patrick Benavoli68a91282011-08-31 11:23:23 +0200329 default:
330 assert(0);
331 return false;
332 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200333}
334
335void CSubsystem::mapEnd()
336{
337 // Unstack context
338 _contextStack.pop();
339}