summaryrefslogtreecommitdiffstats
path: root/parameter/Subsystem.cpp
blob: a501f910b550c58bc4b566d787431e6c45f111db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/* <auto_header>
 * <FILENAME>
 * 
 * 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
 * 
 * 
 * </auto_header>
 */
#include "Subsystem.h"
#include "ComponentLibrary.h"
#include "InstanceDefinition.h"
#include "XmlParameterSerializingContext.h"
#include "ParameterAccessContext.h"
#include "ConfigurationAccessContext.h"
#include "SubsystemObjectCreator.h"
#include <assert.h>

#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<CXmlParameterSerializingContext&>(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& xmlConfigurableElementSettingsElement, CConfigurationAccessContext& configurationAccessContext) const
{
    // Fix Endianness
    configurationAccessContext.setBigEndianSubsystem(_bBigEndian);

    return base::serializeXmlSettings(xmlConfigurableElementSettingsElement, 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<CInstanceConfigurableElement*>(getChild(uiChild));

        if (!pInstanceConfigurableChildElement->map(*this, strError)) {

            return false;
        }
    }
    return true;
}

// Parameter access
bool CSubsystem::setValue(CPathNavigator& pathNavigator, const string& strValue, CErrorContext& errorContext) const
{
    CParameterAccessContext& parameterContext = static_cast<CParameterAccessContext&>(errorContext);

    // Deal with Endianness
    parameterContext.setBigEndianSubsystem(_bBigEndian);

    return base::setValue(pathNavigator, strValue, errorContext);
}

bool CSubsystem::getValue(CPathNavigator& pathNavigator, string& strValue, CErrorContext& errorContext) const
{
    CParameterAccessContext& parameterContext = static_cast<CParameterAccessContext&>(errorContext);

    // Deal with Endianness
    parameterContext.setBigEndianSubsystem(_bBigEndian);

    return base::getValue(pathNavigator, strValue, errorContext);
}

void CSubsystem::logValue(string& strValue, CErrorContext& errorContext) const
{
    CParameterAccessContext& parameterContext = static_cast<CParameterAccessContext&>(errorContext);

    // Deal with Endianness
    parameterContext.setBigEndianSubsystem(_bBigEndian);

    return base::logValue(strValue, errorContext);
}

// Used for simulation only
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::addSubsystemObjectCreator(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];
        string strValue;

        if (pInstanceConfigurableElement->getMappingData(strKey, strValue)) {
            // Assign item to context
            if (!context.setItem(uiItem, strValue)) {

                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
        string strId;

        if (pInstanceConfigurableElement->getMappingData(strKey, strId)) {

            // First check context consisteny
            uint32_t uiAncestorKey;
            uint32_t uiAncestorMask = pSubsystemObjectCreator->getAncestorMask();

            for (uiAncestorKey = 0; uiAncestorKey & uiAncestorMask; uiAncestorKey++) {

                string strAncestorKey = _subsystemObjectCreatorArray[uiAncestorKey]->getMappingKey();

                if (!context.iSet(uiAncestorKey)) {

                    getMappingError(strError, strKey, strAncestorKey + " not set", pInstanceConfigurableElement);

                    return false;
                }
            }

            // Do create object
            string strCreationError;

            CSubsystemObject* pSubsystemObject = pSubsystemObjectCreator->objectCreate(strId, pInstanceConfigurableElement, context, strCreationError);

            if (!pSubsystemObject) {

                getMappingError(strError, strKey, strCreationError, pInstanceConfigurableElement);

                return false;
            }
            // Keep track of created object
            _subsystemObjectList.push_back(pSubsystemObject);

            // 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, string& strError)
{
    // Get current context
    CMappingContext context = _contextStack.top();

    switch(pInstanceConfigurableElement->getType()) {

    case CInstanceConfigurableElement::EComponent:

        if (!handleMappingContext(pInstanceConfigurableElement, context, strError)) {

            return false;
        }
        break;
    case CInstanceConfigurableElement::EParameterBlock:
    case CInstanceConfigurableElement::EBitParameterBlock:
    case CInstanceConfigurableElement::EParameter:
    {
        if (!handleSubsystemObjectCreation(pInstanceConfigurableElement, context, strError)) {

            return false;
        }
        break;
    }
    default:
        assert(0);
        return false;
    }

    // Push context
    _contextStack.push(context);

    return true;
}

void CSubsystem::mapEnd()
{
    // Unstack context
    _contextStack.pop();
}