blob: 5ae04d297669ca432a8654717dddddcf1fddaa6e [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
216void CSubsystem::findSusbystemLevelMappingKeyValue(
217 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
258 findSusbystemLevelMappingKeyValue(pInstanceConfigurableElement, strMappingKey, strMappingValue);
259
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,
338 const vector<string>& contextMappingKeyArray,
339 CMappingContext& context,
340 string& strError) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200341{
342 // Feed context with found mapping data
343 uint32_t uiItem;
344
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200345 for (uiItem = 0; uiItem < contextMappingKeyArray.size(); uiItem++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200346
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200347 string strKey = contextMappingKeyArray[uiItem];
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200348 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200349
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200350 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200351 // Assign item to context
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200352 if (!context.setItem(uiItem, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200353
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200354 strError = getMappingError(strKey, "Already set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200355
356 return false;
357 }
358 }
359 }
360 return true;
361}
362
Kevin Rocard084cafb2013-01-28 17:02:08 +0100363// Subsystem object creation handling
364bool CSubsystem::handleSubsystemObjectCreation(
365 CInstanceConfigurableElement* pInstanceConfigurableElement,
366 CMappingContext& context, bool& bHasCreatedSubsystemObject, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200367{
368 uint32_t uiItem;
Kevin Rocard084cafb2013-01-28 17:02:08 +0100369 bHasCreatedSubsystemObject = false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200370
371 for (uiItem = 0; uiItem < _subsystemObjectCreatorArray.size(); uiItem++) {
372
Kevin Rocard3414f992013-04-02 19:49:40 +0200373 const CSubsystemObjectCreator* pSubsystemObjectCreator =
374 _subsystemObjectCreatorArray[uiItem];
Patrick Benavoli68a91282011-08-31 11:23:23 +0200375
376 // Mapping key
377 string strKey = pSubsystemObjectCreator->getMappingKey();
378 // Object id
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200379 const string* pStrValue;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200380
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200381 if (pInstanceConfigurableElement->getMappingData(strKey, pStrValue)) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200382
Kevin Rocard3414f992013-04-02 19:49:40 +0200383 // First check context consistency
384 // (required ancestors must have been set prior to object creation)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200385 uint32_t uiAncestorKey;
386 uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask();
387
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200388 for (uiAncestorKey = 0; uiAncestorKey < _contextMappingKeyArray.size(); uiAncestorKey++) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200389
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200390 if (!((1 << uiAncestorKey) & uiAncestorMask)) {
391 // Ancestor not required
392 continue;
393 }
394 // Check ancestor was provided
Patrick Benavoli68a91282011-08-31 11:23:23 +0200395 if (!context.iSet(uiAncestorKey)) {
396
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200397 strError = getMappingError(strKey, _contextMappingKeyArray[uiAncestorKey] +
398 " not set", pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200399
400 return false;
401 }
402 }
403
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200404 // Then check configurable element size is correct
Kevin Rocard3414f992013-04-02 19:49:40 +0200405 if (pInstanceConfigurableElement->getFootPrint() >
406 pSubsystemObjectCreator->getMaxConfigurableElementSize()) {
Patrick Benavoli68a91282011-08-31 11:23:23 +0200407
Kevin Rocard3414f992013-04-02 19:49:40 +0200408 string strSizeError = "Size should not exceed " +
409 pSubsystemObjectCreator->getMaxConfigurableElementSize();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200410
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200411 strError = getMappingError(strKey, strSizeError, pInstanceConfigurableElement);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200412
413 return false;
414 }
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200415
416 // Do create object and keep its track
Kevin Rocard3414f992013-04-02 19:49:40 +0200417 _subsystemObjectList.push_back(pSubsystemObjectCreator->objectCreate(
418 *pStrValue, pInstanceConfigurableElement, context));
Patrick Benavoli68a91282011-08-31 11:23:23 +0200419
Kevin Rocard084cafb2013-01-28 17:02:08 +0100420 // Indicate subsytem creation to caller
421 bHasCreatedSubsystemObject = true;
422
423 // The subsystem Object has been instantiated, no need to continue looking for an
424 // instantiation mapping
425 break;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200426 }
427 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200428
Kevin Rocard084cafb2013-01-28 17:02:08 +0100429 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200430}
431
Patrick Benavoli68a91282011-08-31 11:23:23 +0200432// From IMapper
Kevin Rocard084cafb2013-01-28 17:02:08 +0100433// Handle a configurable element mapping
434bool CSubsystem::mapBegin(CInstanceConfigurableElement* pInstanceConfigurableElement,
435 bool& bKeepDiving, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200436{
437 // Get current context
438 CMappingContext context = _contextStack.top();
439
Kevin Rocard084cafb2013-01-28 17:02:08 +0100440 // Add mapping in context
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200441 if (!handleMappingContext(pInstanceConfigurableElement, _contextMappingKeyArray, context,
442 strError)) {
Kevin Rocard084cafb2013-01-28 17:02:08 +0100443
444 return false;
445 }
446
447 // Push context
448 _contextStack.push(context);
449
450 // Assume diving by default
451 bKeepDiving = true;
452
453 // Deal with ambiguous usage of parameter blocks
454 bool bShouldCreateSubsystemObject = true;
455
Patrick Benavoli68a91282011-08-31 11:23:23 +0200456 switch(pInstanceConfigurableElement->getType()) {
457
Kevin Rocard084cafb2013-01-28 17:02:08 +0100458 case CInstanceConfigurableElement::EComponent:
459 return true;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200460
Kevin Rocard084cafb2013-01-28 17:02:08 +0100461 case CInstanceConfigurableElement::EParameterBlock:
462 // Subsystem object creation is optional in parameter blocks
463 bShouldCreateSubsystemObject = false;
464 // No break
465 case CInstanceConfigurableElement::EBitParameterBlock:
466 case CInstanceConfigurableElement::EParameter:
467 case CInstanceConfigurableElement::EStringParameter:
Patrick Benavoli68a91282011-08-31 11:23:23 +0200468
Kevin Rocard084cafb2013-01-28 17:02:08 +0100469 bool bHasCreatedSubsystemObject;
470
471 if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context,
472 bHasCreatedSubsystemObject, strError)) {
473
474 return false;
475 }
476 // Check for creation error
477 if (bShouldCreateSubsystemObject && !bHasCreatedSubsystemObject) {
478
Frederic Boisnard6cae0ec2013-05-23 18:48:58 +0200479 strError = getMappingError("Not found",
480 "Subsystem object mapping key is missing",
481 pInstanceConfigurableElement);
Kevin Rocard084cafb2013-01-28 17:02:08 +0100482 return false;
483 }
484 // Not created and no error, keep diving
485 bKeepDiving = !bHasCreatedSubsystemObject;
486
487 return true;
488
489 default:
490 assert(0);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200491 return false;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200492 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200493}
494
495void CSubsystem::mapEnd()
496{
497 // Unstack context
498 _contextStack.pop();
499}