// license:BSD-3-Clause // copyright-holders:Couriersud /// /// \file param.h /// #ifndef NL_CORE_OBJECT_ARRAY_H_ #define NL_CORE_OBJECT_ARRAY_H_ #include "../nltypes.h" #include "../plib/plists.h" #include "../plib/pstring.h" #include #include namespace netlist { template class object_array_base_t : public plib::static_vector { public: template //object_array_base_t(D &dev, const std::initializer_list &names, Args&&... args) object_array_base_t(D &dev, std::array &&names, Args&&... args) { for (std::size_t i = 0; iemplace_back(dev, pstring(names[i]), std::forward(args)...); } template object_array_base_t(D &dev, const pstring &fmt) { for (std::size_t i = 0; iemplace_back(dev, formatted(fmt, i)); } template object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args) { for (std::size_t i = 0; iemplace_back(dev, formatted(fmt, i+offset), std::forward(args)...); } template object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, nl_delegate delegate) { for (std::size_t i = 0; iemplace_back(dev, formatted(fmt, i+offset), delegate); } template object_array_base_t(D &dev, std::size_t offset, std::size_t output_mask, const pstring &fmt) { for (std::size_t i = 0; i> i) & 1) name += "Q"; this->emplace(i, dev, name); } } protected: object_array_base_t() = default; static pstring formatted(const pstring &fmt, std::size_t n) { if (N != 1) return plib::pfmt(fmt)(n); return plib::pfmt(fmt)(""); } }; template class object_array_t : public object_array_base_t { public: using base_type = object_array_base_t; using base_type::base_type; }; template class object_array_t : public object_array_base_t { public: using base_type = object_array_base_t; using base_type::base_type; template object_array_t(D &dev, std::size_t offset, std::size_t output_mask, const pstring &fmt, std::array &&delegates) { static_assert(N <= ND, "initializer_list size mismatch"); std::size_t i = 0; for (auto &e : delegates) { if (i < N) { pstring name(this->formatted(fmt, i+offset)); if ((output_mask >> i) & 1) name += "Q"; this->emplace_back(dev, name, e); } i++; } } //using value_type = typename plib::fast_type_for_bits::type; using value_type = std::uint32_t; value_type operator ()() { if (N == 1) return e<0>() ; if (N == 2) return e<0>() | (e<1>() << 1); if (N == 3) return e<0>() | (e<1>() << 1) | (e<2>() << 2); if (N == 4) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3); if (N == 5) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3) | (e<4>() << 4); if (N == 6) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3) | (e<4>() << 4) | (e<5>() << 5); if (N == 7) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3) | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6); if (N == 8) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3) | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6) | (e<7>() << 7); value_type r(0); for (std::size_t i = 0; i < N; i++) r = static_cast((*this)[i]() << (N-1)) | (r >> 1); return r; } private: template constexpr value_type e() const { return (*this)[P](); } }; template class object_array_t : public object_array_base_t { public: using base_type = object_array_base_t; using base_type::base_type; template void push(const T &v, const netlist_time &t) { if (N >= 1) (*this)[0].push((v >> 0) & 1, t); if (N >= 2) (*this)[1].push((v >> 1) & 1, t); if (N >= 3) (*this)[2].push((v >> 2) & 1, t); if (N >= 4) (*this)[3].push((v >> 3) & 1, t); if (N >= 5) (*this)[4].push((v >> 4) & 1, t); if (N >= 6) (*this)[5].push((v >> 5) & 1, t); if (N >= 7) (*this)[6].push((v >> 6) & 1, t); if (N >= 8) (*this)[7].push((v >> 7) & 1, t); for (std::size_t i = 8; i < N; i++) (*this)[i].push((v >> i) & 1, t); } template void push(const T &v, const netlist_time * t) { if (N >= 1) (*this)[0].push((v >> 0) & 1, t[0]); if (N >= 2) (*this)[1].push((v >> 1) & 1, t[1]); if (N >= 3) (*this)[2].push((v >> 2) & 1, t[2]); if (N >= 4) (*this)[3].push((v >> 3) & 1, t[3]); if (N >= 5) (*this)[4].push((v >> 4) & 1, t[4]); if (N >= 6) (*this)[5].push((v >> 5) & 1, t[5]); if (N >= 7) (*this)[6].push((v >> 6) & 1, t[6]); if (N >= 8) (*this)[7].push((v >> 7) & 1, t[7]); for (std::size_t i = 8; i < N; i++) (*this)[i].push((v >> i) & 1, t[i]); } template void push(const T &v, const std::array &t) { static_assert(NT >= N, "Not enough timing entries provided"); push(v, t.data()); } void set_tristate(netlist_sig_t v, netlist_time ts_off_on, netlist_time ts_on_off) noexcept { for (std::size_t i = 0; i < N; i++) (*this)[i].set_tristate(v, ts_off_on, ts_on_off); } }; template class object_array_t : public object_array_base_t { public: using base_type = object_array_base_t; using base_type::base_type; template void push(const T &v, const netlist_time &t) { if (N >= 1) (*this)[0].push((v >> 0) & 1, t); if (N >= 2) (*this)[1].push((v >> 1) & 1, t); if (N >= 3) (*this)[2].push((v >> 2) & 1, t); if (N >= 4) (*this)[3].push((v >> 3) & 1, t); if (N >= 5) (*this)[4].push((v >> 4) & 1, t); if (N >= 6) (*this)[5].push((v >> 5) & 1, t); if (N >= 7) (*this)[6].push((v >> 6) & 1, t); if (N >= 8) (*this)[7].push((v >> 7) & 1, t); for (std::size_t i = 8; i < N; i++) (*this)[i].push((v >> i) & 1, t); } void set_tristate(netlist_sig_t v, netlist_time ts_off_on, netlist_time ts_on_off) noexcept { for (std::size_t i = 0; i < N; i++) (*this)[i].set_tristate(v, ts_off_on, ts_on_off); } }; // ----------------------------------------------------------------------------- // Externals // ----------------------------------------------------------------------------- extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; extern template class object_array_t; } // namespace netlist #endif // NL_CORE_OBJECT_ARRAY_H_