• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "FixedPointParameterType.h"
31 #include <stdlib.h>
32 #include <sstream>
33 #include <iomanip>
34 #include <assert.h>
35 #include <math.h>
36 #include "Parameter.h"
37 #include "ParameterAccessContext.h"
38 #include "ConfigurationAccessContext.h"
39 #include "Utility.h"
40 #include <errno.h>
41 #include <convert.hpp>
42 
43 #define base CParameterType
44 
45 using std::string;
46 
CFixedPointParameterType(const string & strName)47 CFixedPointParameterType::CFixedPointParameterType(const string& strName) : base(strName), _uiIntegral(0), _uiFractional(0)
48 {
49 }
50 
getKind() const51 string CFixedPointParameterType::getKind() const
52 {
53     return "FixedPointParameter";
54 }
55 
56 // Element properties
showProperties(string & strResult) const57 void CFixedPointParameterType::showProperties(string& strResult) const
58 {
59     base::showProperties(strResult);
60 
61     // Notation
62     strResult += "Notation: Q";
63     strResult += CUtility::toString(_uiIntegral);
64     strResult += ".";
65     strResult += CUtility::toString(_uiFractional);
66     strResult += "\n";
67 }
68 
69 // XML Serialization value space handling
70 // Value space handling for configuration import
handleValueSpaceAttribute(CXmlElement & xmlConfigurableElementSettingsElement,CConfigurationAccessContext & configurationAccessContext) const71 void CFixedPointParameterType::handleValueSpaceAttribute(CXmlElement& xmlConfigurableElementSettingsElement, CConfigurationAccessContext& configurationAccessContext) const
72 {
73     // Direction?
74     if (!configurationAccessContext.serializeOut()) {
75 
76         // Get Value space from XML
77         if (xmlConfigurableElementSettingsElement.hasAttribute("ValueSpace")) {
78 
79             configurationAccessContext.setValueSpaceRaw(xmlConfigurableElementSettingsElement.getAttributeBoolean("ValueSpace", "Raw"));
80         } else {
81 
82             configurationAccessContext.setValueSpaceRaw(false);
83         }
84     } else {
85         // Provide value space only if not the default one
86         if (configurationAccessContext.valueSpaceIsRaw()) {
87 
88             xmlConfigurableElementSettingsElement.setAttributeString("ValueSpace", "Raw");
89         }
90     }
91 }
92 
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)93 bool CFixedPointParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
94 {
95     // Size
96     uint32_t uiSizeInBits = xmlElement.getAttributeInteger("Size");
97 
98     // Q notation
99     _uiIntegral = xmlElement.getAttributeInteger("Integral");
100     _uiFractional = xmlElement.getAttributeInteger("Fractional");
101 
102     // Size vs. Q notation integrity check
103     if (uiSizeInBits < getUtilSizeInBits()) {
104 
105         serializingContext.setError("Inconsistent Size vs. Q notation for " + getKind() + " " + xmlElement.getPath() + ": Summing (Integral + _uiFractional + 1) should not exceed given Size (" + xmlElement.getAttributeString("Size") + ")");
106 
107         return false;
108     }
109 
110     // Set the size
111     setSize(uiSizeInBits / 8);
112 
113     return base::fromXml(xmlElement, serializingContext);
114 }
115 
toBlackboard(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const116 bool CFixedPointParameterType::toBlackboard(const string& strValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
117 {
118     bool bValueProvidedAsHexa = isHexadecimal(strValue);
119 
120     // Check data integrity
121     if (bValueProvidedAsHexa && !parameterAccessContext.valueSpaceIsRaw()) {
122 
123         parameterAccessContext.setError("Hexadecimal values are not supported for " + getKind() + " when selected value space is real:");
124 
125         return false;
126     }
127 
128     if (parameterAccessContext.valueSpaceIsRaw()) {
129 
130         if (bValueProvidedAsHexa) {
131 
132             return convertFromHexadecimal(strValue, uiValue, parameterAccessContext);
133 
134         }
135         return convertFromDecimal(strValue, uiValue, parameterAccessContext);
136     }
137     return convertFromQnm(strValue, uiValue, parameterAccessContext);
138 }
139 
setOutOfRangeError(const string & strValue,CParameterAccessContext & parameterAccessContext) const140 void CFixedPointParameterType::setOutOfRangeError(const string& strValue, CParameterAccessContext& parameterAccessContext) const
141 {
142     std::ostringstream strStream;
143 
144     strStream << "Value " << strValue << " standing out of admitted ";
145 
146     if (!parameterAccessContext.valueSpaceIsRaw()) {
147 
148         // Min/Max computation
149         double dMin = 0;
150         double dMax = 0;
151         getRange(dMin, dMax);
152 
153         strStream << std::fixed << std::setprecision(_uiFractional)
154                   << "real range [" << dMin << ", " << dMax << "]";
155     } else {
156 
157         // Min/Max computation
158         int32_t iMax = getMaxValue<uint32_t>();
159         int32_t iMin = -iMax - 1;
160 
161         strStream << "raw range [";
162 
163         if (isHexadecimal(strValue)) {
164 
165             // Format Min
166             strStream << "0x" << std::hex << std::uppercase <<
167                 std::setw(getSize() * 2) << std::setfill('0') << makeEncodable(iMin);
168             // Format Max
169             strStream << ", 0x" << std::hex << std::uppercase <<
170                 std::setw(getSize() * 2) << std::setfill('0') << makeEncodable(iMax);
171 
172         } else {
173 
174             strStream << iMin << ", " << iMax;
175         }
176 
177         strStream << "]";
178     }
179     strStream << " for " << getKind();
180 
181     parameterAccessContext.setError(strStream.str());
182 }
183 
fromBlackboard(string & strValue,const uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const184 bool CFixedPointParameterType::fromBlackboard(string& strValue, const uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
185 {
186     int32_t iData = uiValue;
187 
188     // Check encodability
189     assert(isEncodable((uint32_t)iData, false));
190 
191     // Format
192     std::ostringstream strStream;
193 
194     // Raw formatting?
195     if (parameterAccessContext.valueSpaceIsRaw()) {
196 
197         // Hexa formatting?
198         if (parameterAccessContext.outputRawFormatIsHex()) {
199 
200             strStream << "0x" << std::hex << std::uppercase << std::setw(getSize()*2) << std::setfill('0') << (uint32_t)iData;
201         } else {
202 
203             // Sign extend
204             signExtend(iData);
205 
206             strStream << iData;
207         }
208     } else {
209 
210         // Sign extend
211         signExtend(iData);
212 
213         // Conversion
214         double dData = binaryQnmToDouble(iData);
215 
216         strStream << std::fixed << std::setprecision(_uiFractional) << dData;
217     }
218 
219     strValue = strStream.str();
220 
221     return true;
222 }
223 
224 // Value access
toBlackboard(double dUserValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const225 bool CFixedPointParameterType::toBlackboard(double dUserValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
226 {
227     // Check that the value is within the allowed range for this type
228     if (!checkValueAgainstRange(dUserValue)) {
229 
230         // Illegal value provided
231         parameterAccessContext.setError("Value out of range");
232 
233         return false;
234     }
235 
236     // Do the conversion
237     int32_t iData = doubleToBinaryQnm(dUserValue);
238 
239     // Check integrity
240     assert(isEncodable((uint32_t)iData, true));
241 
242     uiValue = iData;
243 
244     return true;
245 }
246 
fromBlackboard(double & dUserValue,uint32_t uiValue,CParameterAccessContext & parameterAccessContext) const247 bool CFixedPointParameterType::fromBlackboard(double& dUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
248 {
249     (void)parameterAccessContext;
250 
251     int32_t iData = uiValue;
252 
253     // Check unsigned value is encodable
254     assert(isEncodable(uiValue, false));
255 
256     // Sign extend
257     signExtend(iData);
258 
259     dUserValue = binaryQnmToDouble(iData);
260 
261     return true;
262 }
263 
264 // Util size
getUtilSizeInBits() const265 uint32_t CFixedPointParameterType::getUtilSizeInBits() const
266 {
267     return _uiIntegral + _uiFractional + 1;
268 }
269 
270 // Compute the range for the type (minimum and maximum values)
getRange(double & dMin,double & dMax) const271 void CFixedPointParameterType::getRange(double& dMin, double& dMax) const
272 {
273     dMax = (double)((1UL << (_uiIntegral + _uiFractional)) - 1) / (1UL << _uiFractional);
274     dMin = -(double)(1UL << (_uiIntegral + _uiFractional)) / (1UL << _uiFractional);
275 }
276 
isHexadecimal(const string & strValue) const277 bool CFixedPointParameterType::isHexadecimal(const string& strValue) const
278 {
279     return !strValue.compare(0, 2, "0x");
280 }
281 
convertFromHexadecimal(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const282 bool CFixedPointParameterType::convertFromHexadecimal(const string& strValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
283 {
284     // For hexadecimal representation, we need full 32 bit range conversion.
285     uint32_t uiData;
286     if (!convertTo(strValue, uiData) || !isEncodable(uiData, false)) {
287 
288         setOutOfRangeError(strValue, parameterAccessContext);
289         return false;
290     }
291     signExtend((int32_t&)uiData);
292 
293     // check that the data is encodable and can been safely written to the blackboard
294     assert(isEncodable(uiData, true));
295     uiValue = uiData;
296 
297     return true;
298 }
299 
convertFromDecimal(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const300 bool CFixedPointParameterType::convertFromDecimal(const string& strValue, uint32_t& uiValue, CParameterAccessContext& parameterAccessContext) const
301 {
302     int32_t iData;
303 
304     if (!convertTo(strValue, iData) || !isEncodable((uint32_t)iData, true)) {
305 
306         setOutOfRangeError(strValue, parameterAccessContext);
307         return false;
308     }
309     uiValue = static_cast<uint32_t>(iData);
310 
311     return true;
312 }
313 
convertFromQnm(const string & strValue,uint32_t & uiValue,CParameterAccessContext & parameterAccessContext) const314 bool CFixedPointParameterType::convertFromQnm(const string& strValue, uint32_t& uiValue,
315                                               CParameterAccessContext& parameterAccessContext) const
316 {
317     double dData;
318 
319     if (!convertTo(strValue, dData) || !checkValueAgainstRange(dData)) {
320 
321         setOutOfRangeError(strValue, parameterAccessContext);
322         return false;
323     }
324     uiValue = static_cast<uint32_t>(doubleToBinaryQnm(dData));
325 
326     // check that the data is encodable and has been safely written to the blackboard
327     assert(isEncodable(uiValue, true));
328 
329     return true;
330 }
331 
332 // Check that the value is within available range for this type
checkValueAgainstRange(double dValue) const333 bool CFixedPointParameterType::checkValueAgainstRange(double dValue) const
334 {
335     double dMin = 0;
336     double dMax = 0;
337     getRange(dMin, dMax);
338 
339     return (dValue <= dMax) && (dValue >= dMin);
340 }
341 
342 // Data conversion
doubleToBinaryQnm(double dValue) const343 int32_t CFixedPointParameterType::doubleToBinaryQnm(double dValue) const
344 {
345     // For Qn.m number, multiply by 2^n and round to the nearest integer
346     int32_t iData = static_cast<int32_t>(round(dValue * (1UL << _uiFractional)));
347     // Left justify
348     // For a Qn.m number, shift 32 - (n + m + 1) bits to the left (the rest of
349     // the bits aren't used)
350     iData <<= getSize() * 8 - getUtilSizeInBits();
351 
352     return iData;
353 }
354 
355 
binaryQnmToDouble(int32_t iValue) const356 double CFixedPointParameterType::binaryQnmToDouble(int32_t iValue) const
357 {
358     // Unjustify
359     iValue >>= getSize() * 8 - getUtilSizeInBits();
360     return static_cast<double>(iValue) / (1UL << _uiFractional);
361 }
362 
363 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const364 void CFixedPointParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
365 {
366     // Size
367     xmlElement.setAttributeString("Size", CUtility::toString(getSize() * 8));
368 
369     // Integral
370     xmlElement.setAttributeString("Integral", CUtility::toString(_uiIntegral));
371 
372     // Fractional
373     xmlElement.setAttributeString("Fractional", CUtility::toString(_uiFractional));
374 
375     base::toXml(xmlElement, serializingContext);
376 }
377