blob: 221b27a229b8789b0f1eae783d4f5111c34c3cd8 [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"
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +020032#include "MappingData.h"
Patrick Benavoli68a91282011-08-31 11:23:23 +020033#include <assert.h>
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +020034#include <sstream>
Patrick Benavoli68a91282011-08-31 11:23:23 +020035
36#define base CConfigurableElement
37
38CSubsystem::CSubsystem(const string& strName) : base(strName), _pComponentLibrary(new CComponentLibrary), _pInstanceDefinition(new CInstanceDefinition), _bBigEndian(false)
39{
40 // Note: A subsystem contains instance components
41 // InstanceDefintion and ComponentLibrary objects are then not chosen to be children
42 // They'll be delt with locally
43}
44
45CSubsystem::~CSubsystem()
46{
47 // Remove subsystem objects
48 SubsystemObjectListIterator subsystemObjectIt;
49
50 for (subsystemObjectIt = _subsystemObjectList.begin(); subsystemObjectIt != _subsystemObjectList.end(); ++subsystemObjectIt) {
51
52 delete *subsystemObjectIt;
53 }
54
55 // Remove susbsystem creators
56 uint32_t uiIndex;
57
58 for (uiIndex = 0; uiIndex < _subsystemObjectCreatorArray.size(); uiIndex++) {
59
60 delete _subsystemObjectCreatorArray[uiIndex];
61 }
62
63 // Order matters!
64 delete _pInstanceDefinition;
65 delete _pComponentLibrary;
66}
67
68string CSubsystem::getKind() const
69{
70 return "Subsystem";
71}
72
73// Susbsystem Endianness
74bool CSubsystem::isBigEndian() const
75{
76 return _bBigEndian;
77}
78
Guillaume Denneulinf2fd15a2012-12-20 17:53:29 +010079// Susbsystem sanity
80bool CSubsystem::isAlive() const
81{
82 return true;
83}
84
85// Resynchronization after subsystem restart needed
86bool CSubsystem::needResync(bool bClear)
87{
88 (void)bClear;
89
90 return false;
91}
92
Patrick Benavoli68a91282011-08-31 11:23:23 +020093// From IXmlSink
94bool CSubsystem::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
95{
96 // Context
97 CXmlParameterSerializingContext& parameterBuildContext = static_cast<CXmlParameterSerializingContext&>(serializingContext);
98
99 // Install temporary component library for further component creation
100 parameterBuildContext.setComponentLibrary(_pComponentLibrary);
101
102 CXmlElement childElement;
103
104 // XML populate ComponentLibrary
105 xmlElement.getChildElement("ComponentLibrary", childElement);
106
107 if (!_pComponentLibrary->fromXml(childElement, serializingContext)) {
108
109 return false;
110 }
111
112 // XML populate InstanceDefintion
113 xmlElement.getChildElement("InstanceDefintion", childElement);
114 if (!_pInstanceDefinition->fromXml(childElement, serializingContext)) {
115
116 return false;
117 }
118
119 // Create components
120 _pInstanceDefinition->createInstances(this);
121
122 // Execute mapping to create subsystem mapping entities
123 string strError;
124 if (!mapSubsystemElements(strError)) {
125
126 serializingContext.setError(strError);
127
128 return false;
129 }
130
131 // Endianness
132 _bBigEndian = xmlElement.getAttributeBoolean("Endianness", "Big");
133
134 return true;
135}
136
137// XML configuration settings parsing
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200138bool CSubsystem::serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200139{
140 // Fix Endianness
141 configurationAccessContext.setBigEndianSubsystem(_bBigEndian);
142
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200143 return base::serializeXmlSettings(xmlConfigurationSettingsElementContent, configurationAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200144}
145
146
147bool CSubsystem::mapSubsystemElements(string& strError)
148{
149 // Default mapping context
150 _contextStack.push(CMappingContext(_contextMappingKeyArray.size()));
151
152 // Map all instantiated subelements in subsystem
153 uint32_t uiNbChildren = getNbChildren();
154 uint32_t uiChild;
155
156 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
157
158 CInstanceConfigurableElement* pInstanceConfigurableChildElement = static_cast<CInstanceConfigurableElement*>(getChild(uiChild));
159
160 if (!pInstanceConfigurableChildElement->map(*this, strError)) {
161
162 return false;
163 }
164 }
165 return true;
166}
167
168// Parameter access
Patrick Benavoli065264a2011-11-20 15:46:41 +0100169bool CSubsystem::accessValue(CPathNavigator& pathNavigator, string& strValue, bool bSet, CParameterAccessContext& parameterAccessContext) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200170{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200171 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100172 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200173
Patrick Benavoli065264a2011-11-20 15:46:41 +0100174 return base::accessValue(pathNavigator, strValue, bSet, parameterAccessContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200175}
176
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200177// Formats the mapping of the ConfigurableElements
178string CSubsystem::formatMappingDataList(
179 const list<const CConfigurableElement*>& configurableElementPath) const
180{
181 // The list is parsed in reverse order because it has been filled from the leaf to the trunk
182 // of the tree. When formatting the mapping, we want to start from the subsystem level
183 ostringstream ossStream;
184 list<const CConfigurableElement*>::const_reverse_iterator it;
185 for (it = configurableElementPath.rbegin(); it != configurableElementPath.rend(); ++it) {
186
187 const CInstanceConfigurableElement* pInstanceConfigurableElement =
188 static_cast<const CInstanceConfigurableElement*>(*it);
189
190 ossStream << pInstanceConfigurableElement->getFormattedMapping() << ", ";
191 }
192 return ossStream.str();
193}
194
195// Find the CSubystemObject containing a specific CInstanceConfigurableElement
196const CSubsystemObject* CSubsystem::findSubsystemObjectFromConfigurableElement(
197 const CInstanceConfigurableElement* pInstanceConfigurableElement) const {
198
199 const CSubsystemObject* pSubsystemObject = NULL;
200
201 list<CSubsystemObject*>::const_iterator it;
202 for (it = _subsystemObjectList.begin(); it != _subsystemObjectList.end(); ++it) {
203
204 // Check if one of the SubsystemObjects is associated with a ConfigurableElement
205 // corresponding to the expected one
206 pSubsystemObject = *it;
207 if (pSubsystemObject->getConfigurableElement() == pInstanceConfigurableElement) {
208
209 break;
210 }
211 }
212
213 return pSubsystemObject;
214}
215
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200216void CSubsystem::findSubsystemLevelMappingKeyValue(
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200217 const CInstanceConfigurableElement* pInstanceConfigurableElement,
218 string& strMappingKey,
219 string& strMappingValue) const
220{
221 // Find creator to get key name
222 vector<CSubsystemObjectCreator*>::const_iterator it;
223 for (it = _subsystemObjectCreatorArray.begin();
224 it != _subsystemObjectCreatorArray.end(); ++it) {
225
226 const CSubsystemObjectCreator* pSubsystemObjectCreator = *it;
227
228 strMappingKey = pSubsystemObjectCreator->getMappingKey();
229
230 // Check if the ObjectCreator MappingKey corresponds to the element mapping data
231 const string* pStrValue;
232 if (pInstanceConfigurableElement->getMappingData(strMappingKey, pStrValue)) {
233
234 strMappingValue = *pStrValue;
235 return;
236 }
237 }
238 assert(0);
239}
240
241// Formats the mapping data as a comma separated list of key value pairs
242string CSubsystem::getFormattedSubsystemMappingData(
243 const CInstanceConfigurableElement* pInstanceConfigurableElement) const
244{
245 // Find the SubsystemObject related to pInstanceConfigurableElement
246 const CSubsystemObject* pSubsystemObject = findSubsystemObjectFromConfigurableElement(
247 pInstanceConfigurableElement);
248
249 // Exit if node does not correspond to a SubsystemObject
250 if (pSubsystemObject == NULL) {
251
252 return "";
253 }
254
255 // Find SubsystemCreator mapping key
256 string strMappingKey;
257 string strMappingValue; // mapping value where amends are not replaced by their value
Frédéric Boisnard487ce852013-07-19 17:17:52 +0200258 findSubsystemLevelMappingKeyValue(pInstanceConfigurableElement, strMappingKey, strMappingValue);
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200259
260 // Find SubSystemObject mapping value (with amends replaced by their value)
261 return strMappingKey + ":" + pSubsystemObject->getFormattedMappingValue();
262}
263
264string CSubsystem::getMapping(list<const CConfigurableElement*>& configurableElementPath) const
265{
266 if (configurableElementPath.empty()) {
267
268 return "";
269 }
270
271 // Get the first element, which is the element containing the amended mapping
272 const CInstanceConfigurableElement* pInstanceConfigurableElement =
273 static_cast<const CInstanceConfigurableElement*>(configurableElementPath.front());
274 configurableElementPath.pop_front();
275 // Now the list only contains elements whose mapping are related to the context
276
277 // Format context mapping data
278 string strValue = formatMappingDataList(configurableElementPath);
279
280 // Print the mapping of the first node, which corresponds to a SubsystemObject
281 strValue += getFormattedSubsystemMappingData(pInstanceConfigurableElement);
282
283 return strValue;
284}
285
Patrick Benavoli68a91282011-08-31 11:23:23 +0200286void CSubsystem::logValue(string& strValue, CErrorContext& errorContext) const
287{
Patrick Benavoli065264a2011-11-20 15:46:41 +0100288 CParameterAccessContext& parameterAccessContext = static_cast<CParameterAccessContext&>(errorContext);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200289
290 // Deal with Endianness
Patrick Benavoli065264a2011-11-20 15:46:41 +0100291 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200292
293 return base::logValue(strValue, errorContext);
294}
295
Patrick Benavoli6ccab9d2011-11-10 23:21:01 +0100296// Used for simulation and virtual subsystems
Patrick Benavoli68a91282011-08-31 11:23:23 +0200297void CSubsystem::setDefaultValues(CParameterAccessContext& parameterAccessContext) const
298{
299 // Deal with Endianness
300 parameterAccessContext.setBigEndianSubsystem(_bBigEndian);
301
302 base::setDefaultValues(parameterAccessContext);
303}
304
305// Belonging subsystem
306const CSubsystem* CSubsystem::getBelongingSubsystem() const
307{
308 return this;
309}
310
311// Subsystem context mapping keys publication
312void CSubsystem::addContextMappingKey(const string& strMappingKey)
313{
314 _contextMappingKeyArray.push_back(strMappingKey);
315}
316
317// Subsystem object creator publication (strong reference)
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200318void CSubsystem::addSubsystemObjectFactory(CSubsystemObjectCreator* pSubsystemObjectCreator)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200319{
320 _subsystemObjectCreatorArray.push_back(pSubsystemObjectCreator);
321}
322
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200323// Generic error handling from derived subsystem classes
324string CSubsystem::getMappingError(const string& strKey,
325 const string& strMessage,
326 const CInstanceConfigurableElement* pInstanceConfigurableElement)
327const
328{
329 return getName() + " " + getKind() + " " +
330 "mapping:\n" + strKey + " " +
331 "error: \"" + strMessage + "\" " +
332 "for element " + pInstanceConfigurableElement->getPath();
333}
334
Patrick Benavoli68a91282011-08-31 11:23:23 +0200335// Mapping generic context handling
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200336bool CSubsystem::handleMappingContext(
337 const CInstanceConfigurableElement* pInstanceConfigurableElement,
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200338 CMappingContext& context,
339 string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200340{
341 // Feed context with found mapping data
342 uint32_t uiItem;
343
Renaud de Chivre46966e02013-09-02 10:48:36 +0200344 for (uiItem = 0; uiItem < _contextMappingKeyArray.size(); uiItem++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200345
Renaud de Chivre46966e02013-09-02 10:48:36 +0200346 const string& strKey = _contextMappingKeyArray[uiItem];
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200347 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200348
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200349 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200350 // Assign item to context
Renaud de Chivre46966e02013-09-02 10:48:36 +0200351 if (!context.setItem(uiItem, &strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200352
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200353 strError = getMappingError(strKey, "Already set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200354
355 return false;
356 }
357 }
358 }
359 return true;
360}
361
Kevin Rocard084cafb2013-01-28 17:02:08 +0100362// Subsystem object creation handling
363bool CSubsystem::handleSubsystemObjectCreation(
364 CInstanceConfigurableElement* pInstanceConfigurableElement,
365 CMappingContext& context, bool& bHasCreatedSubsystemObject, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200366{
367 uint32_t uiItem;
Kevin Rocard084cafb2013-01-28 17:02:08 +0100368 bHasCreatedSubsystemObject = false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200369
370 for (uiItem = 0; uiItem < _subsystemObjectCreatorArray.size(); uiItem++) {
371
Kevin Rocard3414f992013-04-02 19:49:40 +0200372 const CSubsystemObjectCreator* pSubsystemObjectCreator =
373 _subsystemObjectCreatorArray[uiItem];
Patrick Benavoli68a91282011-08-31 11:23:23 +0200374
375 // Mapping key
376 string strKey = pSubsystemObjectCreator->getMappingKey();
377 // Object id
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200378 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200379
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200380 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200381
Kevin Rocard3414f992013-04-02 19:49:40 +0200382 // First check context consistency
383 // (required ancestors must have been set prior to object creation)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200384 uint32_t uiAncestorKey;
385 uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask();
386
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200387 for (uiAncestorKey = 0; uiAncestorKey < _contextMappingKeyArray.size(); uiAncestorKey++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200388
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200389 if (!((1 << uiAncestorKey) & uiAncestorMask)) {
390 // Ancestor not required
391 continue;
392 }
393 // Check ancestor was provided
Patrick Benavoli68a91282011-08-31 11:23:23 +0200394 if (!context.iSet(uiAncestorKey)) {
395
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200396 strError = getMappingError(strKey, _contextMappingKeyArray[uiAncestorKey] +
397 " not set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200398
399 return false;
400 }
401 }
402
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200403 // Then check configurable element size is correct
Kevin Rocard3414f992013-04-02 19:49:40 +0200404 if (pInstanceConfigurableElement->getFootPrint() >
405 pSubsystemObjectCreator->getMaxConfigurableElementSize()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200406
Kevin Rocard3414f992013-04-02 19:49:40 +0200407 string strSizeError = "Size should not exceed " +
408 pSubsystemObjectCreator->getMaxConfigurableElementSize();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200409
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200410 strError = getMappingError(strKey, strSizeError, pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200411
412 return false;
413 }
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200414
415 // Do create object and keep its track
Kevin Rocard3414f992013-04-02 19:49:40 +0200416 _subsystemObjectList.push_back(pSubsystemObjectCreator->objectCreate(
417 *pStrValue, pInstanceConfigurableElement, context));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200418
Kevin Rocard084cafb2013-01-28 17:02:08 +0100419 // Indicate subsytem creation to caller
420 bHasCreatedSubsystemObject = true;
421
422 // The subsystem Object has been instantiated, no need to continue looking for an
423 // instantiation mapping
424 break;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200425 }
426 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200427
Kevin Rocard084cafb2013-01-28 17:02:08 +0100428 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200429}
430
Patrick Benavoli68a91282011-08-31 11:23:23 +0200431// From IMapper
Kevin Rocard084cafb2013-01-28 17:02:08 +0100432// Handle a configurable element mapping
433bool CSubsystem::mapBegin(CInstanceConfigurableElement* pInstanceConfigurableElement,
434 bool& bKeepDiving, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200435{
436 // Get current context
437 CMappingContext context = _contextStack.top();
438
Kevin Rocard084cafb2013-01-28 17:02:08 +0100439 // Add mapping in context
Renaud de Chivre46966e02013-09-02 10:48:36 +0200440 if (!handleMappingContext(pInstanceConfigurableElement, context,
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200441 strError)) {
Kevin Rocard084cafb2013-01-28 17:02:08 +0100442
443 return false;
444 }
445
446 // Push context
447 _contextStack.push(context);
448
449 // Assume diving by default
450 bKeepDiving = true;
451
452 // Deal with ambiguous usage of parameter blocks
453 bool bShouldCreateSubsystemObject = true;
454
Patrick Benavoli68a91282011-08-31 11:23:23 +0200455 switch(pInstanceConfigurableElement->getType()) {
456
Kevin Rocard084cafb2013-01-28 17:02:08 +0100457 case CInstanceConfigurableElement::EComponent:
458 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200459
Kevin Rocard084cafb2013-01-28 17:02:08 +0100460 case CInstanceConfigurableElement::EParameterBlock:
461 // Subsystem object creation is optional in parameter blocks
462 bShouldCreateSubsystemObject = false;
463 // No break
464 case CInstanceConfigurableElement::EBitParameterBlock:
465 case CInstanceConfigurableElement::EParameter:
466 case CInstanceConfigurableElement::EStringParameter:
Patrick Benavoli68a91282011-08-31 11:23:23 +0200467
Kevin Rocard084cafb2013-01-28 17:02:08 +0100468 bool bHasCreatedSubsystemObject;
469
470 if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context,
471 bHasCreatedSubsystemObject, strError)) {
472
473 return false;
474 }
475 // Check for creation error
476 if (bShouldCreateSubsystemObject && !bHasCreatedSubsystemObject) {
477
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200478 strError = getMappingError("Not found",
479 "Subsystem object mapping key is missing",
480 pInstanceConfigurableElement);
Kevin Rocard084cafb2013-01-28 17:02:08 +0100481 return false;
482 }
483 // Not created and no error, keep diving
484 bKeepDiving = !bHasCreatedSubsystemObject;
485
486 return true;
487
488 default:
489 assert(0);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200490 return false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200491 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200492}
493
494void CSubsystem::mapEnd()
495{
496 // Unstack context
497 _contextStack.pop();
498}