From 39254c45577562ca9467e4d6ef69d6deb2c11149 Mon Sep 17 00:00:00 2001 From: DarkSharpness <2040703891@qq.com> Date: Tue, 9 Jul 2024 22:54:00 +0800 Subject: [PATCH] feat(bit): complete a bit simulate library --- include/bit.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ include/bitop.h | 110 ++++++++++++++++++++++++++++++++++++++++++++ include/tools | 17 +++++++ 3 files changed, 245 insertions(+) create mode 100644 include/bit.h create mode 100644 include/bitop.h create mode 100644 include/tools diff --git a/include/bit.h b/include/bit.h new file mode 100644 index 0000000..ba5e8e2 --- /dev/null +++ b/include/bit.h @@ -0,0 +1,118 @@ +#pragma once +#include "target.h" +#include +#include + +namespace dark::bits { + +static constexpr std::size_t kMaxLength = 8 * sizeof(target_size_t); + +template +constexpr auto int_concat(target_size_t arg) { return arg; } + +template +constexpr auto int_concat(target_size_t arg, auto ...args) { + return (arg << (_Lens + ...)) | int_concat<_Lens...>(args...); +} + +template +struct Bit { + private: + static_assert(0 < _Nm && _Nm <= kMaxLength, + "Bit: _Nm out of range. Should be in [1, kMaxLength]"); + + target_size_t _M_data : _Nm; // Real storage + + public: + static constexpr std::size_t _Bit_Len = _Nm; + + constexpr Bit(target_size_t data = 0) : _M_data(data) {} + + template + constexpr Bit(Bit<_Lens> ...args) requires ((_Lens + ...) == _Nm) : + _M_data(int_concat<_Lens...>(args...)) {} + + constexpr Bit(const Bit &val) = default; + + template + constexpr Bit(const Bit <_Len> &val) requires (_Len != _Nm) { + static_assert(_Len == _Nm, "Bit: bit length mismatch"); + } + + constexpr Bit &operator=(const Bit &val) = default; + + template requires (_Len != _Nm) + constexpr Bit &operator=(const Bit <_Len> &val) { + static_assert(_Len == _Nm, "Bit: bit length mismatch"); + return *this; + } + + constexpr Bit &operator=(target_size_t val) { + this->_M_data = val; + return *this; + } + + constexpr operator target_size_t() const { return this->_M_data; } + + template + constexpr auto slice() const -> Bit <_Hi - _Lo + 1> { + static_assert(_Lo <= _Hi, "Bit::slice: _Lo should be no greater than _Hi"); + static_assert(_Hi < _Nm, "Bit::slice: _Hi should be less than _Nm"); + return Bit<_Hi - _Lo + 1>(this->_M_data >> _Lo); + } + + template + constexpr auto zero_extend() const -> Bit<_New>; + + template + constexpr auto sign_extend() const -> Bit<_New>; +}; + +template +static constexpr bool is_bit_v = false; +template +static constexpr bool is_bit_v> = true; + +template +concept BitType = is_bit_v<_Tp>; + +template +Bit(_Tp...) -> Bit<(_Tp::_Bit_Len + ...)>; + +template +constexpr auto sign_extend(target_size_t val) { + static_assert(_Old < _New, "sign_extend: _Old should be less than _New"); + struct { target_ssize_t _M_data : _Old; } tmp; + return Bit<_New>(tmp._M_data = val); +} + +template +constexpr auto sign_extend(_Tp val) { + return sign_extend<_Tp::_Bit_Len, _New>(static_cast(val)); +} + +template +constexpr auto zero_extend(target_size_t val) { + static_assert(_Old < _New, "zero_extend: _Old should be less than _New"); + struct { target_size_t _M_data : _Old; } tmp; + return Bit<_New>(tmp._M_data = val); +} + +template +constexpr auto zero_extend(_Tp val) { + return zero_extend<_Tp::_Bit_Len, _New>(static_cast(val)); +} + +template +template +constexpr auto Bit<_Nm>::sign_extend() const -> Bit<_New> { + return ::dark::bits::sign_extend<_New> (*this); +} + +template +template +constexpr auto Bit<_Nm>::zero_extend() const -> Bit<_New> { + return ::dark::bits::zero_extend<_New> (*this); +} + +} // namespace dark::bits diff --git a/include/bitop.h b/include/bitop.h new file mode 100644 index 0000000..67c5d14 --- /dev/null +++ b/include/bitop.h @@ -0,0 +1,110 @@ +#pragma once +#include "bit.h" + +namespace dark::bits { + +template +concept NonBit = !BitType<_Tp>; + +template +auto cast(_Tp &&val) -> target_size_t { + return static_cast(val); +} + +template +constexpr auto operator + (_Lhs lhs, _Rhs rhs) { + static_assert(_Lhs::_Bit_Len == _Rhs::_Bit_Len, + "operator +: lhs and rhs should have the same length"); + return _Lhs { cast(lhs) + cast(rhs) }; +} + +template +constexpr auto operator - (_Lhs lhs, _Rhs rhs) { + static_assert(_Lhs::_Bit_Len == _Rhs::_Bit_Len, + "operator -: lhs and rhs should have the same length"); + return _Lhs { cast(lhs) - cast(rhs) }; +} + +template +constexpr auto operator & (_Lhs lhs, _Rhs rhs) { + static_assert(_Lhs::_Bit_Len == _Rhs::_Bit_Len, + "operator &: lhs and rhs should have the same length"); + return _Lhs { cast(lhs) & cast(rhs) }; +} + +template +constexpr auto operator | (_Lhs lhs, _Rhs rhs) { + static_assert(_Lhs::_Bit_Len == _Rhs::_Bit_Len, + "operator |: lhs and rhs should have the same length"); + return _Lhs { cast(lhs) | cast(rhs) }; +} + +template +constexpr auto operator ^ (_Lhs lhs, _Rhs rhs) { + static_assert(_Lhs::_Bit_Len == _Rhs::_Bit_Len, + "operator ^: lhs and rhs should have the same length"); + return _Lhs { cast(lhs) ^ cast(rhs) }; +} + +template +constexpr auto operator + (_Lhs lhs, _Rhs rhs) { + return _Lhs { cast(lhs) + cast(rhs) }; +} + +template +constexpr auto operator - (_Lhs lhs, _Rhs rhs) { + return _Lhs { cast(lhs) - cast(rhs) }; +} + +template +constexpr auto operator & (_Lhs lhs, _Rhs rhs) { + return _Lhs { cast(lhs) & cast(rhs) }; +} + +template +constexpr auto operator | (_Lhs lhs, _Rhs rhs) { + return _Lhs { cast(lhs) | cast(rhs) }; +} + +template +constexpr auto operator ^ (_Lhs lhs, _Rhs rhs) { + return _Lhs { cast(lhs) ^ cast(rhs) }; +} + +template +constexpr auto operator + (_Lhs lhs, _Rhs rhs) { + return _Rhs { cast(lhs) + cast(rhs) }; +} + +template +constexpr auto operator - (_Lhs lhs, _Rhs rhs) { + return _Rhs { cast(lhs) - cast(rhs) }; +} + +template +constexpr auto operator & (_Lhs lhs, _Rhs rhs) { + return _Rhs { cast(lhs) & cast(rhs) }; +} + +template +constexpr auto operator | (_Lhs lhs, _Rhs rhs) { + return _Rhs { cast(lhs) | cast(rhs) }; +} + +template +constexpr auto operator ^ (_Lhs lhs, _Rhs rhs) { + return _Rhs { cast(lhs) ^ cast(rhs) }; +} + +template +constexpr auto operator ~ (_Tp val) { + return _Tp { ~cast(val) }; +} + +template +constexpr auto operator ! (_Tp val) { + return _Tp { !cast(val) }; +} + + +} // namespace dark::bits diff --git a/include/tools b/include/tools new file mode 100644 index 0000000..b0817d9 --- /dev/null +++ b/include/tools @@ -0,0 +1,17 @@ +#pragma once +#include "target.h" +#include "hardware.h" +#include "synchronize.h" +#include "bit.h" +#include "bitop.h" + +using ::dark::target_size_t; +using ::dark::target_ssize_t; + +using ::dark::hardware::Register; +using ::dark::hardware::Wire; +using ::dark::hardware::Visitor; +using ::dark::hardware::SyncTags; +using ::dark::hardware::sync_member; + +using ::dark::bits::Bit;