// license:BSD-3-Clause // copyright-holders:Couriersud /// /// \file netlist_state.h /// #ifndef NL_CORE_NETLIST_STATE_H_ #define NL_CORE_NETLIST_STATE_H_ #include "../nltypes.h" #include "queue.h" #include "../plib/plists.h" #include "../plib/pstate.h" #include "../plib/pstring.h" #include #include #include #include namespace netlist { // ----------------------------------------------------------------------------- // netlist_state__t // ----------------------------------------------------------------------------- class netlist_state_t { public: using nets_collection_type = std::vector< device_arena::owned_ptr>; using family_collection_type = std::unordered_map>; // need to preserve order of device creation ... using devices_collection_type = std::vector< std::pair>>; netlist_state_t(const pstring &name, plib::plog_delegate logger); PCOPYASSIGNMOVE(netlist_state_t, delete) /// \brief Destructor /// /// The destructor is virtual to allow implementation specific devices /// to connect to the outside world. For examples see MAME netlist.cpp. /// virtual ~netlist_state_t() noexcept = default; template static bool check_class(core_device_t *p) noexcept { return bool(plib::dynamic_downcast(p)); } core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const noexcept(false); /// \brief Get single device filtered by class and name /// /// \tparam C Device class for which devices will be returned /// \param name Name of the device /// /// \return pointers to device template C *get_single_device(const pstring &name) const { return dynamic_cast(get_single_device(name, check_class)); } /// \brief Get vector of devices /// /// \tparam C Device class for which devices will be returned /// /// \return vector with pointers to devices template std::vector get_device_list() const { std::vector tmp; for (const auto &d : m_devices) { if (auto dev = plib::dynamic_downcast(d.second.get())) tmp.push_back(*dev); } return tmp; } // logging log_type & log() noexcept { return m_log; } const log_type &log() const noexcept { return m_log; } plib::dynamic_library_base &static_solver_lib() const noexcept { return *m_lib; } /// \brief provide library with static solver implementations. /// /// By default no static solvers are provided since these are /// determined by the specific use case. You can pass such a collection /// of symbols with this method. /// void set_static_solver_lib( std::unique_ptr &&lib); netlist_t & exec() noexcept { return *m_netlist; } const netlist_t &exec() const noexcept { return *m_netlist; } // state handling plib::state_manager_t &run_state_manager() noexcept { return m_state; } template void save(O &owner, C &state, const pstring &module, const pstring &stname) { this->run_state_manager().save_item(plib::void_ptr_cast(&owner), state, module + "." + stname); } template void save(O &owner, C *state, const pstring &module, const pstring &stname, const std::size_t count) { this->run_state_manager().save_state_ptr( plib::void_ptr_cast(&owner), module + "." + stname, plib::state_manager_t::dtype(), count, state); } // FIXME: only used by queue_t save state std::size_t find_net_id(const detail::net_t *net) const; detail::net_t *net_by_id(std::size_t id) const; template void register_net(device_arena::owned_ptr &&net) { m_nets.push_back(std::move(net)); } /// \brief Get device pointer by name /// /// /// \param name Name of the device /// /// \return core_device_t pointer if device exists, else nullptr core_device_t *find_device(const pstring &name) const { for (const auto &d : m_devices) if (d.first == name) return d.second.get(); return nullptr; } /// \brief Register device using owned_ptr /// /// Used to register owned devices. These are devices declared as /// objects in another devices. /// /// \param name Name of the device /// \param dev Device to be registered template void register_device(const pstring &name, device_arena::owned_ptr && dev) noexcept(false) { for (auto &d : m_devices) if (d.first == name) { dev.release(); log().fatal(MF_DUPLICATE_NAME_DEVICE_LIST(name)); throw nl_exception(MF_DUPLICATE_NAME_DEVICE_LIST(name)); } // m_devices.push_back(std::move(dev)); m_devices.insert(m_devices.end(), {name, std::move(dev)}); } /// \brief Register device using unique_ptr /// /// Used to register devices. /// /// \param name Name of the device /// \param dev Device to be registered template void register_device(const pstring &name, device_arena::unique_ptr && dev) { register_device(name, device_arena::owned_ptr(dev.release(), true, dev.get_deleter())); } /// \brief Remove device /// /// Care needs to be applied if this is called to remove devices with /// sub-devices which may have registered state. /// /// \param dev Device to be removed void remove_device(core_device_t *dev); setup_t & setup() noexcept { return *m_setup; } const setup_t &setup() const noexcept { return *m_setup; } nlparse_t & parser() noexcept; const nlparse_t &parser() const noexcept; // FIXME: make a post load member and include code there void rebuild_lists(); // must be called after post_load ! static void compile_defines( std::vector> &defs); static pstring version(); static pstring version_patchlevel(); nets_collection_type & nets() noexcept { return m_nets; } const nets_collection_type &nets() const noexcept { return m_nets; } devices_collection_type & devices() noexcept { return m_devices; } const devices_collection_type &devices() const noexcept { return m_devices; } family_collection_type &family_cache() { return m_family_cache; } template device_arena::unique_ptr make_pool_object(Args &&...args) { return plib::make_unique(m_pool, std::forward(args)...); } // memory pool - still needed in some places device_arena & pool() noexcept { return m_pool; } const device_arena &pool() const noexcept { return m_pool; } struct stats_info { const detail::queue_t & m_queue; // performance const plib::pperftime_t & m_stat_mainloop; const plib::pperfcount_t &m_perf_out_processed; }; /// \brief print statistics gathered during run /// void print_stats(stats_info &si) const; /// \brief call reset on all netlist components /// void reset(); /// \brief prior to running free no longer needed resources /// void free_setup_resources(); #if !(NL_USE_INPLACE_CORE_TERMS) std::vector &core_terms( const detail::net_t &net) { return m_core_terms[&net]; } #endif private: device_arena m_pool; // must be deleted last! device_arena::unique_ptr m_netlist; std::unique_ptr m_lib; plib::state_manager_t m_state; log_type m_log; // FIXME: should only be available during device construction host_arena::unique_ptr m_setup; nets_collection_type m_nets; // sole use is to manage lifetime of net objects devices_collection_type m_devices; // sole use is to manage lifetime of family objects family_collection_type m_family_cache; #if !(NL_USE_INPLACE_CORE_TERMS) // all terms for a net std::unordered_map> m_core_terms; #endif // dummy version int m_dummy_version; }; } // namespace netlist #endif // NL_CORE_NETLIST_STATE_H_