1 /*
2 * Copyright (c) 2011-2015, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "BitParameterType.h"
31 #include "BitParameter.h"
32 #include <stdlib.h>
33 #include <sstream>
34 #include "ParameterAccessContext.h"
35 #include "BitParameterBlockType.h"
36 #include "Utility.h"
37
38 #define base CTypeElement
39
40 using std::string;
41
CBitParameterType(const string & strName)42 CBitParameterType::CBitParameterType(const string& strName) : base(strName), _uiBitPos(0), _uiBitSize(0), _uiMax(uint64_t(-1))
43 {
44 }
45
46 // CElement
getKind() const47 string CBitParameterType::getKind() const
48 {
49 return "BitParameter";
50 }
51
52 // Element properties
showProperties(string & strResult) const53 void CBitParameterType::showProperties(string& strResult) const
54 {
55 base::showProperties(strResult);
56
57 // Bit Pos
58 strResult += "Bit pos: ";
59 strResult += CUtility::toString(_uiBitPos);
60 strResult += "\n";
61
62 // Bit size
63 strResult += "Bit size: ";
64 strResult += CUtility::toString(_uiBitSize);
65 strResult += "\n";
66
67 // Max
68 strResult += "Max: ";
69 strResult += CUtility::toString(_uiMax);
70 strResult += "\n";
71 }
72
73 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)74 bool CBitParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
75 {
76 // Pos
77 _uiBitPos = xmlElement.getAttributeInteger("Pos");
78
79 // Size
80 _uiBitSize = xmlElement.getAttributeInteger("Size");
81
82 // Validate bit pos and size still fit into parent type
83 const CBitParameterBlockType* pBitParameterBlockType = static_cast<const CBitParameterBlockType*>(getParent());
84
85 uint32_t uiParentBlockBitSize = pBitParameterBlockType->getSize() * 8;
86
87 if (_uiBitPos + _uiBitSize > uiParentBlockBitSize) {
88
89 // Range exceeded
90 std::ostringstream strStream;
91
92 strStream << "Pos and Size attributes inconsistent with maximum container element size (" << uiParentBlockBitSize << " bits) for " + getKind();
93
94 serializingContext.setError(strStream.str());
95
96 return false;
97 }
98
99 // Max
100 if (xmlElement.hasAttribute("Max")) {
101
102 _uiMax = xmlElement.getAttributeInteger("Max");
103
104 if (_uiMax > getMaxEncodableValue()) {
105
106 // Max value exceeded
107 std::ostringstream strStream;
108
109 strStream << "Max attribute inconsistent with maximum encodable size (" << getMaxEncodableValue() << ") for " + getKind();
110
111 serializingContext.setError(strStream.str());
112
113 return false;
114 }
115 } else {
116
117 _uiMax = getMaxEncodableValue();
118 }
119
120 // Base
121 return base::fromXml(xmlElement, serializingContext);
122 }
123
124 // Conversion
toBlackboard(const string & strValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const125 bool CBitParameterType::toBlackboard(const string& strValue, uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
126 {
127 // Hexa
128 bool bValueProvidedAsHexa = !strValue.compare(0, 2, "0x");
129
130 // Get value
131 uint64_t uiConvertedValue = strtoull(strValue.c_str(), NULL, 0);
132
133 if (uiConvertedValue > _uiMax) {
134
135 // Range exceeded
136 std::ostringstream strStream;
137
138 strStream << "Value " << strValue << " standing out of admitted range [";
139
140 if (bValueProvidedAsHexa) {
141
142 strStream << "0x0, " << "0x" << std::hex << std::uppercase;
143 } else {
144
145 strStream << "0, ";
146 }
147 strStream << _uiMax << "] for " + getKind();
148
149 parameterAccessContext.setError(strStream.str());
150
151 return false;
152 }
153
154 // Do bitwise RMW operation
155 uiValue = (uiValue & ~getMask()) | (uiConvertedValue << _uiBitPos);
156
157 return true;
158 }
159
fromBlackboard(string & strValue,const uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const160 void CBitParameterType::fromBlackboard(string& strValue, const uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
161 {
162 uint64_t uiConvertedValue = (uiValue & getMask()) >> _uiBitPos;
163
164 // Format
165 std::ostringstream strStream;
166
167 // Take care of format
168 if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) {
169
170 strStream << "0x" << std::hex << std::uppercase;
171 }
172
173 strStream << uiConvertedValue;
174
175 strValue = strStream.str();
176 }
177
178 // Value access
179 // Integer
toBlackboard(uint64_t uiUserValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const180 bool CBitParameterType::toBlackboard(uint64_t uiUserValue, uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
181 {
182 if (uiUserValue > _uiMax) {
183
184 parameterAccessContext.setError("Value out of range");
185
186 return false;
187 }
188
189 // Do bitwise RMW operation
190 uiValue = (uiValue & ~getMask()) | (uiUserValue << _uiBitPos);
191
192 return true;
193 }
194
fromBlackboard(uint32_t & uiUserValue,uint64_t uiValue,CParameterAccessContext & parameterAccessContext) const195 void CBitParameterType::fromBlackboard(uint32_t& uiUserValue, uint64_t uiValue, CParameterAccessContext& parameterAccessContext) const
196 {
197 (void)parameterAccessContext;
198
199 uiUserValue = (uiValue & getMask()) >> _uiBitPos;
200 }
201
202 // Access from area configuration
merge(uint64_t uiOriginData,uint64_t uiNewData) const203 uint64_t CBitParameterType::merge(uint64_t uiOriginData, uint64_t uiNewData) const
204 {
205 return (uiOriginData & ~getMask()) | (uiNewData & getMask());
206 }
207
208 // Bit Size
getBitSize() const209 uint32_t CBitParameterType::getBitSize() const
210 {
211 return _uiBitSize;
212 }
213
doInstantiate() const214 CInstanceConfigurableElement* CBitParameterType::doInstantiate() const
215 {
216 return new CBitParameter(getName(), this);
217 }
218
219 // Max value
getMaxEncodableValue() const220 uint64_t CBitParameterType::getMaxEncodableValue() const
221 {
222 return (uint64_t)-1L >> (8 * sizeof(uint64_t) - _uiBitSize);
223 }
224
225 // Biwise mask
getMask() const226 uint64_t CBitParameterType::getMask() const
227 {
228 return getMaxEncodableValue() << _uiBitPos;
229 }
230
231 // Check data has no bit set outside available range
isEncodable(uint64_t uiData) const232 bool CBitParameterType::isEncodable(uint64_t uiData) const
233 {
234 uint32_t uiShift = 8 * sizeof(uiData) - _uiBitSize;
235
236 if (uiShift) {
237
238 // Check high bits are clean
239 return !(uiData >> uiShift);
240 }
241
242 return true;
243 }
244
245 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const246 void CBitParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
247 {
248 // Position
249 xmlElement.setAttributeString("Pos", CUtility::toString(_uiBitPos));
250
251 // Size
252 xmlElement.setAttributeString("Size", CUtility::toString(_uiBitSize));
253
254 // Maximum
255 xmlElement.setAttributeString("Max", CUtility::toString(_uiMax));
256
257 base::toXml(xmlElement, serializingContext);
258
259 }
260