mame/src/lib/netlist/nl_factory.h
couriersud 324f9d44d5
netlist: More c++, less macros, added support for cspell (#9794)
- More c++, less macros
  * Significantly reduced the use of unused_var and replaced it with
    [[maybe_unused]]
  * use enum class in ppmf.h

- Changes to testing code in ptest.h
  * Catch exceptions in more places
  * The verbosity of the output can now be controlled
  * Display of test stats totals

- added support for cspell
- fixed various typos
- fixed SUBTARGET=nl build
- fixed more file permissions
- srcclean and add fix_permissions target to netlist makefile
2022-05-22 01:16:50 +10:00

222 lines
5.9 KiB
C++

// 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 <tuple>
#include <utility>
#include <vector>
#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<ns :: NETLIB_NAME(chip)>; \
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<core_device_t>;
using uptr = host_arena::unique_ptr<element_t>;
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 C, typename... Args>
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>(args)...)
{ }
template <std::size_t... Is>
dev_uptr make_device(device_arena &pool,
netlist_state_t &anetlist,
const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>)
{
return plib::make_unique<C>(pool, anetlist, name, std::forward<Args>(std::get<Is>(args))...);
}
dev_uptr make_device(device_arena &pool,
netlist_state_t &anetlist,
const pstring &name, std::tuple<Args...>& args)
{
return make_device(pool, anetlist, name, args, std::index_sequence_for<Args...>{});
}
dev_uptr make_device(device_arena &pool,
netlist_state_t &anetlist,
const pstring &name) override
{
return make_device(pool, anetlist, name, m_args);
}
static uptr create(const pstring &name, properties &&props, Args&&... args)
{
return plib::make_unique<device_element_t<C, Args...>, host_arena>(name,
std::move(props), std::forward<Args>(args)...);
}
private:
std::tuple<Args...> m_args;
};
class list_t : public std::vector<element_t::uptr>
{
public:
explicit list_t(log_type &alog);
~list_t() = default;
PCOPYASSIGNMOVE(list_t, delete)
template<class device_class, typename... Args>
void add(const pstring &name, properties &&props, Args&&... args)
{
add(device_element_t<device_class, Args...>::create(name, std::move(props),
std::forward<Args>(args)...));
}
void add(element_t::uptr &&factory) noexcept(false);
element_t::pointer factory_by_name(const pstring &devname) noexcept(false);
template <class C>
bool is_class(element_t::pointer f) noexcept
{
return dynamic_cast<device_element_t<C> *>(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 <typename T>
element_t::uptr constructor_t(const pstring &name, properties &&props)
{
return plib::make_unique<device_element_t<T>, 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_