mirror of https://github.com/YosysHQ/yosys.git
cxxrtl: implement `value.get()` and `value.set()` for signed types.
This commit is contained in:
parent
22370ad21e
commit
5aaf1f1d39
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -145,7 +146,7 @@ struct value : public expr_base<value<Bits>> {
|
||||||
// These functions ensure that a conversion is never out of range, and should be always used, if at all
|
// These functions ensure that a conversion is never out of range, and should be always used, if at all
|
||||||
// possible, instead of direct manipulation of the `data` member. For very large types, .slice() and
|
// possible, instead of direct manipulation of the `data` member. For very large types, .slice() and
|
||||||
// .concat() can be used to split them into more manageable parts.
|
// .concat() can be used to split them into more manageable parts.
|
||||||
template<class IntegerT>
|
template<class IntegerT, typename std::enable_if<!std::is_signed<IntegerT>::value, int>::type = 0>
|
||||||
CXXRTL_ALWAYS_INLINE
|
CXXRTL_ALWAYS_INLINE
|
||||||
IntegerT get() const {
|
IntegerT get() const {
|
||||||
static_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,
|
static_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,
|
||||||
|
@ -158,15 +159,32 @@ struct value : public expr_base<value<Bits>> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class IntegerT>
|
template<class IntegerT, typename std::enable_if<std::is_signed<IntegerT>::value, int>::type = 0>
|
||||||
CXXRTL_ALWAYS_INLINE
|
CXXRTL_ALWAYS_INLINE
|
||||||
void set(IntegerT other) {
|
IntegerT get() const {
|
||||||
|
auto unsigned_result = get<typename std::make_unsigned<IntegerT>::type>();
|
||||||
|
IntegerT result;
|
||||||
|
memcpy(&result, &unsigned_result, sizeof(IntegerT));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class IntegerT, typename std::enable_if<!std::is_signed<IntegerT>::value, int>::type = 0>
|
||||||
|
CXXRTL_ALWAYS_INLINE
|
||||||
|
void set(IntegerT value) {
|
||||||
static_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,
|
static_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,
|
||||||
"set<T>() requires T to be an unsigned integral type");
|
"set<T>() requires T to be an unsigned integral type");
|
||||||
static_assert(std::numeric_limits<IntegerT>::digits >= Bits,
|
static_assert(std::numeric_limits<IntegerT>::digits >= Bits,
|
||||||
"set<T>() requires the value to be at least as wide as T is");
|
"set<T>() requires the value to be at least as wide as T is");
|
||||||
for (size_t n = 0; n < chunks; n++)
|
for (size_t n = 0; n < chunks; n++)
|
||||||
data[n] = (other >> (n * chunk::bits)) & chunk::mask;
|
data[n] = (value >> (n * chunk::bits)) & chunk::mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class IntegerT, typename std::enable_if<std::is_signed<IntegerT>::value, int>::type = 0>
|
||||||
|
CXXRTL_ALWAYS_INLINE
|
||||||
|
void set(IntegerT value) {
|
||||||
|
typename std::make_unsigned<IntegerT>::type unsigned_value;
|
||||||
|
memcpy(&unsigned_value, &value, sizeof(IntegerT));
|
||||||
|
set(unsigned_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operations with compile-time parameters.
|
// Operations with compile-time parameters.
|
||||||
|
|
Loading…
Reference in New Issue