// license:BSD-3-Clause // copyright-holders:Couriersud /// /// \file nl_factory.h /// #ifndef NLFACTORY_H_ #define NLFACTORY_H_ #include "nltypes.h" #include "plib/palloc.h" #include "plib/pmempool.h" #include "plib/psource.h" #include "plib/ptypes.h" #include #include #include #define NETLIB_DEVICE_IMPL_ALIAS(p_alias, chip, p_name, p_def_param) \ NETLIB_DEVICE_IMPL_BASE(devices, p_alias, chip, p_name, p_def_param) \ #define NETLIB_DEVICE_IMPL(chip, p_name, p_def_param) \ NETLIB_DEVICE_IMPL_NS(devices, chip, p_name, p_def_param) #define NETLIB_DEVICE_IMPL_NS(ns, chip, p_name, p_def_param) \ NETLIB_DEVICE_IMPL_BASE(ns, chip, chip, p_name, p_def_param) \ #define NETLIB_DEVICE_IMPL_BASE(ns, p_alias, chip, p_name, p_def_param) \ static factory::element_t::uptr NETLIB_NAME(p_alias ## _c) () \ { \ using devtype = factory::device_element_t; \ factory::properties sl(p_def_param, PSOURCELOC()); \ return devtype::create(p_name, std::move(sl)); \ } \ \ extern factory::constructor_ptr_t decl_ ## p_alias; \ factory::constructor_ptr_t decl_ ## p_alias = NETLIB_NAME(p_alias ## _c); namespace netlist { namespace factory { enum class element_type { BUILTIN, MACRO }; struct properties { properties(const pstring &defparam, plib::source_location &&sourceloc) : m_defparam(defparam) , m_sourceloc(std::move(sourceloc)) , m_type(element_type::BUILTIN) { } ~properties() = default; PCOPYASSIGNMOVE(properties, default) pstring defparam() const noexcept { return m_defparam; } plib::source_location source() const noexcept { return m_sourceloc; } element_type type() const noexcept { return m_type; } properties &set_type(element_type t) noexcept { m_type = t; return *this; } private: pstring m_defparam; plib::source_location m_sourceloc; element_type m_type; }; // ----------------------------------------------------------------------------- // net_dev class factory // ----------------------------------------------------------------------------- class element_t { public: using dev_uptr = device_arena::unique_ptr; using uptr = host_arena::unique_ptr; using pointer = element_t *; element_t(const pstring &name, properties &&props); virtual ~element_t() = default; PCOPYASSIGNMOVE(element_t, default) virtual dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) = 0; pstring name() const noexcept { return m_name; } pstring param_desc() const noexcept { return m_properties.defparam(); } plib::source_location source() const noexcept { return m_properties.source(); } element_type type() const noexcept { return m_properties.type(); } private: pstring m_name; ///< device name properties m_properties; ///< source file and other information and settings }; template class device_element_t : public element_t { public: device_element_t(const pstring &name, properties &&props, Args&&... args) : element_t(name, std::move(props)) , m_args(std::forward(args)...) { } template dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name, std::tuple& args, std::index_sequence) { return plib::make_unique(pool, anetlist, name, std::forward(std::get(args))...); //return anetlist.make_pool_object(anetlist, name, std::forward(std::get(args))...); } dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name, std::tuple& args) { return make_device(pool, anetlist, name, args, std::index_sequence_for{}); } dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) override { return make_device(pool, anetlist, name, m_args); //return pool.make_unique(anetlist, name); } static uptr create(const pstring &name, properties &&props, Args&&... args) { return plib::make_unique, host_arena>(name, std::move(props), std::forward(args)...); } private: std::tuple m_args; }; class list_t : public std::vector { public: explicit list_t(log_type &alog); ~list_t() = default; PCOPYASSIGNMOVE(list_t, delete) template void add(const pstring &name, properties &&props, Args&&... args) { add(device_element_t::create(name, std::move(props), std::forward(args)...)); } void add(element_t::uptr &&factory) noexcept(false); element_t::pointer factory_by_name(const pstring &devname) noexcept(false); template bool is_class(element_t::pointer f) noexcept { return dynamic_cast *>(f) != nullptr; } bool exists(const pstring &name) const noexcept; private: log_type &m_log; }; // ----------------------------------------------------------------------------- // factory_creator_ptr_t // ----------------------------------------------------------------------------- using constructor_ptr_t = element_t::uptr (*const)(); template element_t::uptr constructor_t(const pstring &name, properties &&props) { return plib::make_unique, host_arena>(name, std::move(props)); } // ----------------------------------------------------------------------------- // library_element_t: factory class to wrap macro based chips/elements // ----------------------------------------------------------------------------- class library_element_t : public element_t { public: library_element_t(const pstring &name, properties &&props); dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) override; }; } // namespace factory namespace devices { void initialize_factory(factory::list_t &factory); } // namespace devices } // namespace netlist #endif // NLFACTORY_H_