// license:GPL-2.0+ // copyright-holders:Couriersud /// /// \file device.h /// #ifndef NL_CORE_DEVICE_H_ #define NL_CORE_DEVICE_H_ #include "../nltypes.h" #include "../plib/pstring.h" #include "base_objects.h" #include "logic_family.h" #include "param.h" namespace netlist { // ----------------------------------------------------------------------------- // core_device_t // ----------------------------------------------------------------------------- // FIXME: belongs into detail namespace class core_device_t : public detail::netlist_object_t { public: core_device_t(netlist_state_t &owner, const pstring &name); core_device_t(core_device_t &owner, const pstring &name); PCOPYASSIGNMOVE(core_device_t, delete) virtual ~core_device_t() noexcept = default; void do_inc_active() noexcept { if (m_hint_deactivate) { if (++m_active_outputs == 1) { if (m_stats) m_stats->m_stat_inc_active.inc(); inc_active(); } } } void do_dec_active() noexcept { if (m_hint_deactivate) if (--m_active_outputs == 0) { dec_active(); } } void set_hint_deactivate(bool v) noexcept { m_hint_deactivate = v; } bool get_hint_deactivate() const noexcept { return m_hint_deactivate; } // Has to be set in device reset void set_active_outputs(int n) noexcept { m_active_outputs = n; } // stats struct stats_t { // NL_KEEP_STATISTICS plib::pperftime_t m_stat_total_time; plib::pperfcount_t m_stat_call_count; plib::pperfcount_t m_stat_inc_active; }; stats_t * stats() const noexcept { return m_stats.get(); } #if 0 virtual void update() noexcept { } #endif virtual void reset() { } protected: virtual void inc_active() noexcept { } virtual void dec_active() noexcept { } log_type & log(); public: virtual void timestep(timestep_type ts_type, nl_fptype st) noexcept { plib::unused_var(ts_type, st); } virtual void update_terminals() noexcept { } virtual void update_param() noexcept {} virtual bool is_dynamic() const noexcept { return false; } virtual bool is_timestep() const noexcept { return false; } private: bool m_hint_deactivate; state_var_s32 m_active_outputs; device_arena::unique_ptr m_stats; }; // ----------------------------------------------------------------------------- // base_device_t // ----------------------------------------------------------------------------- class base_device_t : public core_device_t { public: base_device_t(netlist_state_t &owner, const pstring &name); base_device_t(base_device_t &owner, const pstring &name); PCOPYASSIGNMOVE(base_device_t, delete) ~base_device_t() noexcept override = default; template void create_and_register_subdevice(O& owner, const pstring &name, device_arena::unique_ptr &dev, Args&&... args) { dev = state().make_pool_object(owner, name, std::forward(args)...); } void register_subalias(const pstring &name, const detail::core_terminal_t &term); void register_subalias(const pstring &name, const pstring &aliased); void connect(const pstring &t1, const pstring &t2); void connect(const detail::core_terminal_t &t1, const detail::core_terminal_t &t2); protected: //NETLIB_UPDATE_TERMINALSI() { } private: }; // ----------------------------------------------------------------------------- // device_t // ----------------------------------------------------------------------------- class device_t : public base_device_t, public logic_family_t { public: device_t(netlist_state_t &owner, const pstring &name); device_t(netlist_state_t &owner, const pstring &name, const pstring &model); // only needed by proxies device_t(netlist_state_t &owner, const pstring &name, const logic_family_desc_t *desc); device_t(device_t &owner, const pstring &name); // pass in a default model - this may be overwritten by PARAM(DEVICE.MODEL, "XYZ(...)") device_t(device_t &owner, const pstring &name, const pstring &model); PCOPYASSIGNMOVE(device_t, delete) ~device_t() noexcept override = default; protected: //NETLIB_UPDATE_TERMINALSI() { } private: param_model_t m_model; }; } // namespace netlist #endif // NL_CORE_DEVICE_H_