summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/nl_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/nl_base.h')
-rw-r--r--src/lib/netlist/nl_base.h167
1 files changed, 159 insertions, 8 deletions
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 90f1ea88d2e..6d52fed38ea 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -24,6 +24,7 @@
#include "plib/pstonum.h"
#include "plib/pstream.h"
#include "plib/ptime.h"
+#include "plib/ptypes.h"
#include "nl_errstr.h"
#include "nltypes.h"
@@ -174,7 +175,7 @@ class NETLIB_NAME(name) : public delegator_t<base_device_t>
#define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this)
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() noexcept override
-#define NETLIB_HANDLERI(name) virtual void name() noexcept
+#define NETLIB_HANDLERI(name) void name() noexcept
#define NETLIB_UPDATEI() virtual void update() noexcept override
#define NETLIB_UPDATE_PARAMI() virtual void update_param() noexcept override
#define NETLIB_RESETI() virtual void reset() override
@@ -1879,12 +1880,12 @@ namespace netlist
// Support classes for devices
// -----------------------------------------------------------------------------
- template<class C, int N>
- class object_array_t : public plib::uninitialised_array_t<C, N>
+ template<class C, std::size_t N>
+ class object_array_base_t : public plib::uninitialised_array_t<C, N>
{
public:
template<class D, typename... Args>
- object_array_t(D &dev, const std::initializer_list<const char *> &names, Args&&... args)
+ object_array_base_t(D &dev, const std::initializer_list<const char *> &names, Args&&... args)
{
passert_always_msg(names.size() == N, "initializer_list size mismatch");
std::size_t i = 0;
@@ -1892,20 +1893,170 @@ namespace netlist
this->emplace(i++, dev, pstring(n), std::forward<Args>(args)...);
}
+#if 0
template<class D, typename... Args>
- object_array_t(D &dev, const pstring &fmt, Args&&... args)
+ object_array_base_t(D &dev, const pstring &fmt, Args&&... args)
{
for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, plib::pfmt(fmt)(i), std::forward<Args>(args)...);
+ this->emplace(i, dev, formatted(fmt, i), std::forward<Args>(args)...);
}
template<class D, typename... Args>
- object_array_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args)
+ object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args)
{
for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, plib::pfmt(fmt)(i+offset), std::forward<Args>(args)...);
+ this->emplace(i, dev, formatted(fmt, i+offset), std::forward<Args>(args)...);
}
+ template<class D, typename... Args>
+ object_array_base_t(D &dev, std::size_t offset, std::size_t qmask, const pstring &fmt, Args&&... args)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ {
+ pstring name(formatted(fmt, i+offset));
+ if ((qmask >> i) & 1)
+ name += "Q";
+ this->emplace(i, dev, name, std::forward<Args>(args)...);
+ }
+ }
+#else
+ template<class D>
+ object_array_base_t(D &dev, const pstring &fmt)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace(i, dev, formatted(fmt, i));
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, std::size_t offset, const pstring &fmt)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace(i, dev, formatted(fmt, i+offset));
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, nldelegate &&delegate)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ this->emplace(i, dev, formatted(fmt, i+offset), std::move(delegate));
+ }
+
+ template<class D>
+ object_array_base_t(D &dev, std::size_t offset, std::size_t qmask, const pstring &fmt)
+ {
+ for (std::size_t i = 0; i<N; i++)
+ {
+ pstring name(formatted(fmt, i+offset));
+ if ((qmask >> i) & 1)
+ name += "Q";
+ this->emplace(i, dev, name);
+ }
+ }
+ protected:
+ object_array_base_t() = default;
+#endif
+
+ protected:
+ static pstring formatted(const pstring &fmt, std::size_t n)
+ {
+ if (N != 1)
+ return plib::pfmt(fmt)(n);
+ else
+ return plib::pfmt(fmt)("");
+ }
+ };
+
+ template<class C, std::size_t N>
+ class object_array_t : public object_array_base_t<C, N>
+ {
+ public:
+ using base_type = object_array_base_t<C, N>;
+ using base_type::base_type;
+ };
+
+ template<std::size_t N>
+ class object_array_t<logic_input_t,N> : public object_array_base_t<logic_input_t, N>
+ {
+ public:
+ using base_type = object_array_base_t<logic_input_t, N>;
+ using base_type::base_type;
+
+ template<class D, std::size_t ND>
+ object_array_t(D &dev, std::size_t offset, std::size_t qmask,
+// const pstring &fmt, std::initializer_list<nldelegate> &delegates)
+ const pstring &fmt, std::array<nldelegate, ND> &&delegates)
+ {
+ passert_always_msg(delegates.size() >= N, "initializer_list size mismatch");
+ std::size_t i = 0;
+ for (auto &e : delegates)
+ {
+ if (i < N)
+ {
+ pstring name(this->formatted(fmt, i+offset));
+ if ((qmask >> i) & 1)
+ name += "Q";
+ this->emplace(i, dev, name, e);
+ }
+ i++;
+ }
+ }
+
+
+ using value_type = typename plib::least_type_for_bits<N>::type;
+
+ value_type operator ()()
+ {
+ if (N <= 8)
+ return tobits(N, *this);
+ else
+ {
+ value_type r(0);
+ for (std::size_t i = 0; i < N; i++)
+ r = static_cast<value_type>((*this)[i]() << (N-1)) | (r >> 1);
+ return r;
+ }
+ }
+
+ private:
+ template <typename T>
+ static constexpr value_type tobits(std::size_t n, T &a)
+ {
+ return (n == 0 ? 0 : (tobits(n-1, a) | static_cast<value_type>(a[n-1]() << (n-1))));
+ }
+ };
+
+ template<std::size_t N>
+ class object_array_t<logic_output_t,N> : public object_array_base_t<logic_output_t, N>
+ {
+ public:
+ using base_type = object_array_base_t<logic_output_t, N>;
+ using base_type::base_type;
+
+ using value_type = typename plib::least_type_for_bits<N>::type;
+
+ void push(value_type v, netlist_time t)
+ {
+ if (N <= 8)
+ rpush(N, *this, v, t);
+ else
+ {
+ for (std::size_t i = 0; i < N; v = v >> 1, i++)
+ (*this)[i].push(v & 1, t);
+ }
+ }
+
+ private:
+ template <typename A, typename V, typename X>
+ static V rpush(std::size_t n, A &a, V value, X time)
+ {
+ if (n > 0)
+ {
+ value = rpush(n-1, a, value, time);
+ a[n-1].push((value & 1), time);
+ return value >> 1;
+ }
+ return value;
+ }
};
// -----------------------------------------------------------------------------