blob: feac79dac3bfbff940fb103205e5c2e693fae863 [file] [log] [blame]
Kevin Rocard93250d12012-07-19 17:48:30 +02001/*
Patrick Benavoli68a91282011-08-31 11:23:23 +02002 * INTEL CONFIDENTIAL
3 * Copyright © 2011 Intel
4 * Corporation All Rights Reserved.
5 *
6 * The source code contained or described herein and all documents related to
7 * the source code ("Material") are owned by Intel Corporation or its suppliers
8 * or licensors. Title to the Material remains with Intel Corporation or its
9 * suppliers and licensors. The Material contains trade secrets and proprietary
10 * and confidential information of Intel or its suppliers and licensors. The
11 * Material is protected by worldwide copyright and trade secret laws and
12 * treaty provisions. No part of the Material may be used, copied, reproduced,
13 * modified, published, uploaded, posted, transmitted, distributed, or
14 * disclosed in any way without Intel’s prior express written permission.
15 *
16 * No license under any patent, copyright, trade secret or other intellectual
17 * property right is granted to or conferred upon you by disclosure or delivery
18 * of the Materials, either expressly, by implication, inducement, estoppel or
19 * otherwise. Any license under such intellectual property rights must be
20 * express and approved by Intel in writing.
21 *
Patrick Benavoli68a91282011-08-31 11:23:23 +020022 * CREATED: 2011-06-01
23 * UPDATED: 2011-07-27
Patrick Benavoli68a91282011-08-31 11:23:23 +020024 */
25#include "Subsystem.h"
26#include "ComponentLibrary.h"
27#include "InstanceDefinition.h"
28#include "XmlParameterSerializingContext.h"
29#include "ParameterAccessContext.h"
30#include "ConfigurationAccessContext.h"
31#include "SubsystemObjectCreator.h"
32#include <assert.h>
33
34#define base CConfigurableElement
35
36CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false)
37{
38 // Note: A subsystem contains instance components
39 // InstanceDefintion and ComponentLibrary objects are then not chosen to be children
40 // They'll be delt with locally
41}
42
43CSubsystem::~CSubsystem()
44{
45 // Remove subsystem objects
46 SubsystemObjectListIterator subsystemObjectIt;
47
48 for (subsystemObjectIt = _subsystemObjectList.begin(); subsystemObjectIt != _subsystemObjectList.end(); ++subsystemObjectIt) {
49
50 delete *subsystemObjectIt;
51 }
52
53 // Remove susbsystem creators
54 uint32_t uiIndex;
55
56 for (uiIndex = 0; uiIndex < _subsystemObjectCreatorArray.size(); uiIndex++) {
57
58 delete _subsystemObjectCreatorArray[uiIndex];
59 }
60
61 // Order matters!
62 delete _pInstanceDefinition;
63 delete _pComponentLibrary;
64}
65
66string CSubsystem::getKind() const
67{
68 return "Subsystem";
69}
70
71// Susbsystem Endianness
72bool CSubsystem::isBigEndian() const
73{
74 return _bBigEndian;
75}
76
Guillaume Denneulinf2fd15a2012-12-20 17:53:29 +010077// Susbsystem sanity
78bool CSubsystem::isAlive() const
79{
80 return true;
81}
82
83// Resynchronization after subsystem restart needed
84bool CSubsystem::needResync(bool bClear)
85{
86 (void)bClear;
87
88 return false;
89}
90
Patrick Benavoli68a91282011-08-31 11:23:23 +020091// From IXmlSink
92bool CSubsystem::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
93{
94 // Context
95 CXmlParameterSerializingContext& parameterBuildContext = static_cast<CXmlParameterSerializingContext&>(serializingContext);
96
97 // Install temporary component library for further component creation
98 parameterBuildContext.setComponentLibrary(_pComponentLibrary);
99
100 CXmlElement childElement;
101
102 // XML populate ComponentLibrary
103 xmlElement.getChildElement("ComponentLibrary", childElement);
104
105 if (!_pComponentLibrary->fromXml(childElement, serializingContext)) {
106
107 return false;
108 }
109
110 // XML populate InstanceDefintion
111 xmlElement.getChildElement("InstanceDefintion", childElement);
112 if (!_pInstanceDefinition->fromXml(childElement, serializingContext)) {
113
114 return false;
115 }
116
117 // Create components
118 _pInstanceDefinition->createInstances(this);
119
120 // Execute mapping to create subsystem mapping entities
121 string strError;
122 if (!mapSubsystemElements(strError)) {
123
124 serializingContext.setError(strError);
125
126 return false;
127 }
128
129 // Endianness
130 _bBigEndian = xmlElement.getAttributeBoolean("Endianness", "Big");
131
132 return true;
133}
134
135// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200136bool CSubsystem::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200137{
138 // Fix Endianness
139 configurationAccessContext.setBigEndianSubsystem(_bBigEndian);
140
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200141 return base::serializeXmlSettings(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200142}
143
144
145bool CSubsystem::mapSubsystemElements(string& strError)
146{
147 // Default mapping context
148 _contextStack.push(CMappingContext(_contextMappingKeyArray.size()));
149
150 // Map all instantiated subelements in subsystem
151 uint32_t uiNbChildren = getNbChildren();
152 uint32_t uiChild;
153
154 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
155
156 CInstanceConfigurableElement* pInstanceConfigurableChildElement = static_cast<CInstanceConfigurableElement*>(getChild(uiChild));
157
158 if (!pInstanceConfigurableChildElement->map(*this, strError)) {
159
160 return false;
161 }
162 }
163 return true;
164}
165
166// Parameter access
Patrick Benavoli065264a2011-11-20 15:46:41 +0100167bool CSubsystem::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200168{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200169 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100170 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200171
Patrick Benavoli065264a2011-11-20 15:46:41 +0100172 return base::accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200173}
174
175void CSubsystem::logValue(string& strValue, CErrorContext& errorContext) const
176{
Patrick Benavoli065264a2011-11-20 15:46:41 +0100177 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200178
179 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100180 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200181
182 return base::logValue(strValue, errorContext);
183}
184
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100185// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200186void CSubsystem::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
187{
188 // Deal with Endianness
189 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
190
191 base::setDefaultValues(parameterAccessContext);
192}
193
194// Belonging subsystem
195const CSubsystem* CSubsystem::getBelongingSubsystem() const
196{
197 return this;
198}
199
200// Subsystem context mapping keys publication
201void CSubsystem::addContextMappingKey(const string& strMappingKey)
202{
203 _contextMappingKeyArray.push_back(strMappingKey);
204}
205
206// Subsystem object creator publication (strong reference)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200207void CSubsystem::addSubsystemObjectFactory(CSubsystemObjectCreator* pSubsystemObjectCreator)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200208{
209 _subsystemObjectCreatorArray.push_back(pSubsystemObjectCreator);
210}
211
212// Mapping generic context handling
213bool CSubsystem::handleMappingContext(const CInstanceConfigurableElement* pInstanceConfigurableElement, CMappingContext& context, string& strError)
214{
215 // Feed context with found mapping data
216 uint32_t uiItem;
217
218 for (uiItem = 0; uiItem < _contextMappingKeyArray.size(); uiItem++) {
219
220 string strKey = _contextMappingKeyArray[uiItem];
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200221 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200222
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200223 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200224 // Assign item to context
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200225 if (!context.setItem(uiItem, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200226
227 getMappingError(strError, strKey, "Already set", pInstanceConfigurableElement);
228
229 return false;
230 }
231 }
232 }
233 return true;
234}
235
Kevin Rocard084cafb2013-01-28 17:02:08 +0100236// Subsystem object creation handling
237bool CSubsystem::handleSubsystemObjectCreation(
238 CInstanceConfigurableElement* pInstanceConfigurableElement,
239 CMappingContext& context, bool& bHasCreatedSubsystemObject, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200240{
241 uint32_t uiItem;
Kevin Rocard084cafb2013-01-28 17:02:08 +0100242 bHasCreatedSubsystemObject = false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200243
244 for (uiItem = 0; uiItem < _subsystemObjectCreatorArray.size(); uiItem++) {
245
Kevin Rocard3414f992013-04-02 19:49:40 +0200246 const CSubsystemObjectCreator* pSubsystemObjectCreator =
247 _subsystemObjectCreatorArray[uiItem];
Patrick Benavoli68a91282011-08-31 11:23:23 +0200248
249 // Mapping key
250 string strKey = pSubsystemObjectCreator->getMappingKey();
251 // Object id
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200252 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200253
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200254 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200255
Kevin Rocard3414f992013-04-02 19:49:40 +0200256 // First check context consistency
257 // (required ancestors must have been set prior to object creation)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200258 uint32_t uiAncestorKey;
259 uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask();
260
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200261 for (uiAncestorKey = 0; uiAncestorKey < _contextMappingKeyArray.size(); uiAncestorKey++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200262
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200263 if (!((1 << uiAncestorKey) & uiAncestorMask)) {
264 // Ancestor not required
265 continue;
266 }
267 // Check ancestor was provided
Patrick Benavoli68a91282011-08-31 11:23:23 +0200268 if (!context.iSet(uiAncestorKey)) {
269
Kevin Rocard3414f992013-04-02 19:49:40 +0200270 getMappingError(strError, strKey, _contextMappingKeyArray[uiAncestorKey] +
271 " not set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200272
273 return false;
274 }
275 }
276
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200277 // Then check configurable element size is correct
Kevin Rocard3414f992013-04-02 19:49:40 +0200278 if (pInstanceConfigurableElement->getFootPrint() >
279 pSubsystemObjectCreator->getMaxConfigurableElementSize()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200280
Kevin Rocard3414f992013-04-02 19:49:40 +0200281 string strSizeError = "Size should not exceed " +
282 pSubsystemObjectCreator->getMaxConfigurableElementSize();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200283
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200284 getMappingError(strError, strKey, strSizeError, pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200285
286 return false;
287 }
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200288
289 // Do create object and keep its track
Kevin Rocard3414f992013-04-02 19:49:40 +0200290 _subsystemObjectList.push_back(pSubsystemObjectCreator->objectCreate(
291 *pStrValue, pInstanceConfigurableElement, context));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200292
Kevin Rocard084cafb2013-01-28 17:02:08 +0100293 // Indicate subsytem creation to caller
294 bHasCreatedSubsystemObject = true;
295
296 // The subsystem Object has been instantiated, no need to continue looking for an
297 // instantiation mapping
298 break;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200299 }
300 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200301
Kevin Rocard084cafb2013-01-28 17:02:08 +0100302 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200303}
304
305// Generic error handling from derived subsystem classes
Kevin Rocard3414f992013-04-02 19:49:40 +0200306void CSubsystem::getMappingError(string& strError, const string& strKey, const string& strMessage,
307 const CInstanceConfigurableElement* pInstanceConfigurableElement)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200308{
Kevin Rocard3414f992013-04-02 19:49:40 +0200309 strError = getName() + " " + getKind() + " "
310 "mapping:\n" + strKey + " "
311 "error: \"" + strMessage + "\" "
312 "for element " + pInstanceConfigurableElement->getPath();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200313}
314
315// From IMapper
Kevin Rocard084cafb2013-01-28 17:02:08 +0100316// Handle a configurable element mapping
317bool CSubsystem::mapBegin(CInstanceConfigurableElement* pInstanceConfigurableElement,
318 bool& bKeepDiving, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200319{
320 // Get current context
321 CMappingContext context = _contextStack.top();
322
Kevin Rocard084cafb2013-01-28 17:02:08 +0100323 // Add mapping in context
324 if (!handleMappingContext(pInstanceConfigurableElement, context, strError)) {
325
326 return false;
327 }
328
329 // Push context
330 _contextStack.push(context);
331
332 // Assume diving by default
333 bKeepDiving = true;
334
335 // Deal with ambiguous usage of parameter blocks
336 bool bShouldCreateSubsystemObject = true;
337
Patrick Benavoli68a91282011-08-31 11:23:23 +0200338 switch(pInstanceConfigurableElement->getType()) {
339
Kevin Rocard084cafb2013-01-28 17:02:08 +0100340 case CInstanceConfigurableElement::EComponent:
341 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200342
Kevin Rocard084cafb2013-01-28 17:02:08 +0100343 case CInstanceConfigurableElement::EParameterBlock:
344 // Subsystem object creation is optional in parameter blocks
345 bShouldCreateSubsystemObject = false;
346 // No break
347 case CInstanceConfigurableElement::EBitParameterBlock:
348 case CInstanceConfigurableElement::EParameter:
349 case CInstanceConfigurableElement::EStringParameter:
Patrick Benavoli68a91282011-08-31 11:23:23 +0200350
Kevin Rocard084cafb2013-01-28 17:02:08 +0100351 bool bHasCreatedSubsystemObject;
352
353 if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context,
354 bHasCreatedSubsystemObject, strError)) {
355
356 return false;
357 }
358 // Check for creation error
359 if (bShouldCreateSubsystemObject && !bHasCreatedSubsystemObject) {
360
361 getMappingError(strError, "Not found",
362 "Subsystem object mapping key is missing",
363 pInstanceConfigurableElement);
364 return false;
365 }
366 // Not created and no error, keep diving
367 bKeepDiving = !bHasCreatedSubsystemObject;
368
369 return true;
370
371 default:
372 assert(0);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200373 return false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200374 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200375}
376
377void CSubsystem::mapEnd()
378{
379 // Unstack context
380 _contextStack.pop();
381}