From 72b0c5bcf097f9fe198aa4823128e461ea79542f Mon Sep 17 00:00:00 2001 From: DarkSharpness <2040703891@qq.com> Date: Thu, 11 Jul 2024 21:53:52 +0800 Subject: [PATCH] feat(wire & register): implement these 2 components --- include/debug.h | 2 + include/hardware.h | 144 ------------------------------------------ include/register.h | 48 ++++++++++++++ include/synchronize.h | 3 +- include/wire.h | 116 ++++++++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+), 146 deletions(-) delete mode 100644 include/hardware.h create mode 100644 include/register.h create mode 100644 include/wire.h diff --git a/include/debug.h b/include/debug.h index 4952ac1..01f4e53 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,6 +1,8 @@ #pragma once #include +#ifdef _DEBUG #include +#endif #include namespace dark::debug { diff --git a/include/hardware.h b/include/hardware.h deleted file mode 100644 index e10a48b..0000000 --- a/include/hardware.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include "debug.h" -#include "concept.h" -#include -#include -#include - -namespace dark::hardware { - -struct Visitor; -struct Wire; -struct Register; - -template -concept WireFunction = - !std::same_as > && - requires(_Fn &&__f) { { __f() } -> std::convertible_to ; }; - -struct WireBase { - using _Ret_t = int; - using _Cpy_t = WireBase *; - virtual _Ret_t call() const = 0; - virtual ~WireBase() = default; -}; - -template -struct WireImpl final : WireBase { - _Fn _M_lambda; - - template - WireImpl(_Fn2 &&fn) : _M_lambda(std::forward <_Fn2>(fn)) {} - - _Ret_t call() const override { return this->_M_lambda(); } -}; - -struct EmptyWire final : WireBase { - _Ret_t call() const override { - debug::assert(false, "Empty wire is called."); - debug::unreachable(); - } -}; - -struct Wire { - private: - friend struct Visitor; - - using _Manage_t = WireBase; - - std::unique_ptr <_Manage_t> _M_impl; - mutable max_size_t _M_cache; - mutable bool _M_holds; - - [[no_unique_address]] - debug::DebugValue _M_dirty; // Can be assigned only once - - void sync() { this->_M_holds = false; } - - template - static auto _M_new_impl(_Fn &&fn) -> _Manage_t * { - return new WireImpl > {std::forward <_Fn>(fn)}; - } - - void _M_check_double_assign() { - debug::assert(!this->_M_dirty, "Wire is already assigned."); - this->_M_dirty = true; - } - - public: - Wire() : _M_impl(new EmptyWire), _M_cache(), _M_holds(), _M_dirty() {} - - Wire(Wire &&) = delete; - Wire(const Wire &) = delete; - Wire &operator=(Wire &&) = delete; - Wire &operator=(const Wire &rhs) = delete; - - template - Wire(_Fn &&fn) - : _M_impl(_M_new_impl(std::forward <_Fn>(fn))), _M_cache(), _M_holds(), _M_dirty() {} - - template - Wire &operator=(_Fn &&fn) { - this->assign(std::forward <_Fn>(fn)); - return *this; - } - - template - void assign(_Fn &&fn) { - this->_M_check_double_assign(); - this->_M_impl.reset(this->_M_new_impl(std::forward <_Fn>(fn))); - this->_M_holds = false; - } - - operator max_size_t() const { - if (this->_M_holds == false) { - this->_M_cache = this->_M_impl->call(); - this->_M_holds = true; - } - return this->_M_cache; - } -}; - -struct Register { - private: - friend struct Visitor; - - max_size_t _M_new; - max_size_t _M_old; - - [[no_unique_address]] - debug::DebugValue _M_dirty; - - void sync() { - if (this->_M_dirty) { - this->_M_old = this->_M_new; - this->_M_dirty = false; - } - } - - void set_value(max_size_t value) { - this->_M_new = value; - debug::assert(!this->_M_dirty, "Register is already assigned in this cycle."); - this->_M_dirty = true; - } - - auto get_value() const -> max_size_t { return this->_M_old; } - - public: - - Register() : _M_new(), _M_old(), _M_dirty() {} - - Register(Register &&) = delete; - Register(const Register &) = delete; - Register &operator=(Register &&) = delete; - Register &operator=(const Register &rhs) = delete; - - template _Int> - void operator <= (_Int &&value) { - this->set_value(static_cast (value)); - } - - operator max_size_t() const { return this->get_value(); } -}; - -} // namespace dark::hardware diff --git a/include/register.h b/include/register.h new file mode 100644 index 0000000..21731b0 --- /dev/null +++ b/include/register.h @@ -0,0 +1,48 @@ +#pragma once +#include "debug.h" +#include "concept.h" + +namespace dark { + +template +struct Register { + private: + static_assert(0 < _Len && _Len <= kMaxLength, + "Register: _Len must be in range [1, kMaxLength]."); + + friend class Visitor; + + max_size_t _M_old : _Len; + max_size_t _M_new : _Len; + + [[no_unique_address]] + debug::DebugValue _M_assigned; + + void sync() { + if (this->_M_assigned) { + this->_M_assigned = false; + this->_M_old = this->_M_new; + } + } + + public: + static constexpr bool _Bit_Len = _Len; + + explicit Register() : _M_old(), _M_new(), _M_assigned() {} + + Register(Register &&) = delete; + Register(const Register &) = delete; + Register &operator=(Register &&) = delete; + Register &operator=(const Register &rhs) = delete; + + template _Tp> + void operator <= (_Tp &&value) { + debug::assert(!this->_M_assigned, "Register is double assigned in this cycle."); + this->_M_assigned = true; + this->_M_new = static_cast (value); + } + + explicit operator max_size_t() const { return this->_M_old; } +}; + +} // namespace dark diff --git a/include/synchronize.h b/include/synchronize.h index 3b112af..b3decd5 100644 --- a/include/synchronize.h +++ b/include/synchronize.h @@ -1,9 +1,8 @@ #pragma once -#include "hardware.h" #include "reflect.h" #include -namespace dark::hardware { +namespace dark { struct Visitor { template diff --git a/include/wire.h b/include/wire.h new file mode 100644 index 0000000..64d7015 --- /dev/null +++ b/include/wire.h @@ -0,0 +1,116 @@ +#pragma once +#include "debug.h" +#include "concept.h" +#include + +namespace dark { + +namespace details { + +template +concept WireFunction = requires(_Fn &&func) { + { func() } -> concepts::bit_convertible <_Len>; +}; + +struct FuncBase { + using _Ret_t = int; + using _Cpy_t = FuncBase *; + virtual _Ret_t call() const = 0; + virtual _Cpy_t copy() const = 0; + virtual ~FuncBase() = default; +}; + +template _Fn> +struct FuncImpl final : FuncBase { + _Fn _M_lambda; + + template + FuncImpl(_Tp &&fn) : _M_lambda(std::forward <_Tp> (fn)) {} + + _Ret_t call() const override { return this->_M_lambda(); } + _Cpy_t copy() const override { return new FuncImpl(*this); } +}; + +struct EmptyWire final : FuncBase { + _Ret_t call() const override { + debug::assert(false, "Empty wire is called."); + debug::unreachable(); + } + _Cpy_t copy() const override { return new EmptyWire; } +}; + +} // namespace details + + +template +struct Wire { + private: + static_assert(0 < _Len && _Len <= kMaxLength, + "Wire: _Len must be in range [1, kMaxLength]."); + + friend class Visitor; + + using _Manage_t = std::unique_ptr ; + + _Manage_t _M_func; + + mutable max_size_t _M_cache; + mutable bool _M_holds; + + [[no_unique_address]] + debug::DebugValue _M_assigned; + + void sync() { this->_M_holds = false; } + + template _Fn> + static auto _M_new_func(_Fn &&fn) { + using _Decay_t = std::decay_t <_Fn>; + return new details::FuncImpl <_Len, _Decay_t> {std::forward <_Fn>(fn)}; + } + + void _M_checked_assign() { + debug::assert(!this->_M_assigned, "Wire is assigned twice."); + this->_M_assigned = true; + } + + public: + static constexpr bool _Bit_Len = _Len; + + explicit Wire() : + _M_func(new details::EmptyWire), + _M_cache(), _M_holds(), _M_assigned() {} + + explicit operator max_size_t() const { + if (this->_M_holds == false) { + this->_M_holds = true; + constexpr auto mask = make_mask <_Len> (); + this->_M_cache = this->_M_func->call() & mask; + } + return this->_M_cache; + } + + Wire(Wire &&) = delete; + Wire(const Wire &) = delete; + Wire &operator=(Wire &&) = delete; + Wire &operator=(const Wire &rhs) = delete; + + template _Fn> + Wire(_Fn &&fn) : + _M_func(_M_new_func(std::forward <_Fn> (fn))), + _M_cache(), _M_holds(), _M_assigned() {} + + template _Fn> + Wire &operator=(_Fn &&fn) { + return this->assign(std::forward <_Fn> (fn)), *this; + } + + template _Fn> + void assign(_Fn &&fn) { + this->_M_checked_assign(); + this->_M_func.reset(_M_new_func(std::forward <_Fn> (fn))); + this->sync(); + } +}; + + +} // namespace dark