Home | History | Annotate | Download | only in parameter
      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 
     47 CFixedPointParameterType::CFixedPointParameterType(const string& strName) : base(strName), _uiIntegral(0), _uiFractional(0)
     48 {
     49 }
     50 
     51 string CFixedPointParameterType::getKind() const
     52 {
     53     return "FixedPointParameter";
     54 }
     55 
     56 // Element properties
     57 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
     71 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 
     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 
    116 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 
    140 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 
    184 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
    225 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 
    247 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
    265 uint32_t CFixedPointParameterType::getUtilSizeInBits() const
    266 {
    267     return _uiIntegral + _uiFractional + 1;
    268 }
    269 
    270 // Compute the range for the type (minimum and maximum values)
    271 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 
    277 bool CFixedPointParameterType::isHexadecimal(const string& strValue) const
    278 {
    279     return !strValue.compare(0, 2, "0x");
    280 }
    281 
    282 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 
    300 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 
    314 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
    333 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
    343 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 
    356 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
    364 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