/*
|
* Copyright (c) 2011-2015, Intel Corporation
|
* All rights reserved.
|
*
|
* Redistribution and use in source and binary forms, with or without modification,
|
* are permitted provided that the following conditions are met:
|
*
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
* list of conditions and the following disclaimer.
|
*
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
* this list of conditions and the following disclaimer in the documentation and/or
|
* other materials provided with the distribution.
|
*
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
* may be used to endorse or promote products derived from this software without
|
* specific prior written permission.
|
*
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
*/
|
#include "BitParameterType.h"
|
#include "BitParameter.h"
|
#include <stdlib.h>
|
#include <sstream>
|
#include "ParameterAccessContext.h"
|
#include "BitParameterBlockType.h"
|
#include "Utility.h"
|
|
#define base CTypeElement
|
|
using std::string;
|
|
CBitParameterType::CBitParameterType(const string &strName) : base(strName)
|
{
|
}
|
|
// CElement
|
string CBitParameterType::getKind() const
|
{
|
return "BitParameter";
|
}
|
|
// Element properties
|
void CBitParameterType::showProperties(string &strResult) const
|
{
|
base::showProperties(strResult);
|
|
// Bit Pos
|
strResult += "Bit pos: ";
|
strResult += std::to_string(_bitPos);
|
strResult += "\n";
|
|
// Bit size
|
strResult += "Bit size: ";
|
strResult += std::to_string(_uiBitSize);
|
strResult += "\n";
|
|
// Max
|
strResult += "Max: ";
|
strResult += std::to_string(_uiMax);
|
strResult += "\n";
|
}
|
|
// From IXmlSink
|
bool CBitParameterType::fromXml(const CXmlElement &xmlElement,
|
CXmlSerializingContext &serializingContext)
|
{
|
// Pos
|
xmlElement.getAttribute("Pos", _bitPos);
|
|
// Size
|
xmlElement.getAttribute("Size", _uiBitSize);
|
|
// Validate bit pos and size still fit into parent type
|
const CBitParameterBlockType *pBitParameterBlockType =
|
static_cast<const CBitParameterBlockType *>(getParent());
|
|
size_t uiParentBlockBitSize = pBitParameterBlockType->getSize() * 8;
|
|
if (_bitPos + _uiBitSize > uiParentBlockBitSize) {
|
|
// Range exceeded
|
std::ostringstream strStream;
|
|
strStream << "Pos and Size attributes inconsistent with maximum container element size ("
|
<< uiParentBlockBitSize << " bits) for " + getKind();
|
|
serializingContext.setError(strStream.str());
|
|
return false;
|
}
|
|
// Max
|
_uiMax = getMaxEncodableValue();
|
if (xmlElement.getAttribute("Max", _uiMax) && (_uiMax > getMaxEncodableValue())) {
|
|
// Max value exceeded
|
std::ostringstream strStream;
|
|
strStream << "Max attribute inconsistent with maximum encodable size ("
|
<< getMaxEncodableValue() << ") for " + getKind();
|
|
serializingContext.setError(strStream.str());
|
|
return false;
|
}
|
|
// Base
|
return base::fromXml(xmlElement, serializingContext);
|
}
|
|
// Conversion
|
bool CBitParameterType::toBlackboard(const string &strValue, uint64_t &uiValue,
|
CParameterAccessContext ¶meterAccessContext) const
|
{
|
// Get value
|
uint64_t uiConvertedValue = strtoull(strValue.c_str(), nullptr, 0);
|
|
if (uiConvertedValue > _uiMax) {
|
|
// Range exceeded
|
std::ostringstream strStream;
|
|
strStream << "Value " << strValue << " standing out of admitted range [";
|
|
if (utility::isHexadecimal(strValue)) {
|
|
strStream << "0x0, "
|
<< "0x" << std::hex << std::uppercase;
|
} else {
|
|
strStream << "0, ";
|
}
|
strStream << _uiMax << "] for " + getKind();
|
|
parameterAccessContext.setError(strStream.str());
|
|
return false;
|
}
|
|
// Do bitwise RMW operation
|
uiValue = (uiValue & ~getMask()) | (uiConvertedValue << _bitPos);
|
|
return true;
|
}
|
|
void CBitParameterType::fromBlackboard(string &strValue, const uint64_t &uiValue,
|
CParameterAccessContext ¶meterAccessContext) const
|
{
|
uint64_t uiConvertedValue = (uiValue & getMask()) >> _bitPos;
|
|
// Format
|
std::ostringstream strStream;
|
|
// Take care of format
|
if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) {
|
|
strStream << "0x" << std::hex << std::uppercase;
|
}
|
|
strStream << uiConvertedValue;
|
|
strValue = strStream.str();
|
}
|
|
// Value access
|
// Integer
|
bool CBitParameterType::toBlackboard(uint64_t uiUserValue, uint64_t &uiValue,
|
CParameterAccessContext ¶meterAccessContext) const
|
{
|
if (uiUserValue > _uiMax) {
|
|
parameterAccessContext.setError("Value out of range");
|
|
return false;
|
}
|
|
// Do bitwise RMW operation
|
uiValue = (uiValue & ~getMask()) | (uiUserValue << _bitPos);
|
|
return true;
|
}
|
|
void CBitParameterType::fromBlackboard(uint32_t &userValue, uint64_t value,
|
CParameterAccessContext & /*ctx*/) const
|
{
|
userValue = static_cast<uint32_t>((value & getMask()) >> _bitPos);
|
}
|
|
// Access from area configuration
|
uint64_t CBitParameterType::merge(uint64_t uiOriginData, uint64_t uiNewData) const
|
{
|
return (uiOriginData & ~getMask()) | (uiNewData & getMask());
|
}
|
|
// Bit Size
|
size_t CBitParameterType::getBitSize() const
|
{
|
return _uiBitSize;
|
}
|
|
CInstanceConfigurableElement *CBitParameterType::doInstantiate() const
|
{
|
return new CBitParameter(getName(), this);
|
}
|
|
// Max value
|
uint64_t CBitParameterType::getMaxEncodableValue() const
|
{
|
return (uint64_t)-1L >> (8 * sizeof(uint64_t) - _uiBitSize);
|
}
|
|
// Biwise mask
|
uint64_t CBitParameterType::getMask() const
|
{
|
return getMaxEncodableValue() << _bitPos;
|
}
|
|
// From IXmlSource
|
void CBitParameterType::toXml(CXmlElement &xmlElement,
|
CXmlSerializingContext &serializingContext) const
|
{
|
// Position
|
xmlElement.setAttribute("Pos", _bitPos);
|
|
// Size
|
xmlElement.setAttribute("Size", _uiBitSize);
|
|
// Maximum
|
xmlElement.setAttribute("Max", _uiMax);
|
|
base::toXml(xmlElement, serializingContext);
|
}
|