summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/core/base_objects.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/core/base_objects.h')
-rw-r--r--src/lib/netlist/core/base_objects.h455
1 files changed, 243 insertions, 212 deletions
diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h
index ca263bb87eb..b62c82e160c 100644
--- a/src/lib/netlist/core/base_objects.h
+++ b/src/lib/netlist/core/base_objects.h
@@ -8,279 +8,310 @@
#ifndef NL_CORE_BASE_OBJECTS_H_
#define NL_CORE_BASE_OBJECTS_H_
+#include "../nltypes.h"
#include "netlist_state.h"
#include "state_var.h"
-#include "../nltypes.h"
-
#include "../plib/palloc.h"
#include "../plib/pchrono.h"
#include "../plib/pexception.h"
#include "../plib/plists.h"
#include "../plib/pmempool.h"
+#include "../plib/ppmf.h"
#include <unordered_map>
namespace netlist
{
+ /// \brief Delegate type for device notification.
+ ///
+ using nl_delegate = plib::pmfp<void()>;
+ using nl_delegate_ts = plib::pmfp<void(detail::time_step_type, nl_fptype)>;
+ using nl_delegate_dyn = plib::pmfp<void()>;
+} // namespace netlist
- namespace detail {
+namespace netlist::detail
+{
+
+ template <typename C, typename T>
+ struct property_store_t
+ {
+ using value_type = T;
+ using key_type = const C *;
+ using store_type = std::unordered_map<key_type, value_type>;
- template <typename C, typename T>
- struct property_store_t
+ static void add(key_type obj, const value_type &value) noexcept
{
- using value_type = T;
- using key_type = const C *;
- static void add(key_type obj, const value_type &aname) noexcept
+ try
+ {
+ store().insert({obj, value});
+ }
+ catch (...)
{
- store().insert({obj, aname});
+ plib::terminate("exception in property_store_t.add()");
}
+ }
- static value_type *get(key_type obj) noexcept
+ static const value_type &get(key_type obj) noexcept
+ {
+ try
+ {
+ typename store_type::iterator ret(store().find(obj));
+ if (ret == store().end())
+ plib::terminate(
+ "object not found in property_store_t.get()");
+ return ret->second;
+ }
+ catch (...)
{
- try
- {
- auto ret(store().find(obj));
- if (ret == store().end())
- return nullptr;
- return &ret->second;
- }
- catch (...)
- {
- plib::terminate("exception in property_store_t.get()");
- return static_cast<value_type *>(nullptr);
- }
+ plib::terminate("exception in property_store_t.get()");
}
+ }
- static void remove(key_type obj) noexcept
+ static void remove(key_type obj) noexcept
+ {
+ try
{
store().erase(store().find(obj));
}
-
- static std::unordered_map<key_type, value_type> &store() noexcept
+ catch (...)
{
- static std::unordered_map<key_type, value_type> lstore;
- return lstore;
+ plib::terminate("exception in property_store_t.remove()");
}
+ }
- };
+ static store_type &store() noexcept
+ {
+ static store_type static_store;
+ return static_store;
+ }
+ };
+
+ // -------------------------------------------------------------------------
+ // object_t
+ // -------------------------------------------------------------------------
+
+ /// \brief The base class for netlist devices, terminals and parameters.
+ ///
+ /// This class serves as the base class for all device, terminal and
+ /// objects.
+
+ class object_t
+ {
+ public:
+ /// \brief Constructor.
+ /// Every class derived from the object_t class must have a name.
+ ///
+ /// \param aname string containing name of the object
- // -----------------------------------------------------------------------------
- // object_t
- // -----------------------------------------------------------------------------
+ explicit object_t(const pstring &aname) { props::add(this, aname); }
- /// \brief The base class for netlist devices, terminals and parameters.
+ PCOPYASSIGNMOVE(object_t, delete)
+ /// \brief return name of the object
///
- /// This class serves as the base class for all device, terminal and
- /// objects.
+ /// \returns name of the object.
- class object_t
- {
- public:
+ const pstring &name() const noexcept { return props::get(this); }
- /// \brief Constructor.
- /// Every class derived from the object_t class must have a name.
- ///
- /// \param aname string containing name of the object
+ protected:
+ using props = property_store_t<object_t, pstring>;
- explicit object_t(const pstring &aname)
- {
- props::add(this, aname);
- }
+ // only childs should be destructible
+ ~object_t() noexcept { props::remove(this); }
- PCOPYASSIGNMOVE(object_t, delete)
- /// \brief return name of the object
- ///
- /// \returns name of the object.
+ private:
+ };
- const pstring &name() const noexcept
- {
- return *props::get(this);
- }
+ /// \brief Base class for all objects being owned by a netlist
+ ///
+ /// The object provides adds \ref netlist_state_t and \ref netlist_t
+ /// accessors.
+ ///
- protected:
+ class netlist_object_t : public object_t
+ {
+ public:
+ explicit netlist_object_t(netlist_t &nl, const pstring &name)
+ : object_t(name)
+ , m_netlist(nl)
+ {
+ }
- using props = property_store_t<object_t, pstring>;
+ ~netlist_object_t() = default;
- // only childs should be destructible
- ~object_t() noexcept
- {
- props::remove(this);
- }
+ PCOPYASSIGNMOVE(netlist_object_t, delete)
- private:
- };
+ netlist_state_t &state() noexcept;
+ const netlist_state_t &state() const noexcept;
- /// \brief Base class for all objects bejng owned by a netlist
- ///
- /// The object provides adds \ref netlist_state_t and \ref netlist_t
- /// accessors.
- ///
+ constexpr netlist_t &exec() noexcept { return m_netlist; }
+ constexpr const netlist_t &exec() const noexcept { return m_netlist; }
- class netlist_object_t : public object_t
+ // to ease template design
+ template <typename T, typename... Args>
+ device_arena::unique_ptr<T>
+ make_pool_object(Args &&...args) noexcept(false)
{
- public:
- explicit netlist_object_t(netlist_t &nl, const pstring &name)
- : object_t(name)
- , m_netlist(nl)
- { }
-
- ~netlist_object_t() = default;
-
- PCOPYASSIGNMOVE(netlist_object_t, delete)
-
- netlist_state_t & state() noexcept;
- const netlist_state_t & state() const noexcept;
+ return state().make_pool_object<T>(std::forward<Args>(args)...);
+ }
+
+ private:
+ netlist_t &m_netlist;
+ };
+
+ // -------------------------------------------------------------------------
+ // device_object_t
+ // -------------------------------------------------------------------------
+
+ /// \brief Base class for all objects being owned by a device.
+ ///
+ /// Serves as the base class of all objects being owned by a device.
+ ///
+ /// The class also supports device-less objects. In this case,
+ /// nullptr is passed in as the device object.
+ ///
+
+ class device_object_t : public object_t
+ {
+ public:
+ /// \brief Constructor.
+ ///
+ /// \param dev pointer to device owning the object.
+ /// \param name string holding the name of the device
+
+ device_object_t(core_device_t *dev, const pstring &name);
+
+ /// \brief returns reference to owning device.
+ /// \returns reference to owning device.
+
+ core_device_t &device() noexcept { return *m_device; }
+ const core_device_t &device() const noexcept { return *m_device; }
+
+ /// \brief The netlist owning the owner of this object.
+ /// \returns reference to netlist object.
+
+ netlist_state_t &state() noexcept;
+ const netlist_state_t &state() const noexcept;
+
+ private:
+ core_device_t *m_device;
+ };
+
+ // -------------------------------------------------------------------------
+ // core_terminal_t
+ // -------------------------------------------------------------------------
+
+ /// \brief Base class for all terminals.
+ ///
+ /// All terminals are derived from this class.
+ ///
+ class core_terminal_t
+ : public device_object_t
+ , public plib::linked_list_t<core_terminal_t, 0>::element_t
+#if NL_USE_INPLACE_CORE_TERMS
+ , public plib::linked_list_t<core_terminal_t, 1>::element_t
+#endif
+ {
+ public:
+ /// \brief Number of signal bits
+ ///
+ /// Going forward setting this to 8 will allow 8-bit signal
+ /// buses to be used in netlist, e.g. for more complex memory
+ /// arrangements.
+ /// Minimum value is 2 here to support tristate output on proxies.
+ static constexpr const unsigned int INP_BITS = 2;
- netlist_t & exec() noexcept { return m_netlist; }
- const netlist_t & exec() const noexcept { return m_netlist; }
+ static constexpr const unsigned int INP_MASK = (1 << INP_BITS) - 1;
+ static constexpr const unsigned int INP_HL_SHIFT = 0;
+ static constexpr const unsigned int INP_LH_SHIFT = INP_BITS;
- // to ease template design
- template<typename T, typename... Args>
- device_arena::unique_ptr<T> make_pool_object(Args&&... args)
- {
- return state().make_pool_object<T>(std::forward<Args>(args)...);
- }
+ static constexpr netlist_sig_t OUT_TRISTATE() { return INP_MASK; }
- private:
- netlist_t & m_netlist;
+ static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8,
+ "netlist_sig_t size not sufficient");
+ enum state_e
+ {
+ STATE_INP_PASSIVE = 0,
+ STATE_INP_HL = (INP_MASK << INP_HL_SHIFT),
+ STATE_INP_LH = (INP_MASK << INP_LH_SHIFT),
+ STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH,
+ STATE_OUT = (1 << (2 * INP_BITS)),
+ STATE_BIDIR = (1 << (2 * INP_BITS + 1))
};
- // -----------------------------------------------------------------------------
- // device_object_t
- // -----------------------------------------------------------------------------
-
- /// \brief Base class for all objects being owned by a device.
- ///
- /// Serves as the base class of all objects being owned by a device.
- ///
- /// The class also supports device-less objects. In this case,
- /// nullptr is passed in as the device object.
- ///
+ core_terminal_t(core_device_t &dev, const pstring &aname, state_e state,
+ nl_delegate delegate);
+ virtual ~core_terminal_t() noexcept = default;
- class device_object_t : public object_t
- {
- public:
- /// \brief Constructor.
- ///
- /// \param dev pointer to device owning the object.
- /// \param name string holding the name of the device
+ PCOPYASSIGNMOVE(core_terminal_t, delete)
- device_object_t(core_device_t *dev, const pstring &name);
+ /// \brief The object type.
+ /// \returns type of the object
+ terminal_type type() const noexcept(false);
- /// \brief returns reference to owning device.
- /// \returns reference to owning device.
+ /// \brief Checks if object is of specified type.
+ /// \param atype type to check object against.
+ /// \returns true if object is of specified type else false.
+ bool is_type(const terminal_type atype) const noexcept(false)
+ {
+ return (type() == atype);
+ }
- core_device_t &device() noexcept { return *m_device; }
- const core_device_t &device() const noexcept { return *m_device; }
+ void set_net(net_t *anet) noexcept { m_net = anet; }
+ void clear_net() noexcept { m_net = nullptr; }
+ constexpr bool has_net() const noexcept { return (m_net != nullptr); }
- /// \brief The netlist owning the owner of this object.
- /// \returns reference to netlist object.
+ constexpr net_t &net() const noexcept { return *m_net; }
- netlist_state_t &state() noexcept;
- const netlist_state_t &state() const noexcept;
+ bool is_logic() const noexcept;
+ bool is_logic_input() const noexcept;
+ bool is_logic_output() const noexcept;
+ bool is_tristate_output() const noexcept;
+ bool is_analog() const noexcept;
+ bool is_analog_input() const noexcept;
+ bool is_analog_output() const noexcept;
- private:
- core_device_t * m_device;
- };
+ constexpr bool is_state(state_e state) const noexcept
+ {
+ return (m_state == state);
+ }
+ constexpr state_e terminal_state() const noexcept { return m_state; }
+ constexpr void set_state(state_e state) noexcept { m_state = state; }
- // -----------------------------------------------------------------------------
- // core_terminal_t
- // -----------------------------------------------------------------------------
+ void reset() noexcept
+ {
+ set_state(is_type(terminal_type::OUTPUT) ? STATE_OUT
+ : STATE_INP_ACTIVE);
+ }
- /// \brief Base class for all terminals.
- ///
- /// All terminals are derived from this class.
- ///
- class core_terminal_t : public device_object_t,
- public plib::linkedlist_t<core_terminal_t>::element_t
+ constexpr void
+ set_copied_input([[maybe_unused]] netlist_sig_t val) noexcept
{
- public:
- /// \brief Number of signal bits
- ///
- /// Going forward setting this to 8 will allow 8-bit signal
- /// busses to be used in netlist, e.g. for more complex memory
- /// arrangements.
- /// Mimimum value is 2 here to support tristate output on proxies.
- static constexpr const unsigned int INP_BITS = 2;
-
- static constexpr const unsigned int INP_MASK = (1 << INP_BITS) - 1;
- static constexpr const unsigned int INP_HL_SHIFT = 0;
- static constexpr const unsigned int INP_LH_SHIFT = INP_BITS;
-
- static constexpr netlist_sig_t OUT_TRISTATE() { return INP_MASK; }
-
- static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8, "netlist_sig_t size not sufficient");
-
- enum state_e {
- STATE_INP_PASSIVE = 0,
- STATE_INP_HL = (INP_MASK << INP_HL_SHIFT),
- STATE_INP_LH = (INP_MASK << INP_LH_SHIFT),
- STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH,
- STATE_OUT = (1 << (2*INP_BITS)),
- STATE_BIDIR = (1 << (2*INP_BITS + 1))
- };
-
- core_terminal_t(core_device_t &dev, const pstring &aname,
- state_e state, nldelegate delegate);
- virtual ~core_terminal_t() noexcept = default;
-
- PCOPYASSIGNMOVE(core_terminal_t, delete)
-
- /// \brief The object type.
- /// \returns type of the object
- terminal_type type() const noexcept(false);
-
- /// \brief Checks if object is of specified type.
- /// \param atype type to check object against.
- /// \returns true if object is of specified type else false.
- bool is_type(const terminal_type atype) const noexcept(false) { return (type() == atype); }
-
- void set_net(net_t *anet) noexcept { m_net = anet; }
- void clear_net() noexcept { m_net = nullptr; }
- constexpr bool has_net() const noexcept { return (m_net != nullptr); }
-
- net_t & net() const noexcept { return *m_net;}
-
- bool is_logic() const noexcept;
- bool is_logic_input() const noexcept;
- bool is_logic_output() const noexcept;
- bool is_tristate_output() const noexcept;
- bool is_analog() const noexcept;
- bool is_analog_input() const noexcept;
- bool is_analog_output() const noexcept;
-
- constexpr bool is_state(state_e astate) const noexcept { return (m_state == astate); }
- constexpr const state_e &terminal_state() const noexcept { return m_state; }
- void set_state(state_e astate) noexcept { m_state = astate; }
-
- void reset() noexcept { set_state(is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); }
-
- #if NL_USE_COPY_INSTEAD_OF_REFERENCE
- void set_copied_input(netlist_sig_t val) noexcept
+ if constexpr (config::use_copy_instead_of_reference::value)
{
- m_Q = val;
+ m_Q_CIR = val;
}
+ }
- state_var_sig m_Q;
- #else
- void set_copied_input(const netlist_sig_t &val) const noexcept { plib::unused_var(val); } // NOLINT: static means more message elsewhere
- #endif
-
- void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; }
- const nldelegate &delegate() const noexcept { return m_delegate; }
- void run_delegate() const noexcept { return m_delegate(); }
- private:
- nldelegate m_delegate;
- net_t * m_net;
- state_var<state_e> m_state;
- };
-
-
- } // namespace detail
-
-} // namespace netlist
-
+ void set_delegate(const nl_delegate &delegate) noexcept
+ {
+ m_delegate = delegate;
+ }
+ const nl_delegate &delegate() const noexcept { return m_delegate; }
+ void run_delegate() const noexcept { return m_delegate(); }
+
+ protected:
+ // std::conditional_t<config::use_copy_instead_of_reference::value,
+ // state_var_sig, void *> m_Q;
+ state_var_sig m_Q_CIR;
+
+ private:
+ nl_delegate m_delegate;
+ net_t *m_net;
+ state_var<state_e> m_state;
+ };
+
+} // namespace netlist::detail
#endif // NL_CORE_BASE_OBJECTS_H_