diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 973a5f2cb25..af55f7338d0 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -1252,6 +1252,16 @@ uint64_t netlist_mame_cpu_device::execute_cycles_to_clocks(uint64_t cycles) cons return cycles; } +netlist::netlist_time_ext netlist_mame_cpu_device::nltime_ext_from_clocks(unsigned c) const noexcept +{ + return (m_div * c).shr(MDIV_SHIFT); +} + +netlist::netlist_time netlist_mame_cpu_device::nltime_from_clocks(unsigned c) const noexcept +{ + return static_cast((m_div * c).shr(MDIV_SHIFT)); +} + void netlist_mame_cpu_device::execute_run() { //m_ppc = m_pc; // copy PC to previous PC diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index dc1f651e1c4..ff9adf7d332 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -193,16 +193,6 @@ public: void update_icount(netlist::netlist_time_ext time) noexcept; void check_mame_abort_slice() noexcept; - netlist::netlist_time_ext nltime_ext_from_clocks(unsigned c) const noexcept - { - return (m_div * c).shr(MDIV_SHIFT); - } - - netlist::netlist_time nltime_from_clocks(unsigned c) const noexcept - { - return static_cast((m_div * c).shr(MDIV_SHIFT)); - } - protected: // netlist_mame_device virtual void nl_register_devices(netlist::nlparse_t &parser) const override; @@ -229,6 +219,9 @@ protected: address_space_config m_program_config; private: + netlist::netlist_time_ext nltime_ext_from_clocks(unsigned c) const noexcept; + netlist::netlist_time nltime_from_clocks(unsigned c) const noexcept; + int m_icount; netlist::netlist_time_ext m_div; netlist::netlist_time_ext m_rem; @@ -255,6 +248,8 @@ private: // ---------------------------------------------------------------------------------------- // netlist_mame_sound_input_buffer +// +// This is a wrapper device to provide operator[] on read_stream_view. // ---------------------------------------------------------------------------------------- class netlist_mame_sound_input_buffer : public read_stream_view diff --git a/src/devices/video/fixfreq.cpp b/src/devices/video/fixfreq.cpp index 74db7c77216..e3f2f5f735d 100644 --- a/src/devices/video/fixfreq.cpp +++ b/src/devices/video/fixfreq.cpp @@ -19,9 +19,14 @@ #include "render.h" #include "ui/uimain.h" +#include + // for quick and dirty debugging #define VERBOSE 0 +#define LOG_GENERAL (1U << 0) + #define LOG_OUTPUT_STREAM std::cerr + #include "logmacro.h" #include diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp index 18832d0e4d7..eadb725c5c1 100644 --- a/src/lib/netlist/analog/nld_bjt.cpp +++ b/src/lib/netlist/analog/nld_bjt.cpp @@ -130,32 +130,6 @@ namespace analog }; - // Have a common start for transistors - - NETLIB_BASE_OBJECT(QBJT) - { - public: - - NETLIB_CONSTRUCTOR_EX(QBJT, const pstring &model = "NPN") - , m_model(*this, "MODEL", model) - , m_qtype(bjt_type::BJT_NPN) - { - } - - NETLIB_IS_DYNAMIC(true) - - //NETLIB_RESETI(); - - bjt_type qtype() const noexcept { return m_qtype; } - bool is_qtype(bjt_type atype) const noexcept { return m_qtype == atype; } - void set_qtype(bjt_type atype) noexcept { m_qtype = atype; } - protected: - - param_model_t m_model; - private: - bjt_type m_qtype; - }; - // ----------------------------------------------------------------------------- // nld_QBJT_switch // ----------------------------------------------------------------------------- @@ -174,9 +148,12 @@ namespace analog // E // - NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT) + class nld_QBJT_switch : public base_device_t { - NETLIB_CONSTRUCTOR(QBJT_switch) + public: \ + nld_QBJT_switch(constructor_param_t data) + : base_device_t(data) + , m_model(*this, "MODEL", "NPN") , m_bjt_model(m_model) , m_RB(*this, "m_RB", NETLIB_DELEGATE(terminal_handler)) , m_RC(*this, "m_RC", NETLIB_DELEGATE(terminal_handler)) @@ -205,14 +182,17 @@ namespace analog m_RC.solver()->solve_now(); } + NETLIB_IS_DYNAMIC(true) + NETLIB_UPDATE_PARAMI(); NETLIB_UPDATE_TERMINALSI(); private: + param_model_t m_model; bjt_model_t m_bjt_model; - nld_two_terminal m_RB; - nld_two_terminal m_RC; - nld_two_terminal m_BC; + NETLIB_NAME(two_terminal) m_RB; + NETLIB_NAME(two_terminal) m_RC; + NETLIB_NAME(two_terminal) m_BC; nl_fptype m_gB; // base conductance / switch on nl_fptype m_gC; // collector conductance / switch on @@ -226,10 +206,12 @@ namespace analog // ----------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT) + class nld_QBJT_EB : public base_device_t { - public: - NETLIB_CONSTRUCTOR(QBJT_EB) + public: \ + nld_QBJT_EB(constructor_param_t data) + : base_device_t(data) + , m_model(*this, "MODEL", "NPN") , m_bjt_model(m_model) , m_gD_BC(*this, "m_D_BC") , m_gD_BE(*this, "m_D_BE") @@ -275,17 +257,20 @@ namespace analog m_D_CB.solver()->solve_now(); } + NETLIB_IS_DYNAMIC(true) + NETLIB_UPDATE_PARAMI(); NETLIB_UPDATE_TERMINALSI(); private: + param_model_t m_model; bjt_model_t m_bjt_model; generic_diode m_gD_BC; generic_diode m_gD_BE; - nld_two_terminal m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic - nld_two_terminal m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie - nld_two_terminal m_D_EC; // 0, -gec, -gcc, 0 | 0 + NETLIB_NAME(two_terminal) m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic + NETLIB_NAME(two_terminal) m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie + NETLIB_NAME(two_terminal) m_D_EC; // 0, -gec, -gcc, 0 | 0 nl_fptype m_alpha_f; nl_fptype m_alpha_r; @@ -304,8 +289,8 @@ namespace analog { if (m_RB.solver() == nullptr && m_RC.solver() == nullptr) throw nl_exception(MF_DEVICE_FRY_1(this->name())); - NETLIB_NAME(QBJT)::reset(); - const auto zero(nlconst::zero()); + + static constexpr const auto zero(nlconst::zero()); m_state_on = 0; @@ -323,9 +308,6 @@ namespace analog nl_fptype NF = m_bjt_model.m_NF; //nl_fptype VJE = m_bjt_model.dValue("VJE", 0.75); - // FIXME: check for PNP as well and bail out - set_qtype(m_bjt_model.m_type); - nl_fptype alpha = BF / (nlconst::one() + BF); diode d(IS, NF); @@ -349,7 +331,7 @@ namespace analog NETLIB_UPDATE_TERMINALS(QBJT_switch) { - const nl_fptype m = (is_qtype( bjt_type::BJT_NPN) ? 1 : -1); + const nl_fptype m = (m_bjt_model.m_type == bjt_type::BJT_NPN) ? nlconst::one() : -nlconst::one(); const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0; if (m_state_on ^ new_state) @@ -374,7 +356,7 @@ namespace analog { if (m_D_EB.solver() == nullptr && m_D_CB.solver() == nullptr) throw nl_exception(MF_DEVICE_FRY_1(this->name())); - NETLIB_NAME(QBJT)::reset(); + if (m_CJE) { m_CJE->reset(); @@ -389,7 +371,7 @@ namespace analog NETLIB_UPDATE_TERMINALS(QBJT_EB) { - const nl_fptype polarity(qtype() == bjt_type::BJT_NPN ? nlconst::one() : -nlconst::one()); + const nl_fptype polarity(m_bjt_model.m_type == bjt_type::BJT_NPN ? nlconst::one() : -nlconst::one()); m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity); m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity); @@ -422,9 +404,6 @@ namespace analog nl_fptype NR = m_bjt_model.m_NR; //nl_fptype VJE = m_m_bjt_model.dValue("VJE", 0.75); - // FIXME: check for PNP as well and bail out - set_qtype(m_bjt_model.m_type); - m_alpha_f = BF / (nlconst::one() + BF); m_alpha_r = BR / (nlconst::one() + BR); diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index 46dead610ca..805c2dd1e4b 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -149,44 +149,17 @@ namespace analog param_model_t::value_base_t m_CAPMOD; //!< Capacitance model (0=no model 2=Meyer) }; - // Have a common start for mosfets + // ----------------------------------------------------------------------------- + // nld_MOSFET + // ----------------------------------------------------------------------------- - NETLIB_BASE_OBJECT(FET) + class nld_MOSFET : public base_device_t { public: - enum q_type { - FET_NMOS, - FET_PMOS - }; - - NETLIB_CONSTRUCTOR(FET) + public: \ + nld_MOSFET(constructor_param_t data) + : base_device_t(data) , m_model(*this, "MODEL", "NMOS") - , m_qtype(FET_NMOS) - { - } - - NETLIB_IS_DYNAMIC(true) - - //NETLIB_RESETI(); - - q_type qtype() const noexcept { return m_qtype; } - bool is_qtype(q_type atype) const noexcept { return m_qtype == atype; } - void set_qtype(q_type atype) noexcept { m_qtype = atype; } - protected: - - param_model_t m_model; - private: - q_type m_qtype; - }; - - // ----------------------------------------------------------------------------- - // nld_QBJT_EB - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT_DERIVED(MOSFET, FET) - { - public: - NETLIB_CONSTRUCTOR(MOSFET) , m_DG(*this, "m_DG", NETLIB_DELEGATE(terminal_handler)) , m_SG(*this, "m_SG", NETLIB_DELEGATE(terminal_handler)) , m_SD(*this, "m_SD", NETLIB_DELEGATE(terminal_handler)) @@ -204,7 +177,7 @@ namespace analog , m_lambda(nlconst::zero()) , m_Leff(nlconst::zero()) , m_CoxWL(nlconst::zero()) - , m_polarity(qtype() == FET_NMOS ? nlconst::one() : -nlconst::one()) + //S, m_polarity(qtype() == FET_NMOS ? nlconst::one() : -nlconst::one()) , m_Cgb(nlconst::zero()) , m_Cgs(nlconst::zero()) , m_Cgd(nlconst::zero()) @@ -222,8 +195,7 @@ namespace analog connect(m_SG.N(), m_DG.N()); connect(m_DG.P(), m_SD.N()); - set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS); - m_polarity = (qtype() == FET_NMOS ? nlconst::one() : -nlconst::one()); + m_polarity = (m_model.type() == "NMOS_DEFAULT" ? nlconst::one() : -nlconst::one()); m_capacitor_model = m_model_acc.m_CAPMOD; //# printf("capmod %d %g %g\n", m_capacitor_model, (nl_fptype)m_model_acc.m_VTO, m_polarity); @@ -296,6 +268,7 @@ namespace analog //#printf("Cox: %g\n", m_Cox); } + NETLIB_IS_DYNAMIC(true) NETLIB_IS_TIMESTEP(true || m_capacitor_model != 0) NETLIB_TIMESTEPI() @@ -328,7 +301,6 @@ namespace analog NETLIB_RESETI() { - NETLIB_NAME(FET)::reset(); // Bulk diodes m_D_BD.set_param(m_model_acc.m_ISD, m_model_acc.m_N, exec().gmin(), constants::T0()); @@ -351,9 +323,11 @@ namespace analog private: - nld_two_terminal m_DG; - nld_two_terminal m_SG; - nld_two_terminal m_SD; + param_model_t m_model; + + NETLIB_NAME(two_terminal) m_DG; + NETLIB_NAME(two_terminal) m_SG; + NETLIB_NAME(two_terminal) m_SD; generic_diode m_D_BD; #if (!BODY_CONNECTED_TO_SOURCE) @@ -594,14 +568,14 @@ namespace analog const nl_fptype gSSBB = gSS + gBB + gBS + gSB; const auto zero(nlconst::zero()); // S G - m_SG.set_mat( gSSBB, gSG + gBG, +(IS + IB), // S - gGS + gGB, gGG, IG ); // G + m_SG.set_mat( gSSBB, gSG + gBG, +(IS + IB), // S + gGS + gGB, gGG, IG ); // G // D G - m_DG.set_mat( gDD, gDG, +ID, // D - gGD, zero, zero ); // G + m_DG.set_mat( gDD, gDG, +ID, // D + gGD, zero, zero ); // G // S D - m_SD.set_mat( zero, gSD + gBD, zero, // S - gDS + gDB, zero, zero); // D + m_SD.set_mat( zero, gSD + gBD, zero, // S + gDS + gDB, zero, zero ); // D } NETLIB_UPDATE_PARAM(MOSFET) diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp index f68088a6619..b7e4ebfa762 100644 --- a/src/lib/netlist/analog/nld_opamps.cpp +++ b/src/lib/netlist/analog/nld_opamps.cpp @@ -101,9 +101,11 @@ namespace netlist }; - NETLIB_BASE_OBJECT(opamp) + class nld_opamp : public base_device_t { - NETLIB_CONSTRUCTOR(opamp) + public: + nld_opamp(constructor_param_t data) + : base_device_t(data) , m_RP(*this, "RP1") , m_G1(*this, "G1") , m_VCC(*this, "VCC", NETLIB_DELEGATE(supply)) @@ -113,8 +115,8 @@ namespace netlist , m_VH(*this, "VH") , m_VL(*this, "VL") , m_VREF(*this, "VREF") + , m_type(plib::narrow_cast(m_modacc.m_TYPE)) { - m_type = plib::narrow_cast(m_modacc.m_TYPE); if (m_type < 1 || m_type > 3) { log().fatal(MF_OPAMP_UNKNOWN_TYPE(m_type)); @@ -201,8 +203,8 @@ namespace netlist private: - analog::NETLIB_SUB(R_base) m_RP; - analog::NETLIB_SUB(VCCS) m_G1; + NETLIB_SUB_NS(analog, R_base) m_RP; + NETLIB_SUB_NS(analog, VCCS) m_G1; NETLIB_SUB_UPTR(analog, C) m_CP; #if TEST_ALT_OUTPUT NETLIB_SUB_UPTR(analog, R_base) m_RO; @@ -226,14 +228,14 @@ namespace netlist NETLIB_UPDATE_PARAM(opamp) { - m_G1.m_RI.set(m_modacc.m_RI); + m_G1().m_RI.set(m_modacc.m_RI); if (m_type == 1) { nl_fptype RO = m_modacc.m_RO; nl_fptype G = m_modacc.m_UGF / m_modacc.m_FPF / RO; - m_RP.set_R(RO); - m_G1.m_G.set(G); + m_RP().set_R(RO); + m_G1().m_G.set(G); } if (m_type == 3 || m_type == 2) { @@ -246,8 +248,8 @@ namespace netlist log().warning(MW_OPAMP_FAIL_CONVERGENCE(this->name())); m_CP->set_cap_embedded(CP); - m_RP.set_R(RP); - m_G1.m_G.set(G); + m_RP().set_R(RP); + m_G1().m_G.set(G); } if (m_type == 2) diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp index 169d6465969..6b87279e398 100644 --- a/src/lib/netlist/analog/nld_switches.cpp +++ b/src/lib/netlist/analog/nld_switches.cpp @@ -19,65 +19,69 @@ namespace netlist // SWITCH // ---------------------------------------------------------------------------------------- - NETLIB_BASE_OBJECT(switch1) + class nld_switch1 : public base_device_t { - NETLIB_CONSTRUCTOR(switch1) + public: + nld_switch1(constructor_param_t data) + : base_device_t(data) , m_R(*this, "R") , m_POS(*this, "POS", false) { - register_sub_alias("1", m_R.P()); - register_sub_alias("2", m_R.N()); + register_sub_alias("1", m_R().P()); + register_sub_alias("2", m_R().N()); } NETLIB_RESETI() { - m_R.set_R(R_OFF); + m_R().set_R(R_OFF); } NETLIB_UPDATE_PARAMI() { - m_R.change_state([this]() + m_R().change_state([this]() { - m_R.set_R(m_POS() ? R_ON : R_OFF); + m_R().set_R(m_POS() ? R_ON : R_OFF); }); } private: - analog::NETLIB_SUB(R_base) m_R; - param_logic_t m_POS; + NETLIB_SUB_NS(analog, R_base) m_R; + param_logic_t m_POS; }; // ---------------------------------------------------------------------------------------- // SWITCH2 // ---------------------------------------------------------------------------------------- - NETLIB_BASE_OBJECT(switch2) + class nld_switch2 : public base_device_t { - NETLIB_CONSTRUCTOR(switch2) + public: + nld_switch2(constructor_param_t data) + : base_device_t(data) , m_R1(*this, "R1") , m_R2(*this, "R2") , m_POS(*this, "POS", false) { - connect(m_R1.N(), m_R2.N()); + connect(m_R1().N(), m_R2().N()); - register_sub_alias("1", m_R1.P()); - register_sub_alias("2", m_R2.P()); + register_sub_alias("1", m_R1().P()); + register_sub_alias("2", m_R2().P()); - register_sub_alias("Q", m_R1.N()); + register_sub_alias("Q", m_R1().N()); } NETLIB_RESETI(); NETLIB_UPDATE_PARAMI(); private: - analog::NETLIB_SUB(R_base) m_R1; - analog::NETLIB_SUB(R_base) m_R2; - param_logic_t m_POS; + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; + param_logic_t m_POS; }; NETLIB_RESET(switch2) { - m_R1.set_R(R_ON); - m_R2.set_R(R_OFF); + m_R1().set_R(R_ON); + m_R2().set_R(R_OFF); } #ifdef FIXMELATER @@ -103,12 +107,12 @@ namespace netlist nl_fptype r1 = m_POS() ? R_OFF : R_ON; nl_fptype r2 = m_POS() ? R_ON : R_OFF; - if (m_R1.solver() == m_R2.solver()) - m_R1.change_state([this, &r1, &r2]() { m_R1.set_R(r1); m_R2.set_R(r2); }); + if (m_R1().solver() == m_R2().solver()) + m_R1().change_state([this, &r1, &r2]() { m_R1().set_R(r1); m_R2().set_R(r2); }); else { - m_R1.change_state([this, &r1]() { m_R1.set_R(r1); }); - m_R2.change_state([this, &r2]() { m_R2.set_R(r2); }); + m_R1().change_state([this, &r1]() { m_R1().set_R(r1); }); + m_R2().change_state([this, &r2]() { m_R2().set_R(r2); }); } } diff --git a/src/lib/netlist/analog/nlid_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp index 9e1f185e79c..e12a931c142 100644 --- a/src/lib/netlist/analog/nlid_fourterm.cpp +++ b/src/lib/netlist/analog/nlid_fourterm.cpp @@ -1,139 +1,129 @@ // license:BSD-3-Clause // copyright-holders:Couriersud -#include "solver/nld_solver.h" -#include "nl_factory.h" #include "nlid_fourterm.h" -namespace netlist +#include "nl_factory.h" + +#include "solver/nld_solver.h" + +namespace netlist::analog { - namespace analog + + // ------------------------------------------------------------------------- + // nld_VCCS + // ------------------------------------------------------------------------- + + NETLIB_RESET(VCCS) { + const nl_fptype m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A + const nl_fptype GI = plib::reciprocal(m_RI()); + m_IP.set_conductivity(GI); + m_IN.set_conductivity(GI); -// ---------------------------------------------------------------------------------------- -// nld_VCCS -// ---------------------------------------------------------------------------------------- + m_OP.set_go_gt(-m_mult, nlconst::zero()); + m_OP1.set_go_gt(m_mult, nlconst::zero()); -NETLIB_RESET(VCCS) + m_ON.set_go_gt(m_mult, nlconst::zero()); + m_ON1.set_go_gt(-m_mult, nlconst::zero()); + } + + NETLIB_HANDLER(VCCS, terminal_handler) + { + solver::matrix_solver_t *solv = nullptr; + // only called if connected to a rail net ==> notify the solver to + // recalculate + // NOLINTNEXTLINE(bugprone-branch-clone) + if ((solv = m_IP.solver()) != nullptr) + solv->solve_now(); + else if ((solv = m_IN.solver()) != nullptr) + solv->solve_now(); + else if ((solv = m_OP.solver()) != nullptr) + solv->solve_now(); + else if ((solv = m_ON.solver()) != nullptr) + solv->solve_now(); + } + + // ------------------------------------------------------------------------- + // nld_LVCCS + // ------------------------------------------------------------------------- + + NETLIB_RESET(LVCCS) { NETLIB_NAME(VCCS)::reset(); } + + NETLIB_UPDATE_PARAM(LVCCS) { NETLIB_NAME(VCCS)::update_param(); } + + NETLIB_UPDATE_TERMINALS(LVCCS) + { + const nl_fptype m_mult = m_G() * get_gfac(); // 1.0 ==> 1V ==> 1A + const nl_fptype vi = m_IP.net().Q_Analog() - m_IN.net().Q_Analog(); + const auto c1(nlconst::magic(0.2)); + + if (plib::abs(m_mult / m_cur_limit() * vi) > nlconst::half()) + m_vi = m_vi + c1 * plib::tanh((vi - m_vi) / c1); + else + m_vi = vi; + + const nl_fptype x = m_mult / m_cur_limit() * m_vi; + const nl_fptype tanhx = plib::tanh(x); + + const nl_fptype beta = m_mult * (nlconst::one() - tanhx * tanhx); + const nl_fptype I = m_cur_limit() * tanhx - beta * m_vi; + + m_OP.set_go_gt_I(-beta, nlconst::zero(), I); + m_OP1.set_go_gt(beta, nlconst::zero()); + + m_ON.set_go_gt_I(beta, nlconst::zero(), -I); + m_ON1.set_go_gt(-beta, nlconst::zero()); + } + + // ------------------------------------------------------------------------- + // nld_CCCS + // ------------------------------------------------------------------------- + + NETLIB_RESET(CCCS) { NETLIB_NAME(VCCS)::reset(); } + + NETLIB_UPDATE_PARAM(CCCS) { NETLIB_NAME(VCCS)::update_param(); } + + // ------------------------------------------------------------------------- + // nld_VCVS + // ------------------------------------------------------------------------- + + NETLIB_RESET(VCVS) + { + const auto gfac(plib::reciprocal(m_RO())); + set_gfac(gfac); + + NETLIB_NAME(VCCS)::reset(); + + m_OP2.set_conductivity(gfac); + m_ON2.set_conductivity(gfac); + } + + // ------------------------------------------------------------------------- + // nld_CCVS + // ------------------------------------------------------------------------- + + NETLIB_RESET(CCVS) + { + const auto gfac(plib::reciprocal(m_RO())); + set_gfac(gfac); + + NETLIB_NAME(VCCS)::reset(); + + m_OP2.set_conductivity(gfac); + m_ON2.set_conductivity(gfac); + } + +} // namespace netlist::analog + +namespace netlist::devices { - const nl_fptype m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A - const nl_fptype GI = plib::reciprocal(m_RI()); - - m_IP.set_conductivity(GI); - m_IN.set_conductivity(GI); - - m_OP.set_go_gt(-m_mult, nlconst::zero()); - m_OP1.set_go_gt(m_mult, nlconst::zero()); - - m_ON.set_go_gt(m_mult, nlconst::zero()); - m_ON1.set_go_gt(-m_mult, nlconst::zero()); -} - -NETLIB_HANDLER(VCCS, terminal_handler) -{ - solver::matrix_solver_t *solv = nullptr; - // only called if connected to a rail net ==> notify the solver to recalculate - // NOLINTNEXTLINE(bugprone-branch-clone) - if ((solv = m_IP.solver()) != nullptr) - solv->solve_now(); - else if ((solv = m_IN.solver()) != nullptr) - solv->solve_now(); - else if ((solv = m_OP.solver()) != nullptr) - solv->solve_now(); - else if ((solv = m_ON.solver()) != nullptr) - solv->solve_now(); -} - -// ---------------------------------------------------------------------------------------- -// nld_LVCCS -// ---------------------------------------------------------------------------------------- - -NETLIB_RESET(LVCCS) -{ - NETLIB_NAME(VCCS)::reset(); -} - -NETLIB_UPDATE_PARAM(LVCCS) -{ - NETLIB_NAME(VCCS)::update_param(); -} - -NETLIB_UPDATE_TERMINALS(LVCCS) -{ - const nl_fptype m_mult = m_G() * get_gfac(); // 1.0 ==> 1V ==> 1A - const nl_fptype vi = m_IP.net().Q_Analog() - m_IN.net().Q_Analog(); - const auto c1(nlconst::magic(0.2)); - - if (plib::abs(m_mult / m_cur_limit() * vi) > nlconst::half()) - m_vi = m_vi + c1 * plib::tanh((vi - m_vi) / c1); - else - m_vi = vi; - - const nl_fptype x = m_mult / m_cur_limit() * m_vi; - const nl_fptype tanhx = plib::tanh(x); - - const nl_fptype beta = m_mult * (nlconst::one() - tanhx*tanhx); - const nl_fptype I = m_cur_limit() * tanhx - beta * m_vi; - - m_OP.set_go_gt_I(-beta, nlconst::zero(), I); - m_OP1.set_go_gt(beta, nlconst::zero()); - - m_ON.set_go_gt_I(beta, nlconst::zero(), -I); - m_ON1.set_go_gt(-beta, nlconst::zero()); -} - -// ---------------------------------------------------------------------------------------- -// nld_CCCS -// ---------------------------------------------------------------------------------------- - -NETLIB_RESET(CCCS) -{ - NETLIB_NAME(VCCS)::reset(); -} - -NETLIB_UPDATE_PARAM(CCCS) -{ - NETLIB_NAME(VCCS)::update_param(); -} - -// ---------------------------------------------------------------------------------------- -// nld_VCVS -// ---------------------------------------------------------------------------------------- - -NETLIB_RESET(VCVS) -{ - const auto gfac(plib::reciprocal(m_RO())); - set_gfac(gfac); - - NETLIB_NAME(VCCS)::reset(); - - m_OP2.set_conductivity(gfac); - m_ON2.set_conductivity(gfac); -} - -// ---------------------------------------------------------------------------------------- -// nld_CCVS -// ---------------------------------------------------------------------------------------- - -NETLIB_RESET(CCVS) -{ - const auto gfac(plib::reciprocal(m_RO())); - set_gfac(gfac); - - NETLIB_NAME(VCCS)::reset(); - - m_OP2.set_conductivity(gfac); - m_ON2.set_conductivity(gfac); -} - - } //namespace analog - - namespace devices { - NETLIB_DEVICE_IMPL_NS(analog, VCVS, "VCVS", "G") - NETLIB_DEVICE_IMPL_NS(analog, VCCS, "VCCS", "G") - NETLIB_DEVICE_IMPL_NS(analog, CCCS, "CCCS", "G") - NETLIB_DEVICE_IMPL_NS(analog, CCVS, "CCVS", "G") - NETLIB_DEVICE_IMPL_NS(analog, LVCCS, "LVCCS", "") - } // namespace devices -} // namespace netlist + // clang-format off + NETLIB_DEVICE_IMPL_NS(analog, VCVS, "VCVS", "G") + NETLIB_DEVICE_IMPL_NS(analog, VCCS, "VCCS", "G") + NETLIB_DEVICE_IMPL_NS(analog, CCCS, "CCCS", "G") + NETLIB_DEVICE_IMPL_NS(analog, CCVS, "CCVS", "G") + NETLIB_DEVICE_IMPL_NS(analog, LVCCS, "LVCCS", "") + // clang-format on +} // namespace netlist::devices diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h index 9f71964c6d1..1320f97984b 100644 --- a/src/lib/netlist/analog/nlid_fourterm.h +++ b/src/lib/netlist/analog/nlid_fourterm.h @@ -9,9 +9,11 @@ /// #include "nl_base.h" + #include "plib/putil.h" -namespace netlist::analog { +namespace netlist::analog +{ // ---------------------------------------------------------------------------------------- // nld_VCCS @@ -32,26 +34,27 @@ namespace netlist::analog { // // RI = 1 / NETLIST_GMIN // - NETLIB_BASE_OBJECT(VCCS) + class nld_VCCS : public base_device_t { public: - NETLIB_CONSTRUCTOR_EX(VCCS, nl_fptype ri = nlconst::magic(1e9)) + nld_VCCS(constructor_param_t data, nl_fptype ri = nlconst::magic(1e9)) + : base_device_t(data) , m_G(*this, "G", nlconst::one()) , m_RI(*this, "RI", ri) - , m_OP(*this, "OP", &m_IP, {&m_ON, &m_IN}, NETLIB_DELEGATE(terminal_handler)) - , m_ON(*this, "ON", &m_IP, {&m_OP, &m_IN}, NETLIB_DELEGATE(terminal_handler)) - , m_IP(*this, "IP", &m_IN, {&m_OP, &m_ON}, NETLIB_DELEGATE(terminal_handler)) - , m_IN(*this, "IN", &m_IP, {&m_OP, &m_ON}, NETLIB_DELEGATE(terminal_handler)) + , m_OP(*this, "OP", &m_IP, {&m_ON, &m_IN}, + NETLIB_DELEGATE(terminal_handler)) + , m_ON(*this, "ON", &m_IP, {&m_OP, &m_IN}, + NETLIB_DELEGATE(terminal_handler)) + , m_IP(*this, "IP", &m_IN, {&m_OP, &m_ON}, + NETLIB_DELEGATE(terminal_handler)) + , m_IN(*this, "IN", &m_IP, {&m_OP, &m_ON}, + NETLIB_DELEGATE(terminal_handler)) , m_OP1(*this, "_OP1", &m_IN, NETLIB_DELEGATE(terminal_handler)) , m_ON1(*this, "_ON1", &m_IN, NETLIB_DELEGATE(terminal_handler)) - //, m_IPx(*this, "_IPx", &m_OP, NETLIB_DELEGATE(terminal_handler)) // <= this should be NULL and terminal be filtered out prior to solving... - //, m_INx(*this, "_INx", &m_ON, NETLIB_DELEGATE(terminal_handler)) // <= this should be NULL and terminal be filtered out prior to solving... , m_gfac(nlconst::one()) { connect(m_OP, m_OP1); connect(m_ON, m_ON1); - //connect(m_IP, m_IPx); - //connect(m_IN, m_INx); } NETLIB_RESETI(); @@ -61,20 +64,11 @@ namespace netlist::analog { protected: NETLIB_HANDLERI(terminal_handler); - NETLIB_UPDATE_PARAMI() - { - NETLIB_NAME(VCCS)::reset(); - } + NETLIB_UPDATE_PARAMI() { NETLIB_NAME(VCCS)::reset(); } - void set_gfac(nl_fptype g) noexcept - { - m_gfac = g; - } + void set_gfac(nl_fptype g) noexcept { m_gfac = g; } - nl_fptype get_gfac() const noexcept - { - return m_gfac; - } + nl_fptype get_gfac() const noexcept { return m_gfac; } terminal_t m_OP; terminal_t m_ON; @@ -85,19 +79,17 @@ namespace netlist::analog { terminal_t m_OP1; terminal_t m_ON1; - //terminal_t m_IPx; - //terminal_t m_INx; - private: nl_fptype m_gfac; }; // Limited Current source - NETLIB_OBJECT_DERIVED(LVCCS, VCCS) + class nld_LVCCS : public nld_VCCS { public: - NETLIB_CONSTRUCTOR(LVCCS) + nld_LVCCS(constructor_param_t data) + : nld_VCCS(data) , m_cur_limit(*this, "CURLIM", nlconst::magic(1000.0)) , m_vi(nlconst::zero()) { @@ -106,14 +98,13 @@ namespace netlist::analog { NETLIB_IS_DYNAMIC(true) protected: - //NETLIB_UPDATEI(); NETLIB_RESETI(); NETLIB_UPDATE_PARAMI(); NETLIB_UPDATE_TERMINALSI(); private: param_fp_t m_cur_limit; // current limit - nl_fptype m_vi; + nl_fptype m_vi; }; // ---------------------------------------------------------------------------------------- @@ -140,10 +131,11 @@ namespace netlist::analog { // This needs high levels of accuracy to work with 1 Ohm RI. // - NETLIB_OBJECT_DERIVED(CCCS, VCCS) + class nld_CCCS : public nld_VCCS { public: - NETLIB_CONSTRUCTOR_PASS(CCCS, nlconst::one()) + nld_CCCS(constructor_param_t data) + : nld_VCCS(data, nlconst::one()) { set_gfac(-plib::reciprocal(m_RI())); } @@ -151,11 +143,9 @@ namespace netlist::analog { NETLIB_RESETI(); protected: - //NETLIB_UPDATEI(); NETLIB_UPDATE_PARAMI(); }; - // ---------------------------------------------------------------------------------------- // nld_VCVS // ---------------------------------------------------------------------------------------- @@ -182,10 +172,11 @@ namespace netlist::analog { // Internal GI = G / RO // - NETLIB_OBJECT_DERIVED(VCVS, VCCS) + class nld_VCVS : public nld_VCCS { public: - NETLIB_CONSTRUCTOR(VCVS) + nld_VCVS(constructor_param_t data) + : nld_VCCS(data) , m_RO(*this, "RO", nlconst::one()) , m_OP2(*this, "_OP2", &m_ON2, NETLIB_DELEGATE(terminal_handler)) , m_ON2(*this, "_ON2", &m_OP2, NETLIB_DELEGATE(terminal_handler)) @@ -199,16 +190,14 @@ namespace netlist::analog { param_fp_t m_RO; private: - //NETLIB_UPDATE_PARAMI(); + // NETLIB_UPDATE_PARAMI(); NETLIB_HANDLERI(terminal_handler) { - NETLIB_NAME(VCCS) :: terminal_handler(); + NETLIB_NAME(VCCS)::terminal_handler(); } terminal_t m_OP2; terminal_t m_ON2; - - }; // ---------------------------------------------------------------------------------------- @@ -225,7 +214,7 @@ namespace netlist::analog { // IP ---+ +--+---- OP // | | | // RI I RO - // RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) / RI * G + // RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) / RI * G // RI I RO // | | | // IN ---+ +--+---- ON @@ -237,10 +226,11 @@ namespace netlist::analog { // Internal GI = G / RO // - NETLIB_OBJECT_DERIVED(CCVS, VCCS) + class nld_CCVS : public nld_VCCS { public: - NETLIB_CONSTRUCTOR_PASS(CCVS, nlconst::one()) + nld_CCVS(constructor_param_t data) + : nld_VCCS(data, nlconst::one()) , m_RO(*this, "RO", nlconst::one()) , m_OP2(*this, "_OP2", &m_ON2, NETLIB_DELEGATE(terminal_handler)) , m_ON2(*this, "_ON2", &m_OP2, NETLIB_DELEGATE(terminal_handler)) @@ -254,18 +244,17 @@ namespace netlist::analog { param_fp_t m_RO; private: - //NETLIB_UPDATE_PARAMI(); + // NETLIB_UPDATE_PARAMI(); NETLIB_HANDLERI(terminal_handler) { - NETLIB_NAME(VCCS) :: terminal_handler(); + NETLIB_NAME(VCCS)::terminal_handler(); } terminal_t m_OP2; terminal_t m_ON2; }; - } // namespace netlist::analog #endif // NLD_FOURTERM_H_ diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp index 4bb7ab64059..3d5d0721dfb 100644 --- a/src/lib/netlist/analog/nlid_twoterm.cpp +++ b/src/lib/netlist/analog/nlid_twoterm.cpp @@ -1,21 +1,20 @@ // license:BSD-3-Clause // copyright-holders:Couriersud -#include "solver/nld_solver.h" - -#include "nl_factory.h" #include "nlid_twoterm.h" -namespace netlist -{ -namespace analog +#include "nl_factory.h" + +#include "solver/nld_solver.h" + +namespace netlist::analog { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_twoterm - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - solver::matrix_solver_t * NETLIB_NAME(two_terminal)::solver() const noexcept + solver::matrix_solver_t *nld_two_terminal::solver() const noexcept { auto *solv(m_P.solver()); if (solv != nullptr) @@ -23,8 +22,7 @@ namespace analog return m_N.solver(); } - - void NETLIB_NAME(two_terminal)::solve_now() const + void nld_two_terminal::solve_now() const { auto *solv(solver()); if (solv != nullptr) @@ -33,92 +31,97 @@ namespace analog NETLIB_HANDLER(two_terminal, terminal_handler) { - // only called if connected to a rail net ==> notify the solver to recalculate - //printf("%s update\n", this->name().c_str()); + // only called if connected to a rail net ==> notify the solver to + // recalculate + // printf("%s update\n", this->name().c_str()); solve_now(); } - // ---------------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------- // nld_POT - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- NETLIB_RESET(POT) { nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one()); + v = (plib::exp(v) - nlconst::one()) + / (plib::exp(nlconst::one()) - nlconst::one()); - m_R1.set_R(std::max(m_R() * v, exec().gmin())); - m_R2.set_R(std::max(m_R() * (nlconst::one() - v), exec().gmin())); + m_R1().set_R(std::max(m_R() * v, exec().gmin())); + m_R2().set_R(std::max(m_R() * (nlconst::one() - v), exec().gmin())); } NETLIB_UPDATE_PARAM(POT) { nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one()); + v = (plib::exp(v) - nlconst::one()) + / (plib::exp(nlconst::one()) - nlconst::one()); if (m_Reverse()) v = nlconst::one() - v; nl_fptype r1(std::max(m_R() * v, exec().gmin())); nl_fptype r2(std::max(m_R() * (nlconst::one() - v), exec().gmin())); - if (m_R1.solver() == m_R2.solver()) - m_R1.change_state([this, &r1, &r2]() { m_R1.set_R(r1); m_R2.set_R(r2); }); + if (m_R1().solver() == m_R2().solver()) + m_R1().change_state( + [this, &r1, &r2]() + { + m_R1().set_R(r1); + m_R2().set_R(r2); + }); else { - m_R1.change_state([this, &r1]() { m_R1.set_R(r1); }); - m_R2.change_state([this, &r2]() { m_R2.set_R(r2); }); + m_R1().change_state([this, &r1]() { m_R1().set_R(r1); }); + m_R2().change_state([this, &r2]() { m_R2().set_R(r2); }); } - } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_POT2 - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- NETLIB_RESET(POT2) { nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one()); + v = (plib::exp(v) - nlconst::one()) + / (plib::exp(nlconst::one()) - nlconst::one()); if (m_Reverse()) v = nlconst::one() - v; - m_R1.set_R(std::max(m_R() * v, exec().gmin())); + m_R1().set_R(std::max(m_R() * v, exec().gmin())); } - NETLIB_UPDATE_PARAM(POT2) { nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one()); + v = (plib::exp(v) - nlconst::one()) + / (plib::exp(nlconst::one()) - nlconst::one()); if (m_Reverse()) v = nlconst::one() - v; - m_R1.change_state([this, &v]() - { - m_R1.set_R(std::max(m_R() * v, exec().gmin())); - }); + m_R1().change_state( + [this, &v]() { m_R1().set_R(std::max(m_R() * v, exec().gmin())); }); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_L - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- NETLIB_RESET(L) { m_gmin = exec().gmin(); m_I = nlconst::zero(); m_G = m_gmin; - set_mat( m_G, -m_G, -m_I, - -m_G, m_G, m_I); + set_mat(m_G, -m_G, -m_I, // + -m_G, m_G, m_I); } - NETLIB_UPDATE_PARAM(L) - { - } + NETLIB_UPDATE_PARAM(L) {} NETLIB_TIMESTEP(L) { @@ -129,8 +132,8 @@ namespace analog // Gpar should support convergence m_I += m_G * deltaV(); m_G = step / m_L() + m_gmin; - set_mat( m_G, -m_G, -m_I, - -m_G, m_G, m_I); + set_mat(m_G, -m_G, -m_I, // + -m_G, m_G, m_I); } else { @@ -139,9 +142,9 @@ namespace analog } } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_D - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- NETLIB_RESET(D) { @@ -165,29 +168,37 @@ namespace analog m_D.update_diode(deltaV()); const nl_fptype G(m_D.G()); const nl_fptype I(m_D.Ieq()); - set_mat( G, -G, -I, - -G, G, I); - //set(m_D.G(), 0.0, m_D.Ieq()); + set_mat(G, -G, -I, // + -G, G, I); + // set(m_D.G(), 0.0, m_D.Ieq()); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_Z - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- NETLIB_RESET(Z) { - nl_fptype IsBV = m_modacc.m_IBV / (plib::exp(m_modacc.m_BV / nlconst::np_VT(m_modacc.m_NBV)) - nlconst::one()); + nl_fptype IsBV = m_modacc.m_IBV + / (plib::exp(m_modacc.m_BV + / nlconst::np_VT(m_modacc.m_NBV)) + - nlconst::one()); - m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(), nlconst::T0()); + m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(), + nlconst::T0()); m_R.set_param(IsBV, m_modacc.m_NBV, exec().gmin(), nlconst::T0()); set_G_V_I(m_D.G(), nlconst::zero(), m_D.Ieq()); } NETLIB_UPDATE_PARAM(Z) { - nl_fptype IsBV = m_modacc.m_IBV / (plib::exp(m_modacc.m_BV / nlconst::np_VT(m_modacc.m_NBV)) - nlconst::one()); + nl_fptype IsBV = m_modacc.m_IBV + / (plib::exp(m_modacc.m_BV + / nlconst::np_VT(m_modacc.m_NBV)) + - nlconst::one()); - m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(), nlconst::T0()); + m_D.set_param(m_modacc.m_IS, m_modacc.m_N, exec().gmin(), + nlconst::T0()); m_R.set_param(IsBV, m_modacc.m_NBV, exec().gmin(), nlconst::T0()); set_G_V_I(m_D.G(), nlconst::zero(), m_D.Ieq()); } @@ -198,15 +209,15 @@ namespace analog m_R.update_diode(-deltaV()); const nl_fptype G(m_D.G() + m_R.G()); const nl_fptype I(m_D.Ieq() - m_R.Ieq()); - set_mat( G, -G, -I, - -G, G, I); + set_mat(G, -G, -I, // + -G, G, I); } +} // namespace netlist::analog - -} //namespace analog - -namespace devices { +namespace netlist::devices +{ + // clang-format off NETLIB_DEVICE_IMPL_NS(analog, R, "RES", "R") NETLIB_DEVICE_IMPL_NS(analog, POT, "POT", "R") NETLIB_DEVICE_IMPL_NS(analog, POT2, "POT2", "R") @@ -216,6 +227,5 @@ namespace devices { NETLIB_DEVICE_IMPL_NS(analog, Z, "ZDIODE", "MODEL") NETLIB_DEVICE_IMPL_NS(analog, VS, "VS", "V") NETLIB_DEVICE_IMPL_NS(analog, CS, "CS", "I") -} // namespace devices - -} // namespace netlist + // clang-format on +} // namespace netlist::devices diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index 52fc8aa08e8..c2d9eee3333 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -37,9 +37,11 @@ #include "../nl_setup.h" #include "nl_base.h" #include "nld_generic_models.h" -#include "plib/pfunction.h" + #include "solver/nld_solver.h" +#include "plib/pfunction.h" + // ----------------------------------------------------------------------------- // Implementation // ----------------------------------------------------------------------------- @@ -47,45 +49,37 @@ namespace netlist::analog { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_two_terminal - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - template - static inline core_device_t &bselect(bool b, C &d1, core_device_t &d2) + class nld_two_terminal : public base_device_t { - auto *h = dynamic_cast(&d1); - return b ? *h : d2; - } - template <> - inline core_device_t &bselect(bool b, [[maybe_unused]] netlist_state_t &d1, core_device_t &d2) - { - if (b) - throw nl_exception("bselect with netlist and b==true"); - return d2; - } - - NETLIB_BASE_OBJECT(two_terminal) - { - NETLIB_CONSTRUCTOR(two_terminal) + public: + nld_two_terminal(constructor_param_t data) + : base_device_t(data) , m_P(*this, "1", &m_N, NETLIB_DELEGATE(terminal_handler)) , m_N(*this, "2", &m_P, NETLIB_DELEGATE(terminal_handler)) { } - //#NETLIB_CONSTRUCTOR_EX(twoterm, nldelegate owner_delegate) - template - NETLIB_NAME(two_terminal)(C &owner, const pstring &name, nl_delegate owner_delegate) \ - : base_type(owner, name) + + // This constructor covers the case in which the terminals are "owned" + // by the device using a two_terminal. In this case it passes + // the terminal handler on to the terminals. + + nld_two_terminal(base_device_t &owner, const pstring &name, + nl_delegate owner_delegate) + : base_device_t( + constructor_data_t{owner.state(), owner.name() + "." + name}) , m_P(owner, name + ".1", &m_N, owner_delegate) , m_N(owner, name + ".2", &m_P, owner_delegate) { } - //NETLIB_UPDATE_TERMINALSI() { } - //NETLIB_RESETI() {} + // NETLIB_UPDATE_TERMINALSI() { } + // NETLIB_RESETI() {} public: - NETLIB_HANDLERI(terminal_handler); solver::matrix_solver_t *solver() const noexcept; @@ -112,18 +106,13 @@ namespace netlist::analog return m_P.net().Q_Analog() - m_N.net().Q_Analog(); } - nl_fptype V1P() const noexcept - { - return m_P.net().Q_Analog(); - } + nl_fptype V1P() const noexcept { return m_P.net().Q_Analog(); } - nl_fptype V2N() const noexcept - { - return m_N.net().Q_Analog(); - } + nl_fptype V2N() const noexcept { return m_N.net().Q_Analog(); } - void set_mat(nl_fptype a11, nl_fptype a12, nl_fptype rhs1, - nl_fptype a21, nl_fptype a22, nl_fptype rhs2) const noexcept + void set_mat(nl_fptype a11, nl_fptype a12, nl_fptype rhs1, // + nl_fptype a21, nl_fptype a22, nl_fptype rhs2 // + ) const noexcept { // GO, GT, I m_P.set_go_gt_I(a12, a11, rhs1); @@ -173,78 +162,75 @@ namespace netlist::analog private: terminal_t m_P; terminal_t m_N; - }; - - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_R - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(R_base, two_terminal) + class nld_R_base : public nld_two_terminal { - NETLIB_CONSTRUCTOR(R_base) + public: + nld_R_base(constructor_param_t data) + : nld_two_terminal(data) { } void set_R(nl_fptype R) const noexcept { const nl_fptype G = plib::reciprocal(R); - set_mat( G, -G, nlconst::zero(), - -G, G, nlconst::zero()); + set_mat(G, -G, nlconst::zero(), // + -G, G, nlconst::zero()); } void set_G(nl_fptype G) const noexcept { - set_mat( G, -G, nlconst::zero(), - -G, G, nlconst::zero()); + set_mat(G, -G, nlconst::zero(), // + -G, G, nlconst::zero()); } - //NETLIB_RESETI(); + // NETLIB_RESETI(); protected: - //NETLIB_UPDATEI(); - + // NETLIB_UPDATEI(); }; - NETLIB_OBJECT_DERIVED(R, R_base) + class nld_R : public nld_R_base { - NETLIB_CONSTRUCTOR(R) + public: + nld_R(constructor_param_t data) + : nld_R_base(data) , m_R(*this, "R", nlconst::magic(1e9)) { } - protected: - - NETLIB_RESETI() - { - set_R(std::max(m_R(), exec().gmin())); - } + NETLIB_RESETI() { set_R(std::max(m_R(), exec().gmin())); } NETLIB_UPDATE_PARAMI() { - // FIXME: We only need to update the net first if this is a time stepping net - change_state([this]() - { - set_R(std::max(m_R(), exec().gmin())); - }); + // FIXME: We only need to update the net first if this is a time + // stepping net + change_state([this]() { set_R(std::max(m_R(), exec().gmin())); }); } private: param_fp_t m_R; - // protect set_R ... it's a recipe to disaster when used to bypass the parameter - using NETLIB_NAME(R_base)::set_R; - using NETLIB_NAME(R_base)::set_G; + // protect set_R ... it's a recipe to disaster when used to bypass the + // parameter + using nld_R_base::set_G; + using nld_R_base::set_R; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_POT - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_BASE_OBJECT(POT) + class nld_POT : public base_device_t { - NETLIB_CONSTRUCTOR(POT) + public: + nld_POT(constructor_param_t data) + : base_device_t(data) , m_R1(*this, "_R1") , m_R2(*this, "_R2") , m_R(*this, "R", 10000) @@ -252,63 +238,65 @@ namespace netlist::analog , m_DialIsLog(*this, "DIALLOG", false) , m_Reverse(*this, "REVERSE", false) { - register_sub_alias("1", m_R1.P()); - register_sub_alias("2", m_R1.N()); - register_sub_alias("3", m_R2.N()); - - connect(m_R2.P(), m_R1.N()); + register_sub_alias("1", m_R1().P()); + register_sub_alias("2", m_R1().N()); + register_sub_alias("3", m_R2().N()); + connect(m_R2().P(), m_R1().N()); } - //NETLIB_UPDATEI(); + // NETLIB_UPDATEI(); NETLIB_RESETI(); NETLIB_UPDATE_PARAMI(); private: - NETLIB_SUB(R_base) m_R1; - NETLIB_SUB(R_base) m_R2; + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; - param_fp_t m_R; - param_fp_t m_Dial; + param_fp_t m_R; + param_fp_t m_Dial; param_logic_t m_DialIsLog; param_logic_t m_Reverse; }; - NETLIB_BASE_OBJECT(POT2) + class nld_POT2 : public base_device_t { - NETLIB_CONSTRUCTOR(POT2) + public: + nld_POT2(constructor_param_t data) + : base_device_t(data) , m_R1(*this, "_R1") , m_R(*this, "R", nlconst::magic(10000.0)) , m_Dial(*this, "DIAL", nlconst::half()) , m_DialIsLog(*this, "DIALLOG", false) , m_Reverse(*this, "REVERSE", false) { - register_sub_alias("1", m_R1.P()); - register_sub_alias("2", m_R1.N()); - + register_sub_alias("1", m_R1().P()); + register_sub_alias("2", m_R1().N()); } - //NETLIB_UPDATEI(); + // NETLIB_UPDATEI(); NETLIB_RESETI(); NETLIB_UPDATE_PARAMI(); private: - NETLIB_SUB(R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R1; - param_fp_t m_R; - param_fp_t m_Dial; + param_fp_t m_R; + param_fp_t m_Dial; param_logic_t m_DialIsLog; param_logic_t m_Reverse; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_C - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + #if 1 - NETLIB_OBJECT_DERIVED(C, two_terminal) + class nld_C : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR(C) + nld_C(constructor_param_t data) + : nld_two_terminal(data) , m_C(*this, "C", nlconst::magic(1e-6)) , m_cap(*this, "m_cap") { @@ -320,20 +308,17 @@ namespace netlist::analog if (ts_type == time_step_type::FORWARD) { // G, Ieq - const auto res(m_cap.time_step(m_C(), deltaV(), step)); + const auto res(m_cap.time_step(m_C(), deltaV(), step)); const nl_fptype G = res.first; const nl_fptype I = res.second; - set_mat( G, -G, -I, - -G, G, I); + set_mat(G, -G, -I, // + -G, G, I); } else m_cap.restore_state(); } - NETLIB_RESETI() - { - m_cap.set_parameters(exec().gmin()); - } + NETLIB_RESETI() { m_cap.set_parameters(exec().gmin()); } /// \brief Set capacitance /// @@ -343,27 +328,25 @@ namespace netlist::analog /// /// \param val Capacitance value /// - void set_cap_embedded(nl_fptype val) - { - m_C.set(val); - } + void set_cap_embedded(nl_fptype val) { m_C.set(val); } protected: - //NETLIB_UPDATEI(); - //FIXME: should be able to change - NETLIB_UPDATE_PARAMI() { } + // NETLIB_UPDATEI(); + // FIXME: should be able to change + NETLIB_UPDATE_PARAMI() {} private: - param_fp_t m_C; + param_fp_t m_C; generic_capacitor_const m_cap; }; #else // Code preserved as a basis for a current/voltage controlled capacitor - NETLIB_OBJECT_DERIVED(C, two_terminal) + class nld_C : public nld_two_terminal) { public: - NETLIB_CONSTRUCTOR_DERIVED(C, two_terminal) + nld_C(constructor_param_t data) + : nld_two_terminal(data) , m_C(*this, "C", nlconst::magic(1e-6)) , m_cap(*this, "m_cap") { @@ -377,8 +360,8 @@ namespace netlist::analog { const nl_fptype I = m_cap.Ieq(m_C(), deltaV()); const nl_fptype G = m_cap.G(m_C()); - set_mat( G, -G, -I, - -G, G, I); + set_mat(G, -G, -I, // + -G, G, I); } } @@ -387,34 +370,33 @@ namespace netlist::analog { const nl_fptype I = m_cap.Ieq(m_C(), deltaV()); const nl_fptype G = m_cap.G(m_C()); - set_mat( G, -G, -I, - -G, G, I); + set_mat(G, -G, -I, // + -G, G, I); } param_fp_t m_C; - NETLIB_RESETI() - { - m_cap.set_parameters(exec().gmin()); - } + NETLIB_RESETI() { m_cap.set_parameters(exec().gmin()); } protected: - //NETLIB_UPDATEI(); - //FIXME: should be able to change - NETLIB_UPDATE_PARAMI() { } + // NETLIB_UPDATEI(); + // FIXME: should be able to change + NETLIB_UPDATE_PARAMI() {} private: - //generic_capacitor m_cap; + // generic_capacitor m_cap; generic_capacitor m_cap; }; #endif - // ----------------------------------------------------------------------------- - // nld_L - // ----------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(L, two_terminal) + // ------------------------------------------------------------------------- + // nld_L + // ------------------------------------------------------------------------- + + class nld_L : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR(L) + nld_L(constructor_param_t data) + : nld_two_terminal(data) , m_L(*this, "L", nlconst::magic(1e-6)) , m_gmin(nlconst::zero()) , m_G(*this, "m_G", nlconst::zero()) @@ -422,8 +404,8 @@ namespace netlist::analog , m_last_I(*this, "m_last_I", nlconst::zero()) , m_last_G(*this, "m_last_G", nlconst::zero()) { - //register_term("1", m_P); - //register_term("2", m_N); + // register_term("1", m_P); + // register_term("2", m_N); } NETLIB_IS_TIMESTEP(true) @@ -431,13 +413,13 @@ namespace netlist::analog NETLIB_RESETI(); protected: - //NETLIB_UPDATEI(); + // NETLIB_UPDATEI(); NETLIB_UPDATE_PARAMI(); private: param_fp_t m_L; - nl_fptype m_gmin; + nl_fptype m_gmin; state_var m_G; state_var m_I; state_var m_last_I; @@ -446,9 +428,9 @@ namespace netlist::analog /// \brief Class representing the diode model parameters. /// - /// This is the model representation of the diode model. Typically, SPICE uses - /// the following parameters. A "Y" in the first column indicates that the - /// parameter is actually used in netlist. + /// This is the model representation of the diode model. Typically, SPICE + /// uses the following parameters. A "Y" in the first column indicates that + /// the parameter is actually used in netlist. /// /// NBV, BV and IBV are only used in the ZDIODE model. It is assumed /// that DIODEs are not modeled up to their breakdown voltage. @@ -478,10 +460,11 @@ namespace netlist::analog diode_model_t(param_model_t &model) : m_IS(model, "IS") , m_N(model, "N") - {} + { + } - param_model_t::value_t m_IS; //!< saturation current. - param_model_t::value_t m_N; //!< emission coefficient. + param_model_t::value_t m_IS; //!< saturation current. + param_model_t::value_t m_N; //!< emission coefficient. }; class zdiode_model_t : public diode_model_t @@ -492,21 +475,23 @@ namespace netlist::analog , m_NBV(model, "NBV") , m_BV(model, "BV") , m_IBV(model, "IBV") - {} + { + } - param_model_t::value_t m_NBV; //!< reverse emission coefficient. - param_model_t::value_t m_BV; //!< reverse breakdown voltage. - param_model_t::value_t m_IBV; //!< current at breakdown voltage. + param_model_t::value_t m_NBV; //!< reverse emission coefficient. + param_model_t::value_t m_BV; //!< reverse breakdown voltage. + param_model_t::value_t m_IBV; //!< current at breakdown voltage. }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_D - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(D, two_terminal) + class nld_D : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR_EX(D, const pstring &model = "D") + nld_D(constructor_param_t data, const pstring &model = "D") + : nld_two_terminal(data) , m_model(*this, "MODEL", model) , m_modacc(m_model) , m_D(*this, "m_D") @@ -520,23 +505,24 @@ namespace netlist::analog NETLIB_RESETI(); protected: - //NETLIB_UPDATEI(); + // NETLIB_UPDATEI(); NETLIB_UPDATE_PARAMI(); private: - param_model_t m_model; - diode_model_t m_modacc; + param_model_t m_model; + diode_model_t m_modacc; generic_diode m_D; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_Z - Zener Diode - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(Z, two_terminal) + class nld_Z : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR_EX(Z, const pstring &model = "D") + nld_Z(constructor_param_t data, const pstring &model = "D") + : nld_two_terminal(data) , m_model(*this, "MODEL", model) , m_modacc(m_model) , m_D(*this, "m_D") @@ -551,38 +537,40 @@ namespace netlist::analog NETLIB_RESETI(); protected: - //NETLIB_UPDATEI(); + // NETLIB_UPDATEI(); NETLIB_UPDATE_PARAMI(); private: - param_model_t m_model; - zdiode_model_t m_modacc; + param_model_t m_model; + zdiode_model_t m_modacc; generic_diode m_D; // REVERSE diode generic_diode m_R; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_VS - Voltage source // // netlist voltage source must have inner resistance - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(VS, two_terminal) + class nld_VS : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR(VS) + nld_VS(constructor_param_t data) + : nld_two_terminal(data) , m_t(*this, "m_t", nlconst::zero()) , m_R(*this, "RI", nlconst::magic(0.1)) , m_V(*this, "V", nlconst::zero()) - , m_func(*this,"FUNC", "") + , m_func(*this, "FUNC", "") , m_compiled(*this, "m_compiled") , m_funcparam({nlconst::zero()}) { register_sub_alias("P", P()); register_sub_alias("N", N()); if (!m_func().empty()) - m_compiled->compile(m_func(), std::vector({{pstring("T")}})); + m_compiled->compile(m_func(), + std::vector({{pstring("T")}})); } NETLIB_IS_TIMESTEP(!m_func().empty()) @@ -594,48 +582,49 @@ namespace netlist::analog m_t += step; m_funcparam[0] = m_t; this->set_G_V_I(plib::reciprocal(m_R()), - m_compiled->evaluate(m_funcparam), - nlconst::zero()); + m_compiled->evaluate(m_funcparam), + nlconst::zero()); } else m_t -= step; // only need to restore state, will be called again } protected: - NETLIB_RESETI() { - NETLIB_NAME(two_terminal)::reset(); + nld_two_terminal::reset(); this->set_G_V_I(plib::reciprocal(m_R()), m_V(), nlconst::zero()); } private: - state_var m_t; - param_fp_t m_R; - param_fp_t m_V; - param_str_t m_func; + state_var m_t; + param_fp_t m_R; + param_fp_t m_V; + param_str_t m_func; state_var> m_compiled; - std::vector m_funcparam; + std::vector m_funcparam; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nld_CS - Current source - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(CS, two_terminal) + class nld_CS : public nld_two_terminal { public: - NETLIB_CONSTRUCTOR(CS) + nld_CS(constructor_param_t data) + : nld_two_terminal(data) , m_t(*this, "m_t", nlconst::zero()) , m_I(*this, "I", nlconst::one()) - , m_func(*this,"FUNC", "") + , m_func(*this, "FUNC", "") , m_compiled(*this, "m_compiled") , m_funcparam({nlconst::zero()}) { register_sub_alias("P", "1"); register_sub_alias("N", "2"); if (!m_func().empty()) - m_compiled->compile(m_func(), std::vector({{pstring("T")}})); + m_compiled->compile(m_func(), + std::vector({{pstring("T")}})); } NETLIB_IS_TIMESTEP(!m_func().empty()) @@ -646,42 +635,43 @@ namespace netlist::analog m_t += step; m_funcparam[0] = m_t; const nl_fptype I = m_compiled->evaluate(m_funcparam); - const auto zero(nlconst::zero()); - set_mat(zero, zero, -I, - zero, zero, I); + const auto zero(nlconst::zero()); + set_mat(zero, zero, -I, // + zero, zero, I); } else m_t -= step; } protected: - NETLIB_RESETI() { - NETLIB_NAME(two_terminal)::reset(); + nld_two_terminal::reset(); const auto zero(nlconst::zero()); - set_mat(zero, zero, -m_I(), - zero, zero, m_I()); + set_mat(zero, zero, -m_I(), // + zero, zero, m_I()); } NETLIB_UPDATE_PARAMI() { - // FIXME: We only need to update the net first if this is a time stepping net - //FIXME: works only for CS without function - change_state([this]() - { - const auto zero(nlconst::zero()); - set_mat(zero, zero, -m_I(), - zero, zero, m_I()); - }); + // FIXME: We only need to update the net first if this is a time + // stepping net + // FIXME: works only for CS without function + change_state( + [this]() + { + const auto zero(nlconst::zero()); + set_mat(zero, zero, -m_I(), // + zero, zero, m_I()); + }); } private: - state_var m_t; - param_fp_t m_I; - param_str_t m_func; + state_var m_t; + param_fp_t m_I; + param_str_t m_func; state_var> m_compiled; - std::vector m_funcparam; + std::vector m_funcparam; }; } // namespace netlist::analog diff --git a/src/lib/netlist/build/.clang-format b/src/lib/netlist/build/.clang-format new file mode 100644 index 00000000000..46d1fb6dcec --- /dev/null +++ b/src/lib/netlist/build/.clang-format @@ -0,0 +1,102 @@ +Language: Cpp +Standard: c++17 +UseTab: ForContinuationAndIndentation +TabWidth: 4 +IndentWidth: 4 +ColumnLimit: 80 +ContinuationIndentWidth: 4 +ConstructorInitializerIndentWidth: 0 +NamespaceIndentation: All +CompactNamespaces: true +FixNamespaceComments: true + +IndentAccessModifiers: false +AccessModifierOffset: -4 +IndentCaseLabels: true + +BreakBeforeBraces: Allman +BreakBeforeBinaryOperators: All +BreakConstructorInitializers: BeforeComma +# Currentline doesn't work +# PackConstructorInitializers: CurrentLine >= 14 +BreakStringLiterals: false +# Multiline does not work in clang-format 13 +# AlwaysBreakTemplateDeclarations: MultiLine +AlwaysBreakTemplateDeclarations: Yes +# AfterComma does not work <= 13 +#BreakInheritanceList: AfterComma +#BreakInheritanceList: BeforeComma +#BreakInheritanceList: false +SpaceBeforeInheritanceColon: true + +#AlignAfterOpenBracket: DontAlign +AlignAfterOpenBracket: Align +PointerAlignment: Right +SpacesInAngles: false +SpaceBeforeAssignmentOperators: true +AlignConsecutiveDeclarations: true + +AllowShortIfStatementsOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false + +PenaltyBreakComment: 1 +PenaltyBreakAssignment: 1000 +AlwaysBreakBeforeMultilineStrings: true + +PenaltyReturnTypeOnItsOwnLine: 1 + +# SortIncludes: CaseSensitive # >= 13! +SortIncludes: true +IncludeBlocks: Regroup + +IncludeCategories: + - Regex: '^(("|"../)core)/' + Priority: 20 + - Regex: '^(("|"../)analog)/' + Priority: 21 + - Regex: '^(("|"../)devices)/' + Priority: 22 + - Regex: '^(("|"../)solver)/' + Priority: 23 + - Regex: '^(("|"../)plib)/' + Priority: 30 + - Regex: '<[([:alnum:]|_).]+>' + Priority: 40 + - Regex: '.*' + Priority: 10 + +StatementMacros: + - "NETLIB_DEVICE_IMPL_NS" + - "TTL_7400_NAND" + - "TTL_7402_NOR" + - "NET_C" + - "TRUTHTABLE_ENTRY" + - "LOCAL_LIB_ENTRY" + - "TT_HEAD" + - "TT_LINE" + - "TT_FAMILY" + - "DIPPINS" + +#StatementAttributeLikeMacros: +# - "NETLIST_NAME" +# - "NETLIB_NAME" + +TypenameMacros: + - "NETLIST_NAME" + - "NETLIB_NAME" + +IndentPPDirectives: BeforeHash +MacroBlockBegin: "^static NETLIST_START\\(.*\\)|static TRUTHTABLE_START\\(.*\\)$" +MacroBlockEnd: "^NETLIST_END\\(\\)|TRUTHTABLE_END\\(\\)$" +# ReferenceAlignment: Middle +# Avoid formatting (breaking) doxygen +CommentPragmas: '^\\.+' +# Avoid formatting cspell ignored comments +CommentPragmas: '^#.+' +# Avoid breaking tables +CommentPragmas: '^\|.+' +# Avoid breaking clang-tidy +CommentPragmas: '^ NOLINT.+' + diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 91ae7140acf..ab89d6adcdd 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -55,6 +55,7 @@ TIDY_FLAGSX += -modernize-use-auto, #TIDY_FLAGSX += -modernize-use-transparent-functors, TIDY_FLAGSX += -readability-function-cognitive-complexity, TIDY_FLAGSX += -readability-uppercase-literal-suffix +TIDY_FLAGSX += -cert-err58-cpp #TIDY_FLAGSX += -cppcoreguidelines-avoid-non-const-global-variables @@ -113,7 +114,7 @@ TIDY_DB = $(OBJ)/compile_commands.json #LTO decreases performance :-( #LTO = -flto=4 -fuse-linker-plugin -Wodr -CCOREFLAGS = -g -O3 -std=c++17 -I$(SRC) -I$(SRC)/.. +CCOREFLAGS = -g -O3 -std=c++17 -I$(SRC) -I$(SRC)/.. -I$(SRC)/../.. CFLAGS = $(LTO) $(CCOREFLAGS) $(CEXTRAFLAGS) LDFLAGS = $(LTO) -g -O3 -std=c++17 $(LDEXTRAFLAGS) @@ -289,22 +290,20 @@ native: $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra" gcc9: - $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -Wall -pedantic -Wpedantic -fext-numeric-literals -Wsign-compare -Wextra" EXTRALIBS="-lquadmath" OBJ=obj/gcc9 + $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -Wall -Wextra -pedantic -Wpedantic -pedantic-errors -fext-numeric-literals -Wsign-compare" EXTRALIBS="-lquadmath" OBJ=obj/gcc9 clang: #$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" $(MAKE) CC=clang++-13 LD=clang++-13 OBJ=obj/clang CEXTRAFLAGS="-march=native \ - -mllvm -inline-threshold=2000 \ + -mllvm -inline-threshold=2000 \ -Wunknown-warning-option \ - -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \ + -Weverything -Wall -pedantic -Wpedantic \ -Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wunused-template \ - -Wmissing-variable-declarations -Wno-float-equal -Wconversion \ - -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wformat-nonliteral \ - -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \ - -Wno-embedded-directive \ + -Wno-float-equal \ + -Wno-c++98-compat -Wno-c++98-compat-pedantic \ + -Wno-exit-time-destructors \ -Wno-undefined-reinterpret-cast -Wno-error=unused-macros \ - -Wunreachable-code \ - -Wmissing-prototypes -Wno-error=deprecated" + -Wno-error=deprecated" clang-libc: #clang-11 currently broken diff --git a/src/lib/netlist/core/analog.h b/src/lib/netlist/core/analog.h index a003e1c37a5..da9639a3de1 100644 --- a/src/lib/netlist/core/analog.h +++ b/src/lib/netlist/core/analog.h @@ -20,23 +20,22 @@ namespace netlist { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- class analog_t : public detail::core_terminal_t { public: - analog_t(core_device_t &dev, const pstring &aname, state_e state, nl_delegate delegate); - const analog_net_t & net() const noexcept + const analog_net_t &net() const noexcept { return plib::downcast(core_terminal_t::net()); } - analog_net_t & net() noexcept + analog_net_t &net() noexcept { return plib::downcast(core_terminal_t::net()); } @@ -53,24 +52,23 @@ namespace netlist class terminal_t : public analog_t { public: - /// \brief constructor /// /// \param dev object owning the terminal /// \param aname name of this terminal /// \param other_terminal pointer to the sibling terminal - terminal_t(core_device_t &dev, const pstring &aname, terminal_t *other_terminal, nl_delegate delegate); + terminal_t(core_device_t &dev, const pstring &aname, + terminal_t *other_terminal, nl_delegate delegate); - terminal_t(core_device_t &dev, const pstring &aname, terminal_t *other_terminal, - const std::array &splitter_terms, nl_delegate delegate); + terminal_t(core_device_t &dev, const pstring &aname, + terminal_t * other_terminal, + const std::array &splitter_terms, + nl_delegate delegate); /// \brief Returns voltage of connected net /// /// \return voltage of net this terminal is connected to - nl_fptype operator ()() const noexcept - { - return net().Q_Analog(); - } + nl_fptype operator()() const noexcept { return net().Q_Analog(); } /// \brief sets conductivity value of this terminal /// @@ -85,42 +83,33 @@ namespace netlist set_go_gt_I(GO, GT, nlconst::zero()); } - void set_go_gt_I(nl_fptype GO, nl_fptype GT, nl_fptype I) const noexcept - { - // Check for rail nets ... - if (m_go != nullptr) - { - *m_Idr = I; - *m_go = GO; - *m_gt = GT; - } - } + void set_go_gt_I(nl_fptype GO, nl_fptype GT, + nl_fptype I) const noexcept; - void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false); + void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept( + false); private: nl_fptype *m_Idr; ///< drive current nl_fptype *m_go; ///< conductance for Voltage from other term nl_fptype *m_gt; ///< conductance for total conductance - }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_input_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /// \brief terminal providing analog input voltage. /// - /// This terminal class provides a voltage measurement. The conductance against - /// ground is infinite. - + /// This terminal class provides a voltage measurement. The conductance + /// against ground is infinite. class analog_input_t : public analog_t { public: /// \brief Constructor - analog_input_t(core_device_t &dev, ///< owning device - const pstring &aname, ///< name of terminal - nl_delegate delegate ///< delegate + analog_input_t(core_device_t &dev, ///< owning device + const pstring & aname, ///< name of terminal + nl_delegate delegate ///< delegate ); /// \brief returns voltage at terminal. @@ -129,29 +118,19 @@ namespace netlist /// \brief returns voltage at terminal. /// \returns voltage at terminal. - nl_fptype Q_Analog() const noexcept - { - return net().Q_Analog(); - } + nl_fptype Q_Analog() const noexcept { return net().Q_Analog(); } }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_output_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- class analog_output_t : public analog_t { public: analog_output_t(core_device_t &dev, const pstring &aname); - void push(nl_fptype val) noexcept - { - if (val != m_my_net.Q_Analog()) - { - m_my_net.set_Q_Analog(val); - m_my_net.toggle_and_push_to_queue(netlist_time::quantum()); - } - } + void push(nl_fptype val) noexcept; void initial(nl_fptype val) noexcept; @@ -159,12 +138,36 @@ namespace netlist analog_net_t m_my_net; }; + // ------------------------------------------------------------------------- + // out of class + // ------------------------------------------------------------------------- + inline solver::matrix_solver_t *analog_t::solver() const noexcept { return (this->has_net() ? net().solver() : nullptr); } + inline void terminal_t::set_go_gt_I(nl_fptype GO, nl_fptype GT, + nl_fptype I) const noexcept + { + // Check for rail nets ... + if (m_go != nullptr) + { + *m_Idr = I; + *m_go = GO; + *m_gt = GT; + } + } + + inline void analog_output_t::push(nl_fptype val) noexcept + { + if (val != m_my_net.Q_Analog()) + { + m_my_net.set_Q_Analog(val); + m_my_net.toggle_and_push_to_queue(netlist_time::quantum()); + } + } + } // namespace netlist - #endif // NL_CORE_ANALOG_H_ diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h index 782d94cf572..1f924d988dc 100644 --- a/src/lib/netlist/core/base_objects.h +++ b/src/lib/netlist/core/base_objects.h @@ -8,11 +8,10 @@ #ifndef NL_CORE_BASE_OBJECTS_H_ #define NL_CORE_BASE_OBJECTS_H_ +#include "../nltypes.h" #include "netlist_state.h" #include "state_var.h" -#include "../nltypes.h" - #include "../plib/palloc.h" #include "../plib/pchrono.h" #include "../plib/pexception.h" @@ -21,7 +20,8 @@ #include -namespace netlist::detail { +namespace netlist::detail +{ template struct property_store_t @@ -30,30 +30,44 @@ namespace netlist::detail { using key_type = const C *; using store_type = std::unordered_map; - static void add(key_type obj, const value_type &aname) noexcept + static void add(key_type obj, const value_type &value) noexcept { - store().insert({obj, aname}); + try + { + store().insert({obj, value}); + } + catch (...) + { + plib::terminate("exception in property_store_t.add()"); + } } - static value_type *get(key_type obj) noexcept + static const value_type &get(key_type obj) noexcept { try { typename store_type::iterator ret(store().find(obj)); if (ret == store().end()) - return nullptr; - return &ret->second; + plib::terminate( + "object not found in property_store_t.get()"); + return ret->second; } catch (...) { plib::terminate("exception in property_store_t.get()"); - return static_cast(nullptr); } } static void remove(key_type obj) noexcept { - store().erase(store().find(obj)); + try + { + store().erase(store().find(obj)); + } + catch (...) + { + plib::terminate("exception in property_store_t.remove()"); + } } static store_type &store() noexcept @@ -61,12 +75,11 @@ namespace netlist::detail { static store_type static_store; return static_store; } - }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // object_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /// \brief The base class for netlist devices, terminals and parameters. /// @@ -76,36 +89,25 @@ namespace netlist::detail { class object_t { public: - /// \brief Constructor. /// Every class derived from the object_t class must have a name. /// /// \param aname string containing name of the object - explicit object_t(const pstring &aname) - { - props::add(this, aname); - } + explicit object_t(const pstring &aname) { props::add(this, aname); } PCOPYASSIGNMOVE(object_t, delete) /// \brief return name of the object /// /// \returns name of the object. - const pstring &name() const noexcept - { - return *props::get(this); - } + const pstring &name() const noexcept { return props::get(this); } protected: - using props = property_store_t; // only childs should be destructible - ~object_t() noexcept - { - props::remove(this); - } + ~object_t() noexcept { props::remove(this); } private: }; @@ -122,33 +124,34 @@ namespace netlist::detail { explicit netlist_object_t(netlist_t &nl, const pstring &name) : object_t(name) , m_netlist(nl) - { } + { + } ~netlist_object_t() = default; PCOPYASSIGNMOVE(netlist_object_t, delete) - netlist_state_t & state() noexcept; - const netlist_state_t & state() const noexcept; + netlist_state_t & state() noexcept; + const netlist_state_t &state() const noexcept; - constexpr netlist_t & exec() noexcept { return m_netlist; } - constexpr const netlist_t & exec() const noexcept { return m_netlist; } + constexpr netlist_t & exec() noexcept { return m_netlist; } + constexpr const netlist_t &exec() const noexcept { return m_netlist; } // to ease template design template - device_arena::unique_ptr make_pool_object(Args&&... args) + device_arena::unique_ptr make_pool_object(Args &&...args) noexcept( + false) { return state().make_pool_object(std::forward(args)...); } private: - netlist_t & m_netlist; - + netlist_t &m_netlist; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // device_object_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /// \brief Base class for all objects being owned by a device. /// @@ -171,31 +174,32 @@ namespace netlist::detail { /// \brief returns reference to owning device. /// \returns reference to owning device. - core_device_t &device() noexcept { return *m_device; } + core_device_t & device() noexcept { return *m_device; } const core_device_t &device() const noexcept { return *m_device; } /// \brief The netlist owning the owner of this object. /// \returns reference to netlist object. - netlist_state_t &state() noexcept; + netlist_state_t & state() noexcept; const netlist_state_t &state() const noexcept; private: - core_device_t * m_device; + core_device_t *m_device; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // core_terminal_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /// \brief Base class for all terminals. /// /// All terminals are derived from this class. /// - class core_terminal_t : public device_object_t - , public plib::linked_list_t::element_t + class core_terminal_t + : public device_object_t + , public plib::linked_list_t::element_t #if NL_USE_INPLACE_CORE_TERMS - , public plib::linked_list_t::element_t + , public plib::linked_list_t::element_t #endif { public: @@ -213,19 +217,21 @@ namespace netlist::detail { static constexpr netlist_sig_t OUT_TRISTATE() { return INP_MASK; } - static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8, "netlist_sig_t size not sufficient"); + static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8, + "netlist_sig_t size not sufficient"); - enum state_e { + enum state_e + { STATE_INP_PASSIVE = 0, - STATE_INP_HL = (INP_MASK << INP_HL_SHIFT), - STATE_INP_LH = (INP_MASK << INP_LH_SHIFT), - STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH, - STATE_OUT = (1 << (2*INP_BITS)), - STATE_BIDIR = (1 << (2*INP_BITS + 1)) + STATE_INP_HL = (INP_MASK << INP_HL_SHIFT), + STATE_INP_LH = (INP_MASK << INP_LH_SHIFT), + STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH, + STATE_OUT = (1 << (2 * INP_BITS)), + STATE_BIDIR = (1 << (2 * INP_BITS + 1)) }; - core_terminal_t(core_device_t &dev, const pstring &aname, - state_e state, nl_delegate delegate); + core_terminal_t(core_device_t &dev, const pstring &aname, state_e state, + nl_delegate delegate); virtual ~core_terminal_t() noexcept = default; PCOPYASSIGNMOVE(core_terminal_t, delete) @@ -237,13 +243,16 @@ namespace netlist::detail { /// \brief Checks if object is of specified type. /// \param atype type to check object against. /// \returns true if object is of specified type else false. - bool is_type(const terminal_type atype) const noexcept(false) { return (type() == atype); } + bool is_type(const terminal_type atype) const noexcept(false) + { + return (type() == atype); + } - void set_net(net_t *anet) noexcept { m_net = anet; } - void clear_net() noexcept { m_net = nullptr; } + void set_net(net_t *anet) noexcept { m_net = anet; } + void clear_net() noexcept { m_net = nullptr; } constexpr bool has_net() const noexcept { return (m_net != nullptr); } - constexpr net_t & net() const noexcept { return *m_net;} + constexpr net_t &net() const noexcept { return *m_net; } bool is_logic() const noexcept; bool is_logic_input() const noexcept; @@ -253,13 +262,21 @@ namespace netlist::detail { bool is_analog_input() const noexcept; bool is_analog_output() const noexcept; - constexpr bool is_state(state_e state) const noexcept { return (m_state == state); } + constexpr bool is_state(state_e state) const noexcept + { + return (m_state == state); + } constexpr state_e terminal_state() const noexcept { return m_state; } - constexpr void set_state(state_e state) noexcept { m_state = state; } + constexpr void set_state(state_e state) noexcept { m_state = state; } - void reset() noexcept { set_state(is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); } + void reset() noexcept + { + set_state( + is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); + } - constexpr void set_copied_input([[maybe_unused]] netlist_sig_t val) noexcept + constexpr void set_copied_input( + [[maybe_unused]] netlist_sig_t val) noexcept { if constexpr (config::use_copy_instead_of_reference::value) { @@ -267,20 +284,24 @@ namespace netlist::detail { } } - void set_delegate(const nl_delegate &delegate) noexcept { m_delegate = delegate; } + void set_delegate(const nl_delegate &delegate) noexcept + { + m_delegate = delegate; + } const nl_delegate &delegate() const noexcept { return m_delegate; } void run_delegate() const noexcept { return m_delegate(); } + protected: - //std::conditional_t m_Q; + // std::conditional_t m_Q; state_var_sig m_Q_CIR; + private: - nl_delegate m_delegate; - net_t * m_net; + nl_delegate m_delegate; + net_t * m_net; state_var m_state; }; - } // namespace netlist::detail - #endif // NL_CORE_BASE_OBJECTS_H_ diff --git a/src/lib/netlist/core/core_device.h b/src/lib/netlist/core/core_device.h index b81835b716e..87391450787 100644 --- a/src/lib/netlist/core/core_device.h +++ b/src/lib/netlist/core/core_device.h @@ -9,21 +9,60 @@ #define NL_CORE_DEVICE_H_ #include "../nltypes.h" -#include "../plib/pstring.h" #include "base_objects.h" -#include "logic_family.h" + +#include "../plib/pstring.h" namespace netlist { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + // core_device_t construction parameters + // ------------------------------------------------------------------------- + + struct core_device_data_t + { + friend class core_device_t; + friend class base_device_t; + friend class analog::NETLIB_NAME(two_terminal); + friend class logic_family_std_proxy_t; + + template + friend class devices::factory_truth_table_t; + + template + friend class factory::device_element_t; + friend class factory::library_element_t; + + template + friend struct sub_device_wrapper; + + friend class solver::matrix_solver_t; + + private: + core_device_data_t(netlist_state_t &o, const pstring &n) + : owner(o) + , name(n) + { + } + netlist_state_t &owner; + const pstring & name; + }; + + // The type use to pass data on + using core_device_param_t = const core_device_data_t &; + + // ------------------------------------------------------------------------- // core_device_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // FIXME: belongs into detail namespace + class core_device_t : public detail::netlist_object_t { public: - core_device_t(netlist_state_t &owner, const pstring &name); - core_device_t(core_device_t &owner, const pstring &name); + using constructor_data_t = core_device_data_t; + using constructor_param_t = core_device_param_t; + + core_device_t(core_device_param_t data); core_device_t(const core_device_t &) = delete; core_device_t &operator=(const core_device_t &) = delete; @@ -50,25 +89,25 @@ namespace netlist plib::pperfcount_t m_stat_inc_active; }; - stats_t * stats() const noexcept { return m_stats.get(); } + stats_t *stats() const noexcept { return m_stats.get(); } - virtual void reset() { } + virtual void reset() {} - void handler_noop() - { - } + void handler_noop() {} protected: - using activate_delegate = plib::pmfp; + using activate_delegate = plib::pmfp; activate_delegate m_activate; - log_type & log(); + log_type &log(); public: virtual void time_step([[maybe_unused]] time_step_type ts_type, - [[maybe_unused]] nl_fptype st) noexcept { } - virtual void update_terminals() noexcept { } + [[maybe_unused]] nl_fptype st) noexcept + { + } + virtual void update_terminals() noexcept {} virtual void update_param() noexcept {} virtual bool is_dynamic() const noexcept { return false; } @@ -76,8 +115,8 @@ namespace netlist private: // FIXME: should this be a state_var? - bool m_hint_deactivate; - state_var_s32 m_active_outputs; + bool m_hint_deactivate; + state_var_s32 m_active_outputs; device_arena::unique_ptr m_stats; }; @@ -91,7 +130,7 @@ namespace netlist { if (m_stats) m_stats->m_stat_inc_active.inc(); - m_activate(true);//inc_active(); + m_activate(true); // inc_active(); } } } @@ -103,44 +142,62 @@ namespace netlist if (!m_activate.isnull() && m_hint_deactivate) if (--m_active_outputs == 0) { - m_activate(false); //dec_active(); + m_activate(false); // dec_active(); } } + // ------------------------------------------------------------------------- + // core_device_t construction parameters + // ------------------------------------------------------------------------- - // ----------------------------------------------------------------------------- + using base_device_data_t = core_device_data_t; + // The type use to pass data on + using base_device_param_t = const base_device_data_t &; + + // ------------------------------------------------------------------------- // base_device_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class base_device_t : public core_device_t + class base_device_t : public core_device_t { public: - base_device_t(netlist_state_t &owner, const pstring &name); - base_device_t(base_device_t &owner, const pstring &name); + using constructor_data_t = base_device_data_t; + using constructor_param_t = base_device_param_t; + + base_device_t(base_device_param_t data); PCOPYASSIGNMOVE(base_device_t, delete) ~base_device_t() noexcept override = default; template - void create_and_register_sub_device(O& owner, const pstring &name, device_arena::unique_ptr &dev, Args&&... args) + void create_and_register_sub_device(O &owner, const pstring &name, + device_arena::unique_ptr &dev, Args &&...args) { - dev = state().make_pool_object(owner, name, std::forward(args)...); + // dev = state().make_pool_object(owner, name, + // std::forward(args)...); + using dev_constructor_data_t = typename C::constructor_data_t; + dev = state().make_pool_object( + dev_constructor_data_t{state(), owner.name() + "." + name}, + std::forward(args)...); + state().register_device(dev->name(), + device_arena::owned_ptr(dev.get(), false)); } - void register_sub_alias(const pstring &name, const detail::core_terminal_t &term); + void register_sub_alias(const pstring &name, + const detail::core_terminal_t & term); void register_sub_alias(const pstring &name, const pstring &aliased); void connect(const pstring &t1, const pstring &t2); - void connect(const detail::core_terminal_t &t1, const detail::core_terminal_t &t2); - protected: + void connect(const detail::core_terminal_t &t1, + const detail::core_terminal_t & t2); - //NETLIB_UPDATE_TERMINALSI() { } + protected: + // NETLIB_UPDATE_TERMINALSI() { } private: }; } // namespace netlist - #endif // NL_CORE_DEVICE_H_ diff --git a/src/lib/netlist/core/device.h b/src/lib/netlist/core/device.h index 33a1bdaac35..5f4a6937f23 100644 --- a/src/lib/netlist/core/device.h +++ b/src/lib/netlist/core/device.h @@ -9,29 +9,35 @@ #define NL_DEVICE_H_ #include "core_device.h" +#include "logic_family.h" #include "param.h" namespace netlist { - // ----------------------------------------------------------------------------- - // device_t - // ----------------------------------------------------------------------------- - class device_t : public base_device_t, - public logic_family_t + // ------------------------------------------------------------------------- + // device_t construction parameters + // ------------------------------------------------------------------------- + + using device_data_t = base_device_data_t; + // The type use to pass data on + using device_param_t = const device_data_t &; + + // ------------------------------------------------------------------------- + // device_t + // ------------------------------------------------------------------------- + + class device_t : public base_device_t, public logic_family_t { public: - device_t(netlist_state_t &owner, const pstring &name); - device_t(netlist_state_t &owner, const pstring &name, - const pstring &model); - // only needed by proxies - device_t(netlist_state_t &owner, const pstring &name, - const logic_family_desc_t *desc); + using constructor_data_t = device_data_t; + using constructor_param_t = device_param_t; - device_t(device_t &owner, const pstring &name); - // pass in a default model - this may be overwritten by PARAM(DEVICE.MODEL, "XYZ(...)") - device_t(device_t &owner, const pstring &name, - const pstring &model); + device_t(device_param_t data); + + device_t(device_param_t data, const pstring &model); + // only needed by proxies + device_t(device_param_t data, const logic_family_desc_t *desc); device_t(const device_t &) = delete; device_t &operator=(const device_t &) = delete; @@ -42,8 +48,9 @@ namespace netlist protected: template - void push_two(T1 &term1, netlist_sig_t newQ1, const netlist_time &delay1, - T2 &term2, netlist_sig_t newQ2, const netlist_time &delay2) noexcept + void push_two(T1 &term1, netlist_sig_t newQ1, + const netlist_time &delay1, T2 &term2, netlist_sig_t newQ2, + const netlist_time &delay2) noexcept { if (delay2 < delay1) { @@ -57,13 +64,51 @@ namespace netlist } } - - //NETLIB_UPDATE_TERMINALSI() { } + // NETLIB_UPDATE_TERMINALSI() { } private: param_model_t m_model; }; + // ------------------------------------------------------------------------- + // FIXME: Rename + // ------------------------------------------------------------------------- + + template + struct sub_device_wrapper + { + using constructor_data_t = typename CX::constructor_data_t; + using constructor_param_t = typename CX::constructor_param_t; + + template + sub_device_wrapper(base_device_t &owner, const pstring &name, + Args &&...args) + { + // m_dev = owner.state().make_pool_object(owner, name, + // std::forward(args)...); + m_dev = owner.state().make_pool_object( + constructor_data_t{owner.state(), owner.name() + "." + name}, + std::forward(args)...); + owner.state().register_device(m_dev->name(), + device_arena::owned_ptr(m_dev.get(), false)); + } + template + sub_device_wrapper(device_t &owner, const pstring &name, Args &&...args) + { + // m_dev = owner.state().make_pool_object(owner, name, + // std::forward(args)...); + m_dev = owner.state().make_pool_object( + constructor_data_t{owner.state(), owner.name() + "." + name}, + std::forward(args)...); + owner.state().register_device(m_dev->name(), + device_arena::owned_ptr(m_dev.get(), false)); + } + CX & operator()() { return *m_dev; } + const CX &operator()() const { return *m_dev; } + + private: + device_arena::unique_ptr m_dev; + }; + } // namespace netlist - #endif // NL_DEVICE_H_ diff --git a/src/lib/netlist/core/device_macros.h b/src/lib/netlist/core/device_macros.h index 156722bfc65..af1fb15e78f 100644 --- a/src/lib/netlist/core/device_macros.h +++ b/src/lib/netlist/core/device_macros.h @@ -8,9 +8,9 @@ /// \file device_macros.h /// -//============================================================ +// ----------------------------------------------------------------------------- // MACROS / New Syntax -//============================================================ +// ----------------------------------------------------------------------------- /// \brief Start a netlist device class. /// @@ -25,45 +25,20 @@ /// /// Also refer to #NETLIB_CONSTRUCTOR. #define NETLIB_OBJECT(name) \ -class NETLIB_NAME(name) : public delegator_t - -/// \brief Start a derived netlist device class. -/// -/// Used to define a derived device class based on `plcass`. -/// The simplest device without inputs or outputs would look like this: -/// -/// NETLIB_OBJECT_DERIVED(some_object, parent_object) -/// { -/// public: -/// NETLIB_CONSTRUCTOR(some_object) { } -/// }; -/// -/// Also refer to #NETLIB_CONSTRUCTOR. -#define NETLIB_OBJECT_DERIVED(name, pclass) \ -class NETLIB_NAME(name) : public delegator_t - - - -// Only used for analog objects like diodes and resistors - -#define NETLIB_BASE_OBJECT(name) \ -class NETLIB_NAME(name) : public delegator_t - -#define NETLIB_CONSTRUCTOR_PASS(cname, ...) \ - using this_type = NETLIB_NAME(cname); \ - public: template NETLIB_NAME(cname)(CLASS &owner, const pstring &name) \ - : base_type(owner, name, __VA_ARGS__) + class NETLIB_NAME(name) \ + : public device_t /// \brief Used to define the constructor of a netlist device. /// /// Use this to define the constructor of a netlist device. Please refer to /// #NETLIB_OBJECT for an example. #define NETLIB_CONSTRUCTOR(cname) \ - using this_type = NETLIB_NAME(cname); \ - public: template NETLIB_NAME(cname)(CLASS &owner, const pstring &name)\ - : base_type(owner, name) +public: \ + NETLIB_NAME(cname)(constructor_param_t data) \ + : device_t(data) -/// \brief Used to define the constructor of a netlist device and define a default model. +/// \brief Used to define the constructor of a netlist device and define a +/// default model. /// /// /// NETLIB_CONSTRUCTOR_MODEL(some_object, "TTL") @@ -72,22 +47,16 @@ class NETLIB_NAME(name) : public delegator_t /// NETLIB_CONSTRUCTOR(some_object) { } /// }; /// -#define NETLIB_CONSTRUCTOR_MODEL(cname, cmodel) \ - using this_type = NETLIB_NAME(cname); \ - public: template NETLIB_NAME(cname)(CLASS &owner, const pstring &name) \ - : base_type(owner, name, cmodel) - -/// \brief Define an extended constructor and add further parameters to it. -/// The macro allows to add further parameters to a device constructor. This is -/// normally used for sub-devices and system devices only. -#define NETLIB_CONSTRUCTOR_EX(cname, ...) \ - using this_type = NETLIB_NAME(cname); \ - public: template NETLIB_NAME(cname)(CLASS &owner, const pstring &name, __VA_ARGS__) \ - : base_type(owner, name) +#define NETLIB_CONSTRUCTOR_MODEL(cname, cmodel) \ +public: \ + NETLIB_NAME(cname)(constructor_param_t data) \ + : device_t(data, cmodel) /// \brief Used to define the destructor of a netlist device. /// The use of a destructor for netlist device should normally not be necessary. -#define NETLIB_DESTRUCTOR(name) public: virtual ~NETLIB_NAME(name)() noexcept override +#define NETLIB_DESTRUCTOR(name) \ +public: \ + virtual ~NETLIB_NAME(name)() noexcept override /// \brief Add this to a device definition to mark the device as dynamic. /// @@ -102,9 +71,11 @@ class NETLIB_NAME(name) : public delegator_t /// \param expr boolean expression /// #define NETLIB_IS_DYNAMIC(expr) \ - public: virtual bool is_dynamic() const noexcept override { return expr; } +public: \ + virtual bool is_dynamic() const noexcept override { return expr; } -/// \brief Add this to a device definition to mark the device as a time-stepping device. +/// \brief Add this to a device definition to mark the device as a time-stepping +/// device. /// /// You have to implement NETLIB_TIMESTEP in this case as well. Currently, only /// the capacitor and inductor devices uses this. @@ -127,14 +98,17 @@ class NETLIB_NAME(name) : public delegator_t /// \endcode #define NETLIB_IS_TIMESTEP(expr) \ - public: virtual bool is_time_step() const noexcept override { return expr; } +public: \ + virtual bool is_time_step() const noexcept override { return expr; } /// \brief Used to implement the time stepping code. /// /// Please see \ref NETLIB_IS_TIMESTEP for an example. #define NETLIB_TIMESTEPI() \ - public: virtual void time_step(time_step_type ts_type, nl_fptype step) noexcept override +public: \ + virtual void time_step(time_step_type ts_type, \ + nl_fptype step) noexcept override /// \brief Used to implement the body of the time stepping code. /// @@ -145,26 +119,36 @@ class NETLIB_NAME(name) : public delegator_t /// \param cname Name of object as given to \ref NETLIB_OBJECT /// #define NETLIB_TIMESTEP(cname) \ - void NETLIB_NAME(cname) :: time_step(time_step_type ts_type, nl_fptype step) noexcept + void NETLIB_NAME(cname)::time_step(time_step_type ts_type, \ + nl_fptype step) noexcept -#define NETLIB_DELEGATE(name) nl_delegate(&this_type :: name, this) +//#define NETLIB_DELEGATE(name) nl_delegate(&this_type :: name, this) +#define NETLIB_DELEGATE(name) \ + nl_delegate(&std::remove_pointer_t::name, this) -#define NETLIB_DELEGATE_NOOP() nl_delegate(&core_device_t::handler_noop, static_cast(this)) +#define NETLIB_DELEGATE_NOOP() \ + nl_delegate(&core_device_t::handler_noop, \ + static_cast(this)) -#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() noexcept override +#define NETLIB_UPDATE_TERMINALSI() \ + virtual void update_terminals() noexcept override #define NETLIB_HANDLERI(name) void name() noexcept #define NETLIB_UPDATE_PARAMI() virtual void update_param() noexcept override #define NETLIB_RESETI() virtual void reset() override -#define NETLIB_SUB(chip) nld_ ## chip -#define NETLIB_SUB_UPTR(ns, chip) device_arena::unique_ptr< ns :: nld_ ## chip > +#define NETLIB_SUB(chip) sub_device_wrapper +#define NETLIB_SUB_NS(ns, chip) sub_device_wrapper -#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() noexcept +#define NETLIB_SUB_UPTR(ns, chip) device_arena::unique_ptr -#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void) +#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip)::name() noexcept -#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() noexcept +#define NETLIB_RESET(chip) void NETLIB_NAME(chip)::reset(void) -#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() noexcept +#define NETLIB_UPDATE_PARAM(chip) \ + void NETLIB_NAME(chip)::update_param() noexcept + +#define NETLIB_UPDATE_TERMINALS(chip) \ + void NETLIB_NAME(chip)::update_terminals() noexcept #endif // NL_CORE_DEVICE_MACROS_H_ diff --git a/src/lib/netlist/core/devices.h b/src/lib/netlist/core/devices.h index 07c82be20da..29667723bf5 100644 --- a/src/lib/netlist/core/devices.h +++ b/src/lib/netlist/core/devices.h @@ -30,25 +30,23 @@ namespace netlist::devices NETLIB_OBJECT(mainclock) { NETLIB_CONSTRUCTOR(mainclock) - , m_Q(*this, "Q") - , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5)) + , m_Q(*this, "Q"), m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5)) { - m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + m_inc = netlist_time::from_fp( + plib::reciprocal(m_freq() * nlconst::two())); } - NETLIB_RESETI() - { - m_Q.net().set_next_scheduled_time(exec().time()); - } + NETLIB_RESETI() { m_Q.net().set_next_scheduled_time(exec().time()); } NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + m_inc = netlist_time::from_fp( + plib::reciprocal(m_freq() * nlconst::two())); } public: - logic_output_t m_Q; // NOLINT: needed in core - netlist_time m_inc; // NOLINT: needed in core + logic_output_t m_Q; // NOLINT: needed in core + netlist_time m_inc; // NOLINT: needed in core private: param_fp_t m_freq; }; @@ -65,7 +63,7 @@ namespace netlist::devices class nld_power_pins { public: - using this_type = nld_power_pins; + using constructor_type = nld_power_pins; explicit nld_power_pins(device_t &owner) : m_VCC(owner, owner.logic_family()->vcc_pin(), NETLIB_DELEGATE(noop)) @@ -80,33 +78,26 @@ namespace netlist::devices } // Some devices like the 74LS629 have two pairs of supply pins. - explicit nld_power_pins(device_t &owner, - const pstring &vcc, const pstring &gnd) + explicit nld_power_pins(device_t &owner, const pstring &vcc, + const pstring &gnd) : m_VCC(owner, vcc, NETLIB_DELEGATE(noop)) , m_GND(owner, gnd, NETLIB_DELEGATE(noop)) { } // Some devices like the 74LS629 have two pairs of supply pins. - explicit nld_power_pins(device_t &owner, - const pstring &vcc, const pstring &gnd, - nl_delegate delegate) + explicit nld_power_pins(device_t &owner, const pstring &vcc, + const pstring &gnd, nl_delegate delegate) : m_VCC(owner, vcc, delegate) , m_GND(owner, gnd, delegate) { } - const analog_input_t &VCC() const noexcept - { - return m_VCC; - } - const analog_input_t &GND() const noexcept - { - return m_GND; - } + const analog_input_t &VCC() const noexcept { return m_VCC; } + const analog_input_t &GND() const noexcept { return m_GND; } private: - void noop() { } + void noop() {} analog_input_t m_VCC; analog_input_t m_GND; }; @@ -124,14 +115,14 @@ namespace netlist::devices , m_max_link_loops(*this, "MAX_LINK_RESOLVE_LOOPS", 100) { } - //NETLIB_RESETI() {} - //NETLIB_UPDATE_PARAMI() { } + // NETLIB_RESETI() {} + // NETLIB_UPDATE_PARAMI() { } public: - param_logic_t m_use_deactivate; - param_num_t m_startup_strategy; - param_num_t m_mos_cap_model; + param_logic_t m_use_deactivate; + param_num_t m_startup_strategy; + param_num_t m_mos_cap_model; //! How many times do we try to resolve links (connections) - param_num_t m_max_link_loops; + param_num_t m_max_link_loops; }; // ----------------------------------------------------------------------------- @@ -145,16 +136,13 @@ namespace netlist::devices { public: NETLIB_CONSTRUCTOR(nc_pin) - , m_I(*this, "I", NETLIB_DELEGATE_NOOP()) - { - } + , m_I(*this, "I", NETLIB_DELEGATE_NOOP()) {} protected: - //NETLIB_RESETI() {} + // NETLIB_RESETI() {} private: analog_input_t m_I; - }; // ----------------------------------------------------------------------------- @@ -164,16 +152,11 @@ namespace netlist::devices NETLIB_OBJECT(gnd) { NETLIB_CONSTRUCTOR(gnd) - , m_Q(*this, "Q") - { - } + , m_Q(*this, "Q") {} - NETLIB_UPDATE_PARAMI() - { - m_Q.push(nlconst::zero()); - } + NETLIB_UPDATE_PARAMI() { m_Q.push(nlconst::zero()); } - //NETLIB_RESETI() {} + // NETLIB_RESETI() {} protected: analog_output_t m_Q; }; diff --git a/src/lib/netlist/core/exec.h b/src/lib/netlist/core/exec.h index 70786d420e6..091d7181e7d 100644 --- a/src/lib/netlist/core/exec.h +++ b/src/lib/netlist/core/exec.h @@ -8,23 +8,22 @@ #ifndef NL_CORE_EXEC_H_ #define NL_CORE_EXEC_H_ +#include "../nltypes.h" #include "base_objects.h" #include "state_var.h" -#include "../nltypes.h" #include "../plib/plists.h" #include "../plib/pstring.h" namespace netlist { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // netlist_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- class netlist_t // NOLINT(clang-analyzer-optin.performance.Padding) { public: - explicit netlist_t(netlist_state_t &state, const pstring &aname); netlist_t(const netlist_t &) = delete; @@ -36,7 +35,10 @@ namespace netlist // run functions - constexpr const netlist_time_ext &time() const noexcept { return m_time; } + constexpr const netlist_time_ext &time() const noexcept + { + return m_time; + } void process_queue(netlist_time_ext delta) noexcept; void abort_current_queue_slice() noexcept @@ -45,15 +47,20 @@ namespace netlist queue_push(m_time, nullptr); } - constexpr const detail::queue_t &queue() const noexcept { return m_queue; } + constexpr const detail::queue_t &queue() const noexcept + { + return m_queue; + } template - void queue_push(Args&&...args) noexcept + void queue_push(Args &&...args) noexcept { if (config::use_queue_stats::value && m_use_stats) - m_queue.emplace(std::forward(args)...); // NOLINT(performance-move-const-arg) + m_queue.emplace(std::forward( + args)...); // NOLINT(performance-move-const-arg) else - m_queue.emplace(std::forward(args)...); // NOLINT(performance-move-const-arg) + m_queue.emplace(std::forward( + args)...); // NOLINT(performance-move-const-arg) } template @@ -80,40 +87,38 @@ namespace netlist return static_cast(m_solver)->gmin(); } - netlist_state_t &nl_state() noexcept { return m_state; } + netlist_state_t & nl_state() noexcept { return m_state; } const netlist_state_t &nl_state() const noexcept { return m_state; } - log_type & log() noexcept { return m_state.log(); } + log_type & log() noexcept { return m_state.log(); } const log_type &log() const noexcept { return m_state.log(); } void print_stats() const; constexpr bool stats_enabled() const noexcept { return m_use_stats; } - void enable_stats(bool val) noexcept { m_use_stats = val; } + void enable_stats(bool val) noexcept { m_use_stats = val; } private: - template void process_queue_stats(netlist_time_ext delta) noexcept; - netlist_state_t & m_state; - devices::nld_solver * m_solver; + netlist_state_t & m_state; + devices::nld_solver *m_solver; // mostly rw - //PALIGNAS(16) - netlist_time_ext m_time; - devices::nld_mainclock * m_main_clock; + // PALIGNAS(16) + netlist_time_ext m_time; + devices::nld_mainclock *m_main_clock; - //PALIGNAS_CACHELINE() - //PALIGNAS(16) - bool m_use_stats; - detail::queue_t m_queue; + // PALIGNAS_CACHELINE() + // PALIGNAS(16) + bool m_use_stats; + detail::queue_t m_queue; // performance - plib::pperftime_t m_stat_mainloop; - plib::pperfcount_t m_perf_out_processed; + plib::pperftime_t m_stat_mainloop; + plib::pperfcount_t m_perf_out_processed; }; } // namespace netlist - #endif // NL_CORE_EXEC_H_ diff --git a/src/lib/netlist/core/logic.h b/src/lib/netlist/core/logic.h index 2efa92d8f6d..ef567398c84 100644 --- a/src/lib/netlist/core/logic.h +++ b/src/lib/netlist/core/logic.h @@ -2,7 +2,7 @@ // copyright-holders:Couriersud /// -/// \file param.h +/// \file logic.h /// #ifndef NL_CORE_LOGIC_H_ @@ -22,37 +22,39 @@ namespace netlist { - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class logic_t : public detail::core_terminal_t, public logic_family_t + class logic_t + : public detail::core_terminal_t + , public logic_family_t { public: - logic_t(device_t &dev, const pstring &aname, - state_e terminal_state, nl_delegate delegate); + logic_t(device_t &dev, const pstring &aname, state_e terminal_state, + nl_delegate delegate); - logic_net_t & net() noexcept + logic_net_t &net() noexcept { return plib::downcast(core_terminal_t::net()); } - constexpr const logic_net_t & net() const noexcept + constexpr const logic_net_t &net() const noexcept { return plib::downcast(core_terminal_t::net()); } }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_input_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- class logic_input_t : public logic_t { public: logic_input_t(device_t &dev, const pstring &aname, - nl_delegate delegate); + nl_delegate delegate); - //const netlist_sig_t &operator()() const noexcept + // const netlist_sig_t &operator()() const noexcept constexpr netlist_sig_t operator()() const noexcept { gsl_Expects(terminal_state() != STATE_INP_PASSIVE); @@ -97,17 +99,15 @@ namespace netlist set_state(STATE_INP_LH); } } - }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_output_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- class logic_output_t : public logic_t { public: - /// \brief logic output constructor /// /// The third parameter does nothing. It is provided only for @@ -115,7 +115,8 @@ namespace netlist /// /// \param dev Device owning this output /// \param aname The name of this output - /// \param dummy Dummy parameter to allow construction like tristate output + /// \param dummy Dummy parameter to allow construction like tristate + /// output /// logic_output_t(device_t &dev, const pstring &aname, bool dummy = false); @@ -142,17 +143,20 @@ namespace netlist /// This function terminates if actually called. /// [[noreturn]] static void set_tristate([[maybe_unused]] netlist_sig_t v, - [[maybe_unused]] netlist_time ts_off_on, [[maybe_unused]] netlist_time ts_on_off) + [[maybe_unused]] netlist_time ts_off_on, + [[maybe_unused]] netlist_time ts_on_off) { - plib::terminate("set_tristate on logic_output should never be called!"); + plib::terminate( + "set_tristate on logic_output should never be called!"); } + private: logic_net_t m_my_net; }; - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // tristate_output_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /// \brief Tristate output /// @@ -170,8 +174,8 @@ namespace netlist class tristate_output_t : public logic_output_t { public: - - tristate_output_t(device_t &dev, const pstring &aname, bool force_logic); + tristate_output_t(device_t &dev, const pstring &aname, + bool force_logic); void push(netlist_sig_t newQ, netlist_time delay) noexcept { @@ -180,31 +184,29 @@ namespace netlist m_last_logic = newQ; } - void set_tristate(netlist_sig_t v, - netlist_time ts_off_on, netlist_time ts_on_off) noexcept + void set_tristate(netlist_sig_t v, netlist_time ts_off_on, + netlist_time ts_on_off) noexcept { if (!m_force_logic) if (v != m_tristate) { - logic_output_t::push((v != 0) ? OUT_TRISTATE() : m_last_logic, v ? ts_off_on : ts_on_off); + logic_output_t::push((v != 0) ? OUT_TRISTATE() + : m_last_logic, + v ? ts_off_on : ts_on_off); m_tristate = v; } } - bool is_force_logic() const noexcept - { - return m_force_logic; - } + bool is_force_logic() const noexcept { return m_force_logic; } private: using logic_output_t::initial; using logic_output_t::set_Q_time; state_var m_last_logic; state_var m_tristate; - bool m_force_logic; + bool m_force_logic; }; } // namespace netlist - #endif // NL_CORE_LOGIC_H_ diff --git a/src/lib/netlist/core/logic_family.h b/src/lib/netlist/core/logic_family.h index 7264987b466..97084dd4dc0 100644 --- a/src/lib/netlist/core/logic_family.h +++ b/src/lib/netlist/core/logic_family.h @@ -9,6 +9,7 @@ #define NL_CORE_LOGIC_FAMILY_H_ #include "../nltypes.h" + #include "../plib/pstring.h" namespace netlist @@ -20,52 +21,78 @@ namespace netlist class logic_family_desc_t { public: - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default) - logic_family_desc_t() - { - } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, + // modernize-use-equals-default) + logic_family_desc_t() = default; logic_family_desc_t(const logic_family_desc_t &) = delete; logic_family_desc_t &operator=(const logic_family_desc_t &) = delete; // FOXME: Should be move constructible logic_family_desc_t(logic_family_desc_t &&) noexcept = delete; - logic_family_desc_t &operator=(logic_family_desc_t &&) noexcept = delete; + logic_family_desc_t &operator=( + logic_family_desc_t &&) noexcept = delete; virtual ~logic_family_desc_t() noexcept = default; - virtual device_arena::unique_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_output_t *proxied) const = 0; - virtual device_arena::unique_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_input_t *proxied) const = 0; + virtual device_arena::unique_ptr + create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, + const logic_output_t *proxied) const = 0; + virtual device_arena::unique_ptr + create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, + const logic_input_t *proxied) const = 0; - nl_fptype low_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_low_threshold_PCNT; } - nl_fptype high_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_high_threshold_PCNT; } - nl_fptype low_offset_V() const noexcept{ return m_low_VO; } - nl_fptype high_offset_V() const noexcept{ return m_high_VO; } - nl_fptype R_low() const noexcept{ return m_R_low; } - nl_fptype R_high() const noexcept{ return m_R_high; } + nl_fptype low_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept + { + return VN + (VP - VN) * m_low_threshold_PCNT; + } + nl_fptype high_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept + { + return VN + (VP - VN) * m_high_threshold_PCNT; + } + nl_fptype low_offset_V() const noexcept { return m_low_VO; } + nl_fptype high_offset_V() const noexcept { return m_high_VO; } + nl_fptype R_low() const noexcept { return m_R_low; } + nl_fptype R_high() const noexcept { return m_R_high; } - bool is_above_high_threshold_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept - { return V > high_threshold_V(VN, VP); } + bool is_above_high_threshold_V(nl_fptype V, nl_fptype VN, + nl_fptype VP) const noexcept + { + return V > high_threshold_V(VN, VP); + } - bool is_below_low_threshold_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept - { return V < low_threshold_V(VN, VP); } + bool is_below_low_threshold_V(nl_fptype V, nl_fptype VN, + nl_fptype VP) const noexcept + { + return V < low_threshold_V(VN, VP); + } pstring vcc_pin() const { return pstring(m_vcc); } pstring gnd_pin() const { return pstring(m_gnd); } - nl_fptype m_low_threshold_PCNT; //!< low input threshold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled - nl_fptype m_high_threshold_PCNT; //!< high input threshold offset. If the input voltage is above the value times supply voltage, a "0" input is signalled - nl_fptype m_low_VO; //!< low output voltage offset. This voltage is output if the ouput is "0" - nl_fptype m_high_VO; //!< high output voltage offset. The supply voltage minus this offset is output if the ouput is "1" - nl_fptype m_R_low; //!< low output resistance. Value of series resistor used for low output - nl_fptype m_R_high; //!< high output resistance. Value of series resistor used for high output - const char *m_vcc; //!< default power pin name for positive supply - const char *m_gnd; //!< default power pin name for negative supply + nl_fptype m_low_threshold_PCNT; //!< low input threshold offset. If the + //!< input voltage is below this value + //!< times supply voltage, a "0" input + //!< is signalled + nl_fptype m_high_threshold_PCNT; //!< high input threshold offset. If + //!< the input voltage is above the + //!< value times supply voltage, a "0" + //!< input is signalled + nl_fptype m_low_VO; //!< low output voltage offset. This voltage is + //!< output if the ouput is "0" + nl_fptype m_high_VO; //!< high output voltage offset. The supply voltage + //!< minus this offset is output if the ouput is + //!< "1" + nl_fptype m_R_low; //!< low output resistance. Value of series resistor + //!< used for low output + nl_fptype m_R_high; //!< high output resistance. Value of series + //!< resistor used for high output + const char *m_vcc; //!< default power pin name for positive supply + const char *m_gnd; //!< default power pin name for negative supply }; - /// \brief Base class for devices, terminals, outputs and inputs which support + /// \brief Base class for devices, terminals, outputs and inputs which + /// support /// logic families. /// This class is a storage container to store the logic family for a /// netlist object. You will not directly use it. Please refer to @@ -79,8 +106,14 @@ namespace netlist class logic_family_t { public: - logic_family_t() : m_logic_family(nullptr) {} - logic_family_t(const logic_family_desc_t *d) : m_logic_family(d) {} + logic_family_t() + : m_logic_family(nullptr) + { + } + logic_family_t(const logic_family_desc_t *d) + : m_logic_family(d) + { + } logic_family_t(const logic_family_t &) = delete; logic_family_t &operator=(const logic_family_t &) = delete; @@ -89,16 +122,22 @@ namespace netlist logic_family_t(logic_family_t &&) noexcept = delete; logic_family_t &operator=(logic_family_t &&) noexcept = delete; - const logic_family_desc_t *logic_family() const noexcept { return m_logic_family; } - void set_logic_family(const logic_family_desc_t *fam) noexcept { m_logic_family = fam; } + const logic_family_desc_t *logic_family() const noexcept + { + return m_logic_family; + } + void set_logic_family(const logic_family_desc_t *fam) noexcept + { + m_logic_family = fam; + } protected: - ~logic_family_t() noexcept = default; // prohibit polymorphic destruction + ~logic_family_t() noexcept = default; // prohibit polymorphic + // destruction private: const logic_family_desc_t *m_logic_family; }; } // namespace netlist - #endif // NL_CORE_LOGIC_FAMILY_H_ diff --git a/src/lib/netlist/core/netlist_state.h b/src/lib/netlist/core/netlist_state.h index 0f0b62f8bee..f8a87b9280f 100644 --- a/src/lib/netlist/core/netlist_state.h +++ b/src/lib/netlist/core/netlist_state.h @@ -8,9 +8,8 @@ #ifndef NL_CORE_NETLIST_STATE_H_ #define NL_CORE_NETLIST_STATE_H_ -#include "queue.h" - #include "../nltypes.h" +#include "queue.h" #include "../plib/plists.h" #include "../plib/pstate.h" @@ -30,12 +29,14 @@ namespace netlist class netlist_state_t { public: - - using nets_collection_type = std::vector>; - using family_collection_type = std::unordered_map>; + 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>>; + using devices_collection_type = std::vector< + std::pair>>; netlist_state_t(const pstring &name, plib::plog_delegate logger); @@ -51,10 +52,11 @@ namespace netlist template static bool check_class(core_device_t *p) noexcept { - return dynamic_cast(p) != nullptr; + return bool(plib::dynamic_downcast(p)); } - core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const noexcept(false); + 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 /// @@ -81,19 +83,21 @@ namespace netlist std::vector tmp; for (const auto &d : m_devices) { - auto * const dev = dynamic_cast(d.second.get()); - if (dev != nullptr) - tmp.push_back(dev); + if (auto dev = plib::dynamic_downcast(d.second.get())) + tmp.push_back(*dev); } return tmp; } // logging - log_type & log() noexcept { return m_log; } + 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; } + plib::dynamic_library_base &static_solver_lib() const noexcept + { + return *m_lib; + } /// \brief provide library with static solver implementations. /// @@ -101,32 +105,41 @@ namespace netlist /// 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); + void set_static_solver_lib( + std::unique_ptr &&lib); - netlist_t &exec() noexcept { return *m_netlist; } + 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) + 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); + 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) + 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); + 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; + 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)); } + void register_net(device_arena::owned_ptr &&net) + { + m_nets.push_back(std::move(net)); + } /// \brief Get device pointer by name /// @@ -137,7 +150,7 @@ namespace netlist core_device_t *find_device(const pstring &name) const { - for (const auto & d : m_devices) + for (const auto &d : m_devices) if (d.first == name) return d.second.get(); return nullptr; @@ -145,24 +158,25 @@ namespace netlist /// \brief Register device using owned_ptr /// - /// Used to register owned devices. These are devices declared as objects - /// in another devices. + /// 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) + void register_device(const pstring &name, + device_arena::owned_ptr && dev) noexcept(false) { - for (auto & d : m_devices) + 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) }); + // m_devices.push_back(std::move(dev)); + m_devices.insert(m_devices.end(), {name, std::move(dev)}); } /// \brief Register device using unique_ptr @@ -173,9 +187,11 @@ namespace netlist /// \param dev Device to be registered template - void register_device(const pstring &name, device_arena::unique_ptr &&dev) + void register_device(const pstring &name, + device_arena::unique_ptr && dev) { - register_device(name, device_arena::owned_ptr(dev.release(), true, dev.get_deleter())); + register_device(name, device_arena::owned_ptr(dev.release(), + true, dev.get_deleter())); } /// \brief Remove device @@ -187,41 +203,45 @@ namespace netlist void remove_device(core_device_t *dev); - setup_t &setup() noexcept { return *m_setup; } + setup_t & setup() noexcept { return *m_setup; } const setup_t &setup() const noexcept { return *m_setup; } - nlparse_t &parser(); - const nlparse_t &parser() const; + 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 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; } + 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; } + 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) + 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; } + 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; + 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 @@ -236,37 +256,38 @@ namespace netlist /// void free_setup_resources(); #if !(NL_USE_INPLACE_CORE_TERMS) - std::vector &core_terms(const detail::net_t &net) + 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 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; + 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; + host_arena::unique_ptr m_setup; - nets_collection_type m_nets; + nets_collection_type m_nets; // sole use is to manage lifetime of net objects - devices_collection_type m_devices; + devices_collection_type m_devices; // sole use is to manage lifetime of family objects - family_collection_type m_family_cache; + family_collection_type m_family_cache; #if !(NL_USE_INPLACE_CORE_TERMS) // all terms for a net - std::unordered_map> m_core_terms; + std::unordered_map> + m_core_terms; #endif // dummy version - int m_dummy_version; + int m_dummy_version; }; } // namespace netlist - #endif // NL_CORE_NETLIST_STATE_H_ diff --git a/src/lib/netlist/core/nets.h b/src/lib/netlist/core/nets.h index 280cda2013e..1a81c7ecd1c 100644 --- a/src/lib/netlist/core/nets.h +++ b/src/lib/netlist/core/nets.h @@ -8,12 +8,12 @@ #ifndef NL_CORE_NETS_H_ #define NL_CORE_NETS_H_ +#include "../nltypes.h" #include "base_objects.h" #include "core_device.h" #include "exec.h" #include "state_var.h" -#include "../nltypes.h" #include "../plib/plists.h" #include "../plib/pstring.h" @@ -21,16 +21,16 @@ namespace netlist { - namespace detail { + namespace detail + { - // ----------------------------------------------------------------------------- + // --------------------------------------------------------------------- // net_t - // ----------------------------------------------------------------------------- + // --------------------------------------------------------------------- class net_t : public netlist_object_t { public: - enum class queue_status { DELAYED_DUE_TO_INACTIVE = 0, @@ -38,7 +38,8 @@ namespace netlist DELIVERED }; - net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *rail_terminal = nullptr); + net_t(netlist_state_t &nl, const pstring &aname, + core_terminal_t *rail_terminal = nullptr); net_t(const net_t &) = delete; net_t &operator=(const net_t &) = delete; @@ -49,16 +50,13 @@ namespace netlist virtual void reset() noexcept; - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- // Hot section // // Any changes below will impact performance. - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- - constexpr void toggle_new_Q() noexcept - { - m_new_Q = (m_cur_Q ^ 1); - } + constexpr void toggle_new_Q() noexcept { m_new_Q = (m_cur_Q ^ 1); } void toggle_and_push_to_queue(const netlist_time &delay) noexcept { @@ -73,30 +71,44 @@ namespace netlist return m_in_queue == queue_status::QUEUED; } - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- // Very hot - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- template void update_devs() noexcept; - constexpr const netlist_time_ext &next_scheduled_time() const noexcept { return m_next_scheduled_time; } - void set_next_scheduled_time(const netlist_time_ext &next_time) noexcept { m_next_scheduled_time = next_time; } + constexpr const netlist_time_ext & + next_scheduled_time() const noexcept + { + return m_next_scheduled_time; + } + void set_next_scheduled_time( + const netlist_time_ext &next_time) noexcept + { + m_next_scheduled_time = next_time; + } - bool is_rail_net() const noexcept { return !(m_rail_terminal == nullptr); } - core_terminal_t & rail_terminal() const noexcept { return *m_rail_terminal; } + bool is_rail_net() const noexcept + { + return !(m_rail_terminal == nullptr); + } + core_terminal_t &rail_terminal() const noexcept + { + return *m_rail_terminal; + } void add_to_active_list(core_terminal_t &term) noexcept; void remove_from_active_list(core_terminal_t &term) noexcept; - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- // setup stuff - cold - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- bool is_logic() const noexcept; bool is_analog() const noexcept; - void rebuild_list(); // rebuild m_list after a load + void rebuild_list() noexcept(false); // rebuild m_list after a load void update_inputs() noexcept { @@ -107,26 +119,36 @@ namespace netlist } } - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- // net management - // ----------------------------------------------------------------------------- + // ----------------------------------------------------------------- - const std::vector core_terms_copy() + std::vector + core_terms_copy() noexcept(false) { - std::vector ret(core_terms_ref().size()); - std::copy(core_terms_ref().begin(), core_terms_ref().end(), ret.begin()); + std::vector ret( + core_terms_ref().size()); + std::copy(core_terms_ref().begin(), core_terms_ref().end(), + ret.begin()); return ret; } - void remove_terminal(detail::core_terminal_t &term); - void remove_all_terminals(); - void add_terminal(detail::core_terminal_t &terminal); + void remove_terminal(detail::core_terminal_t &term) noexcept(false); + void remove_all_terminals() noexcept(false); + void add_terminal(detail::core_terminal_t &terminal) noexcept( + false); + + bool core_terms_empty() noexcept(false) + { + return core_terms_ref().empty(); + } - bool core_terms_empty() noexcept { return core_terms_ref().empty(); } protected: - // only used for logic nets - constexpr const netlist_sig_t &Q() const noexcept { return m_cur_Q; } + constexpr const netlist_sig_t &Q() const noexcept + { + return m_cur_Q; + } // only used for logic nets void initial(netlist_sig_t val) noexcept @@ -136,15 +158,17 @@ namespace netlist } // only used for logic nets - void set_Q_and_push(netlist_sig_t newQ, const netlist_time &delay) noexcept; + void set_Q_and_push(netlist_sig_t newQ, + const netlist_time & delay) noexcept; // only used for logic nets - void set_Q_time(netlist_sig_t newQ, const netlist_time_ext &at) noexcept; - + void set_Q_time(netlist_sig_t newQ, + const netlist_time_ext & at) noexcept; private: #if NL_USE_INPLACE_CORE_TERMS - const plib::linked_list_t &core_terms_ref() const noexcept + const plib::linked_list_t & + core_terms_ref() const noexcept { return m_core_terms; } @@ -154,14 +178,14 @@ namespace netlist return state().core_terms(*this); } #endif - state_var m_new_Q; - state_var m_cur_Q; - state_var m_in_queue; + state_var m_new_Q; + state_var m_cur_Q; + state_var m_in_queue; // FIXME: this needs to be saved as well plib::linked_list_t m_list_active; - state_var m_next_scheduled_time; + state_var m_next_scheduled_time; - core_terminal_t * m_rail_terminal; + core_terminal_t *m_rail_terminal; #if NL_USE_INPLACE_CORE_TERMS plib::linked_list_t m_core_terms; #endif @@ -174,10 +198,15 @@ namespace netlist m_next_scheduled_time = exec().time() + delay; if constexpr (config::avoid_noop_queue_pushes::value) - m_in_queue = (m_list_active.empty() ? queue_status::DELAYED_DUE_TO_INACTIVE - : (m_new_Q != m_cur_Q ? queue_status::QUEUED : queue_status::DELIVERED)); + m_in_queue = (m_list_active.empty() + ? queue_status::DELAYED_DUE_TO_INACTIVE + : (m_new_Q != m_cur_Q + ? queue_status::QUEUED + : queue_status::DELIVERED)); else - m_in_queue = m_list_active.empty() ? queue_status::DELAYED_DUE_TO_INACTIVE : queue_status::QUEUED; + m_in_queue = m_list_active.empty() + ? queue_status::DELAYED_DUE_TO_INACTIVE + : queue_status::QUEUED; if (m_in_queue == queue_status::QUEUED) exec().queue_push(m_next_scheduled_time, this); @@ -194,15 +223,16 @@ namespace netlist const netlist_sig_t new_Q(m_new_Q); const netlist_sig_t cur_Q(m_cur_Q); - if (config::avoid_noop_queue_pushes::value || ((new_Q ^ cur_Q) != 0)) + if (config::avoid_noop_queue_pushes::value + || ((new_Q ^ cur_Q) != 0)) { m_cur_Q = new_Q; const auto mask = (new_Q << core_terminal_t::INP_LH_SHIFT) - | (cur_Q << core_terminal_t::INP_HL_SHIFT); + | (cur_Q << core_terminal_t::INP_HL_SHIFT); if (!KEEP_STATS) { - for (core_terminal_t * p: m_list_active) + for (core_terminal_t *p : m_list_active) { p->set_copied_input(new_Q); if ((p->terminal_state() & mask) != 0) @@ -211,7 +241,7 @@ namespace netlist } else { - for (core_terminal_t * p : m_list_active) + for (core_terminal_t *p : m_list_active) { p->set_copied_input(new_Q); auto *stats(p->device().stats()); @@ -239,11 +269,13 @@ namespace netlist rail_terminal().device().do_inc_active(); if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE) { - // if we avoid queue pushes we must test if m_cur_Q and m_new_Q are equal - if ((!config::avoid_noop_queue_pushes::value || (m_cur_Q != m_new_Q)) + // if we avoid queue pushes we must test if m_cur_Q and + // m_new_Q are equal + if ((!config::avoid_noop_queue_pushes::value + || (m_cur_Q != m_new_Q)) && (m_next_scheduled_time > exec().time())) { - m_in_queue = queue_status::QUEUED; // pending + m_in_queue = queue_status::QUEUED; // pending exec().queue_push(m_next_scheduled_time, this); } else @@ -258,7 +290,8 @@ namespace netlist } } - inline void net_t::remove_from_active_list(core_terminal_t &term) noexcept + inline void net_t::remove_from_active_list( + core_terminal_t &term) noexcept { gsl_Expects(!m_list_active.empty()); m_list_active.remove(&term); @@ -269,7 +302,8 @@ namespace netlist // All our connected outputs have signalled they no longer // will act on input. We thus remove any potentially queued // events and mark them. - // FIXME: May cause regression test to fail - revisit in this case + // FIXME: May cause regression test to fail - revisit in + // this case // // This code is definitively needed for the // AVOID_NOOP_QUEUE_PUSHES code path - therefore I left @@ -285,7 +319,8 @@ namespace netlist } // only used for logic nets - inline void net_t::set_Q_and_push(netlist_sig_t newQ, const netlist_time &delay) noexcept + inline void net_t::set_Q_and_push(netlist_sig_t newQ, + const netlist_time & delay) noexcept { gsl_Expects(delay >= netlist_time::zero()); @@ -297,7 +332,8 @@ namespace netlist } // only used for logic nets - inline void net_t::set_Q_time(netlist_sig_t newQ, const netlist_time_ext &at) noexcept + inline void net_t::set_Q_time(netlist_sig_t newQ, + const netlist_time_ext & at) noexcept { gsl_Expects(at >= netlist_time_ext::zero()); @@ -317,12 +353,11 @@ namespace netlist } // namespace detail - class analog_net_t : public detail::net_t { public: - - analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal = nullptr); + analog_net_t(netlist_state_t &nl, const pstring &aname, + detail::core_terminal_t *rail_terminal = nullptr); void reset() noexcept override; @@ -331,11 +366,15 @@ namespace netlist // used by solver code ... nl_fptype *Q_Analog_state_ptr() noexcept { return *m_cur_Analog; } - //FIXME: needed by current solver code + // FIXME: needed by current solver code solver::matrix_solver_t *solver() const noexcept { return m_solver; } - void set_solver(solver::matrix_solver_t *solver) noexcept { m_solver = solver; } + void set_solver(solver::matrix_solver_t *solver) noexcept + { + m_solver = solver; + } - friend constexpr bool operator==(const analog_net_t &lhs, const analog_net_t &rhs) noexcept + friend constexpr bool operator==(const analog_net_t &lhs, + const analog_net_t & rhs) noexcept { return &lhs == &rhs; } @@ -348,17 +387,15 @@ namespace netlist class logic_net_t : public detail::net_t { public: + logic_net_t(netlist_state_t &nl, const pstring &aname, + detail::core_terminal_t *rail_terminal = nullptr); - logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal = nullptr); - - using detail::net_t::Q; using detail::net_t::initial; + using detail::net_t::Q; using detail::net_t::set_Q_and_push; using detail::net_t::set_Q_time; }; - } // namespace netlist - #endif // NL_CORE_NETS_H_ diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h index 388ccebc1ba..34e6c3b1b1e 100644 --- a/src/lib/netlist/core/param.h +++ b/src/lib/netlist/core/param.h @@ -9,7 +9,6 @@ #define NL_CORE_PARAM_H_ #include "../nltypes.h" - #include "base_objects.h" #include "core_device.h" #include "setup.h" @@ -30,16 +29,17 @@ namespace netlist class param_t : public detail::device_object_t { public: - - enum param_type_t { + enum param_type_t + { STRING, DOUBLE, INTEGER, LOGIC, - POINTER // Special-case which is always initialized at MAME startup time + POINTER // Special-case which is always initialized at MAME startup + // time }; - //device-less, it's the responsibility of the owner to register! + // device-less, it's the responsibility of the owner to register! param_t(const pstring &name); param_t(core_device_t &device, const pstring &name); @@ -52,7 +52,6 @@ namespace netlist virtual pstring value_string() const = 0; protected: - pstring get_initial(const core_device_t *dev, bool *found) const; template @@ -64,7 +63,6 @@ namespace netlist device().update_param(); } } - }; // ----------------------------------------------------------------------------- @@ -72,17 +70,21 @@ namespace netlist // ----------------------------------------------------------------------------- template - class param_num_t final: public param_t + class param_num_t final : public param_t { public: using value_type = T; - param_num_t(core_device_t &device, const pstring &name, T val) noexcept(false); + param_num_t(core_device_t &device, const pstring &name, T val) noexcept( + false); constexpr const T &operator()() const noexcept { return m_param; } - constexpr operator const T& () const noexcept { return m_param; } + constexpr operator const T &() const noexcept { return m_param; } - void set(const T ¶m) noexcept { set_and_update_param(m_param, param); } + void set(const T ¶m) noexcept + { + set_and_update_param(m_param, param); + } pstring value_string() const override { @@ -94,22 +96,27 @@ namespace netlist }; template - class param_enum_t final: public param_t + class param_enum_t final : public param_t { public: using value_type = T; - param_enum_t(core_device_t &device, const pstring &name, T val) noexcept(false); + param_enum_t(core_device_t &device, const pstring &name, + T val) noexcept(false); constexpr T operator()() const noexcept { return m_param; } - constexpr operator T() const noexcept { return m_param; } - void set(const T ¶m) noexcept { set_and_update_param(m_param, param); } + constexpr operator T() const noexcept { return m_param; } + void set(const T ¶m) noexcept + { + set_and_update_param(m_param, param); + } pstring value_string() const override { // returns the numerical value return plib::pfmt("{}")(static_cast(m_param)); } + private: T m_param; }; @@ -119,21 +126,25 @@ namespace netlist // ----------------------------------------------------------------------------- // FIXME: not a core component -> legacy - class param_ptr_t final: public param_t + class param_ptr_t final : public param_t { public: - param_ptr_t(core_device_t &device, const pstring &name, std::uint8_t* val); - std::uint8_t * operator()() const noexcept { return m_param; } - void set(std::uint8_t *param) noexcept { set_and_update_param(m_param, param); } + param_ptr_t(core_device_t &device, const pstring &name, + std::uint8_t *val); + std::uint8_t *operator()() const noexcept { return m_param; } + void set(std::uint8_t *param) noexcept + { + set_and_update_param(m_param, param); + } pstring value_string() const override { // returns something which errors - return { "PTRERROR" }; + return {"PTRERROR"}; } private: - std::uint8_t* m_param; + std::uint8_t *m_param; }; // ----------------------------------------------------------------------------- @@ -143,11 +154,16 @@ namespace netlist class param_str_t : public param_t { public: - param_str_t(core_device_t &device, const pstring &name, const pstring &val); - param_str_t(netlist_state_t &state, const pstring &name, const pstring &val); + param_str_t(core_device_t &device, const pstring &name, + const pstring &val); + // FIXME: The device less constructor is only used by macro parameters + // Every macro device gets a nld_wrapper object as the owner. + // Use this as the owner and get rid of this constructor. + param_str_t(netlist_state_t &state, const pstring &name, + const pstring &val); pstring operator()() const noexcept { return str(); } - void set(const pstring ¶m) + void set(const pstring ¶m) { if (*m_param != param) { @@ -156,14 +172,12 @@ namespace netlist device().update_param(); } } - pstring value_string() const override - { - return *m_param; - } + pstring value_string() const override { return *m_param; } protected: virtual void changed() noexcept; - pstring str() const noexcept { return *m_param; } + pstring str() const noexcept { return *m_param; } + private: host_arena::unique_ptr m_param; }; @@ -175,23 +189,26 @@ namespace netlist class param_model_t : public param_str_t { public: - template class value_base_t { public: - template ::value>> + template ::value>> value_base_t(P ¶m, const pstring &name) : m_value(gsl::narrow(param.value(name))) { } - template ::value, int> = 0> + template ::value, int> = 0> value_base_t(P ¶m, const pstring &name) : m_value(static_cast(param.value_str(name))) { } T operator()() const noexcept { return m_value; } - operator T() const noexcept { return m_value; } + operator T() const noexcept { return m_value; } + private: const T m_value; }; @@ -199,18 +216,21 @@ namespace netlist using value_t = value_base_t; using value_str_t = value_base_t; - param_model_t(core_device_t &device, const pstring &name, const pstring &val) + param_model_t(core_device_t &device, const pstring &name, + const pstring &val) : param_str_t(device, name, val) { } - pstring value_str(const pstring &entity); + pstring value_str(const pstring &entity); nl_fptype value(const pstring &entity); - pstring type(); + pstring type(); // hide this void set(const pstring ¶m) = delete; + protected: void changed() noexcept override; + private: }; @@ -227,8 +247,9 @@ namespace netlist } plib::istream_uptr stream(); + protected: - void changed() noexcept override { } + void changed() noexcept override {} }; // ----------------------------------------------------------------------------- @@ -236,17 +257,17 @@ namespace netlist // ----------------------------------------------------------------------------- template - class param_rom_t final: public param_data_t + class param_rom_t final : public param_data_t { public: - param_rom_t(core_device_t &device, const pstring &name); - const ST & operator[] (std::size_t n) const noexcept { return m_data[n]; } + const ST &operator[](std::size_t n) const noexcept { return m_data[n]; } + protected: void changed() noexcept override { - plib::istream_read(*stream(), m_data.data(), 1< - param_num_t::param_num_t(core_device_t &device, const pstring &name, const T val) + param_num_t::param_num_t(core_device_t &device, const pstring &name, + const T val) : param_t(device, name) , m_param(val) { - bool found = false; + bool found = false; pstring p = this->get_initial(&device, &found); if (found) { @@ -267,7 +289,8 @@ namespace netlist auto valx = func.evaluate(); if (plib::is_integral::value) if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6)) - throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p)); + throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2( + device.name() + "." + name, p)); m_param = plib::narrow_cast(valx); } @@ -275,19 +298,21 @@ namespace netlist } template - param_enum_t::param_enum_t(core_device_t &device, const pstring &name, const T val) + param_enum_t::param_enum_t(core_device_t &device, const pstring &name, + const T val) : param_t(device, name) , m_param(val) { - bool found = false; + bool found = false; pstring p = this->get_initial(&device, &found); if (found) { - T temp(val); + T temp(val); bool ok = temp.set_from_string(p); if (!ok) { - device.state().log().fatal(MF_INVALID_ENUM_CONVERSION_1_2(name, p)); + device.state().log().fatal( + MF_INVALID_ENUM_CONVERSION_1_2(name, p)); throw nl_exception(MF_INVALID_ENUM_CONVERSION_1_2(name, p)); } m_param = temp; @@ -297,13 +322,14 @@ namespace netlist } template - param_rom_t::param_rom_t(core_device_t &device, const pstring &name) + param_rom_t::param_rom_t(core_device_t &device, + const pstring & name) : param_data_t(device, name) { auto f = this->stream(); if (!f.empty()) { - plib::istream_read(*f, m_data.data(), 1< - class queue_base : - public config::timed_queue>, - public plib::state_manager_t::callback_t + class queue_base + : public config::timed_queue> + , public plib::state_manager_t::callback_t { public: using entry_t = plib::queue_entry_t; using base_queue = config::timed_queue; - using id_delegate = plib::pmfp; - using obj_delegate = plib::pmfp; + using id_delegate = plib::pmfp; + using obj_delegate = plib::pmfp; - explicit queue_base(A &arena, std::size_t size, id_delegate get_id, obj_delegate get_obj) + explicit queue_base(A &arena, std::size_t size, id_delegate get_id, + obj_delegate get_obj) : base_queue(arena, size) , m_size(0) , m_times(size) @@ -61,43 +61,47 @@ namespace netlist::detail queue_base &operator=(queue_base &&) = delete; protected: - - void register_state(plib::state_manager_t &manager, const pstring &module) override + void register_state(plib::state_manager_t &manager, + const pstring & module) override { manager.save_item(this, m_size, module + "." + "size"); - manager.save_item(this, &m_times[0], module + "." + "times", m_times.size()); - manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size()); + manager.save_item(this, &m_times[0], module + "." + "times", + m_times.size()); + manager.save_item(this, &m_net_ids[0], module + "." + "names", + m_net_ids.size()); } - void on_pre_save([[maybe_unused]] plib::state_manager_t &manager) override + void on_pre_save( + [[maybe_unused]] plib::state_manager_t &manager) override { m_size = this->size(); - for (std::size_t i = 0; i < m_size; i++ ) + for (std::size_t i = 0; i < m_size; i++) { - m_times[i] = this->list_pointer()[i].exec_time().as_raw(); + m_times[i] = this->list_pointer()[i].exec_time().as_raw(); m_net_ids[i] = m_get_id(this->list_pointer()[i].object()); } } - void on_post_load([[maybe_unused]] plib::state_manager_t &manager) override + void on_post_load( + [[maybe_unused]] plib::state_manager_t &manager) override { this->clear(); - for (std::size_t i = 0; i < m_size; i++ ) + for (std::size_t i = 0; i < m_size; i++) { O *n = m_obj_by_id(m_net_ids[i]); - this->template push(entry_t(netlist_time_ext::from_raw(m_times[i]),n)); + this->template push( + entry_t(netlist_time_ext::from_raw(m_times[i]), n)); } } private: - std::size_t m_size; + std::size_t m_size; std::vector m_times; - std::vector m_net_ids; - id_delegate m_get_id; - obj_delegate m_obj_by_id; + std::vector m_net_ids; + id_delegate m_get_id; + obj_delegate m_obj_by_id; }; using queue_t = queue_base; } // namespace netlist::detail - #endif // NL_CORE_QUEUE_H_ diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h index ddf1aa14889..63210a96a06 100644 --- a/src/lib/netlist/core/setup.h +++ b/src/lib/netlist/core/setup.h @@ -179,11 +179,11 @@ namespace netlist models_t &models() noexcept { return m_models; } const models_t &models() const noexcept { return m_models; } - netlist_state_t &nlstate() { return m_nlstate; } - const netlist_state_t &nlstate() const { return m_nlstate; } + netlist_state_t &nlstate() noexcept { return m_nlstate; } + const netlist_state_t &nlstate() const noexcept { return m_nlstate; } - nlparse_t &parser() { return m_parser; } - const nlparse_t &parser() const { return m_parser; } + nlparse_t &parser() noexcept { return m_parser; } + const nlparse_t &parser() const noexcept { return m_parser; } log_type &log() noexcept; const log_type &log() const noexcept; @@ -196,10 +196,10 @@ namespace netlist void merge_nets(detail::net_t &this_net, detail::net_t &other_net); void connect_terminals(detail::core_terminal_t &t1, detail::core_terminal_t &t2); - void connect_input_output(detail::core_terminal_t &in, detail::core_terminal_t &out); - void connect_terminal_output(terminal_t &in, detail::core_terminal_t &out); - void connect_terminal_input(terminal_t &term, detail::core_terminal_t &inp); - bool connect_input_input(detail::core_terminal_t &t1, detail::core_terminal_t &t2); + void connect_input_output(detail::core_terminal_t &input, detail::core_terminal_t &output); + void connect_terminal_output(detail::core_terminal_t &terminal, detail::core_terminal_t &output); + void connect_terminal_input(detail::core_terminal_t &terminal, detail::core_terminal_t &input); + bool connect_input_input(detail::core_terminal_t &input1, detail::core_terminal_t &input2); bool connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2); diff --git a/src/lib/netlist/core/state_var.h b/src/lib/netlist/core/state_var.h index 88f9a072a1f..7c6e7aec8be 100644 --- a/src/lib/netlist/core/state_var.h +++ b/src/lib/netlist/core/state_var.h @@ -9,6 +9,7 @@ #define NL_CORE_STATE_VAR_H_ #include "../nltypes.h" + #include "../plib/pstring.h" namespace netlist @@ -31,20 +32,19 @@ namespace netlist struct state_var { public: - using value_type = T; template //! Constructor. - state_var(O &owner, //!< owner must have a netlist() method. - const pstring &name, //!< identifier/name for this state variable - const T &value //!< Initial value after construction - ); + state_var(O & owner, //!< owner must have a netlist() method. + const pstring &name, //!< identifier/name for this state variable + const T & value //!< Initial value after construction + ); template //! Constructor. - state_var(O &owner, //!< owner must have a netlist() method. - const pstring &name //!< identifier/name for this state variable + state_var(O & owner, //!< owner must have a netlist() method. + const pstring &name //!< identifier/name for this state variable ); state_var(state_var &&) noexcept = delete; @@ -63,38 +63,47 @@ namespace netlist return *this; } // OSX doesn't like noexcept //! Assignment operator to assign value of type T. - constexpr state_var &operator=(const T &rhs) noexcept { m_value = rhs; return *this; } + constexpr state_var &operator=(const T &rhs) noexcept + { + m_value = rhs; + return *this; + } //! Assignment move operator to assign value of type T. - //constexpr state_var &operator=(T &&rhs) noexcept { std::swap(m_value, rhs); return *this; } - constexpr state_var &operator=(T &&rhs) noexcept { m_value = std::move(rhs); return *this; } + // constexpr state_var &operator=(T &&rhs) noexcept { std::swap(m_value, + // rhs); return *this; } + constexpr state_var &operator=(T &&rhs) noexcept + { + m_value = std::move(rhs); + return *this; + } //! Return non-const value of state variable. - constexpr operator T & () noexcept { return m_value; } + constexpr operator T &() noexcept { return m_value; } //! Return const value of state variable. - constexpr operator const T & () const noexcept { return m_value; } + constexpr operator const T &() const noexcept { return m_value; } //! Return non-const value of state variable. - constexpr T & var() noexcept { return m_value; } + constexpr T &var() noexcept { return m_value; } //! Return const value of state variable. - constexpr const T & var() const noexcept { return m_value; } + constexpr const T &var() const noexcept { return m_value; } //! Return non-const value of state variable. - constexpr T & operator ()() noexcept { return m_value; } + constexpr T &operator()() noexcept { return m_value; } //! Return const value of state variable. - constexpr const T & operator ()() const noexcept { return m_value; } + constexpr const T &operator()() const noexcept { return m_value; } //! Access state variable by ->. - constexpr T * operator->() noexcept { return &m_value; } + constexpr T *operator->() noexcept { return &m_value; } //! Access state variable by const ->. - constexpr const T * operator->() const noexcept{ return &m_value; } + constexpr const T *operator->() const noexcept { return &m_value; } //! Access state variable by *. - constexpr T * operator *() noexcept { return &m_value; } + constexpr T *operator*() noexcept { return &m_value; } //! Access state variable by const *. - constexpr const T * operator *() const noexcept{ return &m_value; } + constexpr const T *operator*() const noexcept { return &m_value; } private: T m_value; }; /// \brief A persistent array template. - /// Use this state_var template to define an array whose contents are saved. - /// Please refer to \ref state_var. + /// Use this state_var template to define an array whose contents are + /// saved. Please refer to \ref state_var. /// /// \tparam C container class to use. @@ -105,24 +114,25 @@ namespace netlist using value_type = typename C::value_type; //! Constructor. template - state_container(O &owner, //!< owner must have a netlist() method. - const pstring &name, //!< identifier/name for this state variable - const value_type &value //!< Initial value after construction - ); + state_container(O & owner, //!< owner must have a netlist() method. + const pstring & name, //!< identifier/name for this state variable + const value_type &value //!< Initial value after construction + ); //! Constructor. template - state_container(O &owner, //!< owner must have a netlist() method. - const pstring &name, //!< identifier/name for this state variable - std::size_t n, //!< number of elements to allocate - const value_type &value //!< Initial value after construction - ); + state_container(O & owner, //!< owner must have a netlist() method. + const pstring & name, //!< identifier/name for this state variable + std::size_t n, //!< number of elements to allocate + const value_type &value //!< Initial value after construction + ); //! Copy Constructor. state_container(const state_container &rhs) noexcept = default; //! Destructor. ~state_container() noexcept = default; //! Move Constructor. state_container(state_container &&rhs) noexcept = default; - state_container &operator=(const state_container &rhs) noexcept = default; + state_container &operator=( + const state_container &rhs) noexcept = default; state_container &operator=(state_container &&rhs) noexcept = default; }; @@ -160,17 +170,17 @@ namespace netlist template template state_container::state_container(O &owner, const pstring &name, - const state_container::value_type & value) + const state_container::value_type &value) { owner.state().save(owner, static_cast(*this), owner.name(), name); - for (std::size_t i=0; i < this->size(); i++) + for (std::size_t i = 0; i < this->size(); i++) (*this)[i] = value; } template template state_container::state_container(O &owner, const pstring &name, - std::size_t n, const state_container::value_type & value) + std::size_t n, const state_container::value_type &value) : C(n, value) { owner.state().save(owner, static_cast(*this), owner.name(), name); @@ -190,7 +200,6 @@ namespace netlist extern template struct state_var; extern template struct state_var; - } // namespace netlist namespace plib diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp index 9d08b4a8220..626a22f7d05 100644 --- a/src/lib/netlist/devices/nld_4020.cpp +++ b/src/lib/netlist/devices/nld_4020.cpp @@ -108,63 +108,11 @@ namespace netlist::devices { nld_power_pins m_supply; }; - NETLIB_OBJECT(CD4020) - { - NETLIB_CONSTRUCTOR_MODEL(CD4020, "CD4XXX") - , m_sub(*this, "A") - { - register_sub_alias("IP", "A.IP"); - register_sub_alias("RESET", "A.RESET"); - register_sub_alias("Q1", "A.Q1"); - register_sub_alias("Q4", "A.Q4"); - register_sub_alias("Q5", "A.Q5"); - register_sub_alias("Q6", "A.Q6"); - register_sub_alias("Q7", "A.Q7"); - register_sub_alias("Q8", "A.Q8"); - register_sub_alias("Q9", "A.Q9"); - register_sub_alias("Q10", "A.Q10"); - register_sub_alias("Q11", "A.Q11"); - register_sub_alias("Q12", "A.Q12"); - register_sub_alias("Q13", "A.Q13"); - register_sub_alias("Q14", "A.Q14"); - register_sub_alias("VDD", "A.VDD"); - register_sub_alias("VSS", "A.VSS"); - } + // FIXME: Exposes Q2 and Q3 as well + using NETLIB_NAME(CD4020_impl) = nld_CD4020_sub<14, 0x3ff9>; + NETLIB_DEVICE_IMPL_ALIAS(CD4020, CD4020_impl,"CD4020", "+IP,+RESET,+VDD,+VSS") - //NETLIB_RESETI() {} - - private: - NETLIB_SUB(CD4020_sub)<14, 0x3ff9> m_sub; - }; - - NETLIB_OBJECT(CD4024) - { - NETLIB_CONSTRUCTOR_MODEL(CD4024, "CD4XXX") - , m_sub(*this, "A") - { - register_sub_alias("IP", "A.IP"); - register_sub_alias("RESET", "A.RESET"); - register_sub_alias("Q1", "A.Q1"); - register_sub_alias("Q2", "A.Q2"); - register_sub_alias("Q3", "A.Q3"); - register_sub_alias("Q4", "A.Q4"); - register_sub_alias("Q5", "A.Q5"); - register_sub_alias("Q6", "A.Q6"); - register_sub_alias("Q7", "A.Q7"); - register_sub_alias("VDD", "A.VDD"); - register_sub_alias("VSS", "A.VSS"); - } - - //NETLIB_RESETI() {} - - private: - NETLIB_SUB(CD4020_sub)<7, 0x7f> m_sub; - }; - - - - NETLIB_DEVICE_IMPL(CD4020, "CD4020", "+IP,+RESET,+VDD,+VSS") - - NETLIB_DEVICE_IMPL(CD4024, "CD4024", "") + using NETLIB_NAME(CD4024_impl) = nld_CD4020_sub<7, 0x7f>; + NETLIB_DEVICE_IMPL_ALIAS(CD4024, CD4024_impl, "CD4024", "") } // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4053.cpp b/src/lib/netlist/devices/nld_4053.cpp index c996ed0c2a5..a199fedf7fc 100644 --- a/src/lib/netlist/devices/nld_4053.cpp +++ b/src/lib/netlist/devices/nld_4053.cpp @@ -101,40 +101,40 @@ namespace netlist::devices { const nl_fptype Roff = plib::reciprocal(exec().gmin()); const nl_fptype RX = newx ? Ron : Roff; const nl_fptype RY = newy ? Ron : Roff; - if (m_RX.solver() == m_RY.solver()) + if (m_RX().solver() == m_RY().solver()) { - m_RX.change_state([this, &RX, &RY]() + m_RX().change_state([this, &RX, &RY]() { - m_RX.set_R(RX); - m_RY.set_R(RY); + m_RX().set_R(RX); + m_RY().set_R(RY); }); } else { - m_RX.change_state([this, &RX]() + m_RX().change_state([this, &RX]() { - m_RX.set_R(RX); + m_RX().set_R(RX); }); - m_RY.change_state([this, &RY]() + m_RY().change_state([this, &RY]() { - m_RY.set_R(RY); + m_RY().set_R(RY); }); } m_last_x = newx; m_last_y = newy; } - analog::NETLIB_SUB(R_base) m_RX; - analog::NETLIB_SUB(R_base) m_RY; - analog_input_t m_select; - analog_input_t m_inhibit; - analog_input_t m_VEE; - param_fp_t m_base_r; - state_var m_last_x; - state_var m_last_y; - state_var m_select_state; - state_var m_inhibit_state; - nld_power_pins m_supply; + NETLIB_SUB_NS(analog, R_base) m_RX; + NETLIB_SUB_NS(analog, R_base) m_RY; + analog_input_t m_select; + analog_input_t m_inhibit; + analog_input_t m_VEE; + param_fp_t m_base_r; + state_var m_last_x; + state_var m_last_y; + state_var m_select_state; + state_var m_inhibit_state; + nld_power_pins m_supply; }; NETLIB_DEVICE_IMPL(CD4053_GATE, "CD4053_GATE", "") diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp index b003dd13178..bd2a0a13196 100644 --- a/src/lib/netlist/devices/nld_4066.cpp +++ b/src/lib/netlist/devices/nld_4066.cpp @@ -42,7 +42,7 @@ namespace netlist::devices { { // Start in off condition // FIXME: is ROFF correct? - m_R.set_R(plib::reciprocal(exec().gmin())); + m_R().set_R(plib::reciprocal(exec().gmin())); } private: @@ -67,11 +67,11 @@ namespace netlist::devices { if (R > nlconst::zero() && (m_last != new_state)) { m_last = new_state; - m_R.change_state([this, &R]() -> void { this->m_R.set_R(R);}); + m_R().change_state([this, &R]() -> void { this->m_R().set_R(R);}); } } - analog::NETLIB_SUB(R_base) m_R; + NETLIB_SUB_NS(analog, R_base) m_R; analog_input_t m_control; param_fp_t m_base_r; state_var m_last; diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp index 81ac77d4468..c875a4e5840 100644 --- a/src/lib/netlist/devices/nld_4316.cpp +++ b/src/lib/netlist/devices/nld_4316.cpp @@ -42,27 +42,27 @@ namespace netlist::devices { NETLIB_RESETI() { - m_R.set_R(plib::reciprocal(exec().gmin())); + m_R().set_R(plib::reciprocal(exec().gmin())); } NETLIB_HANDLERI(inputs) { - m_R.change_state([this]() + m_R().change_state([this]() { if (m_S() && !m_E()) - m_R.set_R(m_base_r()); + m_R().set_R(m_base_r()); else - m_R.set_R(plib::reciprocal(exec().gmin())); + m_R().set_R(plib::reciprocal(exec().gmin())); }); } private: - analog::NETLIB_SUB(R_base) m_R; + NETLIB_SUB_NS(analog, R_base) m_R; - logic_input_t m_S; - logic_input_t m_E; - param_fp_t m_base_r; - nld_power_pins m_supply; + logic_input_t m_S; + logic_input_t m_E; + param_fp_t m_base_r; + nld_power_pins m_supply; }; NETLIB_DEVICE_IMPL(CD4316_GATE, "CD4316_GATE", "") diff --git a/src/lib/netlist/devices/nld_74113.cpp b/src/lib/netlist/devices/nld_74113.cpp index ea2c6d7794a..32f96d87c12 100644 --- a/src/lib/netlist/devices/nld_74113.cpp +++ b/src/lib/netlist/devices/nld_74113.cpp @@ -134,11 +134,7 @@ namespace netlist::devices { nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74113A, 74113) - { - NETLIB_CONSTRUCTOR(74113A) { } - - }; + using NETLIB_NAME(74113A) = NETLIB_NAME(74113); NETLIB_DEVICE_IMPL(74113, "TTL_74113", "+CLK,+J,+K,+CLRQ,@VCC,@GND") NETLIB_DEVICE_IMPL(74113A, "TTL_74113A", "+CLK,+J,+K,+CLRQ,@VCC,@GND") diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp index 81a5d3f9e0d..fc0beef9972 100644 --- a/src/lib/netlist/devices/nld_74123.cpp +++ b/src/lib/netlist/devices/nld_74123.cpp @@ -128,8 +128,8 @@ namespace netlist::devices { connect("RN.1", "RP.2"); connect("_CV", "RN.1"); - m_RP.m_RON.set(D::RI()); - m_RN.m_RON.set(D::RI()); + m_RP().m_RON.set(D::RI()); + m_RN().m_RON.set(D::RI()); } NETLIB_HANDLERI(ab_clear) @@ -169,7 +169,7 @@ namespace netlist::devices { { if (m_state == 1) { - const nl_fptype vLow = m_KP * m_RP.P()(); + const nl_fptype vLow = m_KP * m_RP().P()(); if (m_CV() < vLow) { m_RN_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF @@ -178,7 +178,7 @@ namespace netlist::devices { } if (m_state == 2) { - const nl_fptype vHigh = (nlconst::one() - m_KP) * m_RP.P()(); + const nl_fptype vHigh = (nlconst::one() - m_KP) * m_RP().P()(); if (m_CV() > vHigh) { m_RP_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF @@ -192,8 +192,8 @@ namespace netlist::devices { NETLIB_RESETI() { - m_RP.reset(); - m_RN.reset(); + m_RP().reset(); + m_RN().reset(); //m_RP.set_R(R_OFF); //m_RN.set_R(R_OFF); diff --git a/src/lib/netlist/devices/nld_74174.cpp b/src/lib/netlist/devices/nld_74174.cpp index ed45783f31e..2789eef0bb5 100644 --- a/src/lib/netlist/devices/nld_74174.cpp +++ b/src/lib/netlist/devices/nld_74174.cpp @@ -37,15 +37,15 @@ namespace netlist::devices { - NETLIB_OBJECT(74174_GATE) + NETLIB_OBJECT(74174) { - NETLIB_CONSTRUCTOR(74174_GATE) + NETLIB_CONSTRUCTOR(74174) , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) - , m_Q(*this, "Q") + , m_Q(*this, 1, "Q{}") , m_clrq(*this, "m_clr", 0) , m_data(*this, "m_data", 0) - , m_D(*this, "D", NETLIB_DELEGATE(other)) - , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other)) + , m_D(*this, 1, "D{}", NETLIB_DELEGATE(other)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(clrq)) , m_power_pins(*this) { } @@ -57,22 +57,27 @@ namespace netlist::devices { m_data = 0xFF; } - NETLIB_HANDLERI(other) + private: + NETLIB_HANDLERI(clrq) { - netlist_sig_t d = m_D(); m_clrq = m_CLRQ(); if (!m_clrq) { - m_Q.push(0, NLTIME_FROM_NS(40)); m_data = 0; - } else if (d != m_data) - { - m_data = d; - m_CLK.activate_lh(); + m_Q.push(m_data, NLTIME_FROM_NS(40)); + m_CLK.inactivate(); } + else + m_CLK.activate_lh(); + } + + NETLIB_HANDLERI(other) + { + m_data = m_D(); + if (m_clrq) + m_CLK.activate_lh(); } - private: NETLIB_HANDLERI(clk) { if (m_clrq) @@ -83,82 +88,16 @@ namespace netlist::devices { } logic_input_t m_CLK; - logic_output_t m_Q; + object_array_t m_Q; state_var m_clrq; state_var m_data; - logic_input_t m_D; + object_array_t m_D; logic_input_t m_CLRQ; nld_power_pins m_power_pins; }; - NETLIB_OBJECT(74174) - { - NETLIB_CONSTRUCTOR(74174) - , A(*this, "A") - , B(*this, "B") - , C(*this, "C") - , D(*this, "D") - , E(*this, "E") - , F(*this, "F") - { - register_sub_alias("CLRQ", "A.CLRQ"); - connect("A.CLRQ", "B.CLRQ"); - connect("A.CLRQ", "C.CLRQ"); - connect("A.CLRQ", "D.CLRQ"); - connect("A.CLRQ", "E.CLRQ"); - connect("A.CLRQ", "F.CLRQ"); - - register_sub_alias("CLK", "A.CLK"); - connect("A.CLK", "B.CLK"); - connect("A.CLK", "C.CLK"); - connect("A.CLK", "D.CLK"); - connect("A.CLK", "E.CLK"); - connect("A.CLK", "F.CLK"); - - register_sub_alias("D1", "A.D"); - register_sub_alias("Q1", "A.Q"); - - register_sub_alias("D2", "B.D"); - register_sub_alias("Q2", "B.Q"); - - register_sub_alias("D3", "C.D"); - register_sub_alias("Q3", "C.Q"); - - register_sub_alias("D4", "D.D"); - register_sub_alias("Q4", "D.Q"); - - register_sub_alias("D5", "E.D"); - register_sub_alias("Q5", "E.Q"); - - register_sub_alias("D6", "F.D"); - register_sub_alias("Q6", "F.Q"); - - register_sub_alias("GND", "A.GND"); - connect("A.GND", "B.GND"); - connect("A.GND", "C.GND"); - connect("A.GND", "D.GND"); - connect("A.GND", "E.GND"); - connect("A.GND", "F.GND"); - - register_sub_alias("VCC", "A.VCC"); - connect("A.VCC", "B.VCC"); - connect("A.VCC", "C.VCC"); - connect("A.VCC", "D.VCC"); - connect("A.VCC", "E.VCC"); - connect("A.VCC", "F.VCC"); - } - //NETLIB_RESETI() {} - private: - NETLIB_SUB(74174_GATE) A; - NETLIB_SUB(74174_GATE) B; - NETLIB_SUB(74174_GATE) C; - NETLIB_SUB(74174_GATE) D; - NETLIB_SUB(74174_GATE) E; - NETLIB_SUB(74174_GATE) F; - }; - NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ,@VCC,@GND") } // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7473.cpp b/src/lib/netlist/devices/nld_7473.cpp index 5336bfa85dd..d5b859859a4 100644 --- a/src/lib/netlist/devices/nld_7473.cpp +++ b/src/lib/netlist/devices/nld_7473.cpp @@ -127,10 +127,7 @@ namespace netlist::devices { nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(7473A, 7473) - { - NETLIB_CONSTRUCTOR(7473A) { } - }; + using NETLIB_NAME(7473A) = NETLIB_NAME(7473); NETLIB_DEVICE_IMPL(7473, "TTL_7473", "+CLK,+J,+K,+CLRQ,@VCC,@GND") NETLIB_DEVICE_IMPL(7473A, "TTL_7473A", "+CLK,+J,+K,+CLRQ,@VCC,@GND") diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp index a09d99995a7..11cbc8aeb0d 100644 --- a/src/lib/netlist/devices/nld_74ls629.cpp +++ b/src/lib/netlist/devices/nld_74ls629.cpp @@ -121,8 +121,8 @@ namespace netlist::devices { private: NETLIB_RESETI() { - m_R_FC.set_R( nlconst::magic(90000.0)); - m_R_RNG.set_R(nlconst::magic(90000.0)); + m_R_FC().set_R( nlconst::magic(90000.0)); + m_R_RNG().set_R(nlconst::magic(90000.0)); } NETLIB_UPDATE_PARAMI() @@ -131,8 +131,8 @@ namespace netlist::devices { } SN74LS629clk m_clock; - analog::NETLIB_SUB(R_base) m_R_FC; - analog::NETLIB_SUB(R_base) m_R_RNG; + NETLIB_SUB_NS(analog, R_base) m_R_FC; + NETLIB_SUB_NS(analog, R_base) m_R_RNG; logic_input_t m_ENQ; analog_input_t m_RNG; diff --git a/src/lib/netlist/devices/nld_8277.cpp b/src/lib/netlist/devices/nld_8277.cpp index 424155656f1..c1c59e360fd 100644 --- a/src/lib/netlist/devices/nld_8277.cpp +++ b/src/lib/netlist/devices/nld_8277.cpp @@ -114,8 +114,8 @@ namespace netlist::devices { { if (!m_RESET()) { - m_A.reset_shifter(); - m_B.reset_shifter(); + m_A().reset_shifter(); + m_B().reset_shifter(); } } @@ -123,8 +123,8 @@ namespace netlist::devices { { if (!m_last_CLK && m_CLK()) { - m_A.shift(); - m_B.shift(); + m_A().shift(); + m_B().shift(); } m_last_CLK = m_CLK(); m_last_CLKA = m_CLKA(); @@ -135,7 +135,7 @@ namespace netlist::devices { { if (!m_last_CLKA && m_CLKA()) { - m_A.shift(); + m_A().shift(); } m_last_CLKA = m_CLKA(); } @@ -144,7 +144,7 @@ namespace netlist::devices { { if (!m_last_CLKB && m_CLKB()) { - m_B.shift(); + m_B().shift(); } m_last_CLKB = m_CLKB(); } diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp index ac2edb4f3ff..07b811ab0a9 100644 --- a/src/lib/netlist/devices/nld_am2847.cpp +++ b/src/lib/netlist/devices/nld_am2847.cpp @@ -107,10 +107,10 @@ namespace netlist::devices { { if (m_last_CP && !m_CP()) { - m_A.shift(); - m_B.shift(); - m_C.shift(); - m_D.shift(); + m_A().shift(); + m_B().shift(); + m_C().shift(); + m_D().shift(); } m_last_CP = m_CP(); } diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp index 289eb28e67b..a3dae6a4b39 100644 --- a/src/lib/netlist/devices/nld_log.cpp +++ b/src/lib/netlist/devices/nld_log.cpp @@ -117,6 +117,7 @@ namespace netlist::devices { static constexpr std::size_t BUF_SIZE=16384; static constexpr std::size_t BUFFERS=4; analog_input_t m_I; + private: plib::ofstream m_strm; plib::putf8_writer m_writer; bool m_reset; @@ -129,14 +130,17 @@ namespace netlist::devices { std::thread m_write_thread; }; - NETLIB_OBJECT_DERIVED(logD, log) + class NETLIB_NAME(logD) : public NETLIB_NAME(log) { - NETLIB_CONSTRUCTOR(logD) + public: + NETLIB_NAME(logD)(constructor_param_t data) + : NETLIB_NAME(log)(data) , m_I2(*this, "I2", nl_delegate(&NETLIB_NAME(logD)::input, this)) { m_I.set_delegate(nl_delegate(&NETLIB_NAME(logD)::input, this)); } + private: NETLIB_HANDLERI(input) { log_value(static_cast(m_I() - m_I2())); diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp index b1b78208b64..cd92ce1e5df 100644 --- a/src/lib/netlist/devices/nld_mm5837.cpp +++ b/src/lib/netlist/devices/nld_mm5837.cpp @@ -48,7 +48,7 @@ namespace netlist::devices { { //m_V0.initial(0.0); //m_RV.do_reset(); - m_RV.set_G_V_I(plib::reciprocal(m_R_LOW()), + m_RV().set_G_V_I(plib::reciprocal(m_R_LOW()), nlconst::zero(), nlconst::zero()); m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); @@ -86,15 +86,15 @@ namespace netlist::devices { const nl_fptype R = state ? m_R_HIGH : m_R_LOW; const nl_fptype V = state ? m_VDD() : m_VSS(); - m_RV.change_state([this, &R, &V]() + m_RV().change_state([this, &R, &V]() { - m_RV.set_G_V_I(plib::reciprocal(R), V, nlconst::zero()); + m_RV().set_G_V_I(plib::reciprocal(R), V, nlconst::zero()); }); } } - analog::NETLIB_SUB(two_terminal) m_RV; + NETLIB_SUB_NS(analog, two_terminal) m_RV; analog_input_t m_VDD; analog_input_t m_VGG; analog_input_t m_VSS; diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp index b6b444fe04d..a94d868373d 100644 --- a/src/lib/netlist/devices/nld_ne555.cpp +++ b/src/lib/netlist/devices/nld_ne555.cpp @@ -46,11 +46,11 @@ namespace netlist::devices { NETLIB_RESETI() { /* FIXME make resistances a parameter, properly model other variants */ - m_R1.set_R(nlconst::magic(5000)); - m_R2.set_R(nlconst::magic(5000)); - m_R3.set_R(nlconst::magic(5000)); - m_ROUT.set_R(nlconst::magic(20)); - m_RDIS.set_R(nlconst::magic(R_OFF)); + m_R1().set_R(nlconst::magic(5000)); + m_R2().set_R(nlconst::magic(5000)); + m_R3().set_R(nlconst::magic(5000)); + m_ROUT().set_R(nlconst::magic(20)); + m_RDIS().set_R(nlconst::magic(R_OFF)); m_last_out = true; // Check for astable setup, usually TRIG AND THRES connected. Enable @@ -66,8 +66,8 @@ namespace netlist::devices { const auto reset = m_RESET(); - const nl_fptype v_threshold = clamp_hl(m_R2.P()(), nlconst::magic(0.7), nlconst::magic(1.4)); - const nl_fptype v_trigger = clamp_hl(m_R2.N()(), nlconst::magic(0.7), nlconst::magic(1.4)); + const nl_fptype v_threshold = clamp_hl(m_R2().P()(), nlconst::magic(0.7), nlconst::magic(1.4)); + const nl_fptype v_trigger = clamp_hl(m_R2().N()(), nlconst::magic(0.7), nlconst::magic(1.4)); // avoid artificial oscillation due to overshoot compensation when // the control input is used. @@ -106,11 +106,11 @@ namespace netlist::devices { m_overshoot = plib::clamp(m_overshoot(), nlconst::zero(), overshoot_limit); //if (this->name() == "IC6_2") // printf("%f %s %f %f %f\n", exec().time().as_double(), this->name().c_str(), m_overshoot(), m_R2.P()(), m_THRES()); - m_RDIS.change_state([this]() + m_RDIS().change_state([this]() { - m_RDIS.set_R(nlconst::magic(R_ON)); + m_RDIS().set_R(nlconst::magic(R_ON)); }); - m_OUT.push(m_R3.N()()); + m_OUT.push(m_R3().N()()); } else if (!m_last_out && out) { @@ -121,21 +121,21 @@ namespace netlist::devices { m_undershoot += (v_trigger - m_TRIG()); m_undershoot = plib::clamp(m_undershoot(), nlconst::zero(), overshoot_limit); #endif - m_RDIS.change_state([this]() + m_RDIS().change_state([this]() { - m_RDIS.set_R(nlconst::magic(R_OFF)); + m_RDIS().set_R(nlconst::magic(R_OFF)); }); // FIXME: Should be delayed by 100ns - m_OUT.push(m_R1.P()()); + m_OUT.push(m_R1().P()()); } m_last_reset = reset; m_last_out = out; } - analog::NETLIB_SUB(R_base) m_R1; - analog::NETLIB_SUB(R_base) m_R2; - analog::NETLIB_SUB(R_base) m_R3; - analog::NETLIB_SUB(R_base) m_ROUT; - analog::NETLIB_SUB(R_base) m_RDIS; + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; + NETLIB_SUB_NS(analog, R_base) m_R3; + NETLIB_SUB_NS(analog, R_base) m_ROUT; + NETLIB_SUB_NS(analog, R_base) m_RDIS; logic_input_t m_RESET; analog_input_t m_THRES; @@ -151,7 +151,7 @@ namespace netlist::devices { nl_fptype clamp_hl(const nl_fptype v, const nl_fptype a, const nl_fptype b) noexcept { - const nl_fptype vcc = m_R1.P()(); + const nl_fptype vcc = m_R1().P()(); return plib::clamp(v, b, vcc - a); } }; diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp index e1607536db6..efff78d9ca8 100644 --- a/src/lib/netlist/devices/nld_r2r_dac.cpp +++ b/src/lib/netlist/devices/nld_r2r_dac.cpp @@ -44,14 +44,18 @@ */ #include "nl_base.h" -#include "analog/nlid_twoterm.h" #include "nl_factory.h" -namespace netlist::analog { +#include "analog/nlid_twoterm.h" - NETLIB_OBJECT_DERIVED(r2r_dac, two_terminal) +namespace netlist::analog +{ + + class nld_r2r_dac : public nld_two_terminal { - NETLIB_CONSTRUCTOR(r2r_dac) + public: + nld_r2r_dac(constructor_param_t data) + : nld_two_terminal(data) , m_VIN(*this, "VIN", nlconst::one()) , m_R(*this, "R", nlconst::one()) , m_num(*this, "N", 1) @@ -62,31 +66,28 @@ namespace netlist::analog { } NETLIB_UPDATE_PARAMI(); - //NETLIB_RESETI(); - //NETLIB_UPDATEI(); + // NETLIB_RESETI(); protected: - param_fp_t m_VIN; - param_fp_t m_R; + param_fp_t m_VIN; + param_fp_t m_R; param_int_t m_num; param_int_t m_val; }; - NETLIB_UPDATE_PARAM(r2r_dac) { nl_fptype V = m_VIN() / static_cast(1 << m_num()) - * static_cast(m_val()); - change_state([this, &V]() - { - this->set_G_V_I(plib::reciprocal(m_R()), V, nlconst::zero()); - } - ); + * static_cast(m_val()); + change_state( + [this, &V]() + { this->set_G_V_I(plib::reciprocal(m_R()), V, nlconst::zero()); }); } } // namespace netlist::analog -namespace netlist::devices { +namespace netlist::devices +{ NETLIB_DEVICE_IMPL_NS(analog, r2r_dac, "R2R_DAC", "VIN,R,N") diff --git a/src/lib/netlist/devices/nld_roms.cpp b/src/lib/netlist/devices/nld_roms.cpp index 739039c6c22..024d508497a 100644 --- a/src/lib/netlist/devices/nld_roms.cpp +++ b/src/lib/netlist/devices/nld_roms.cpp @@ -169,9 +169,13 @@ namespace netlist::devices { , m_A(*this, 0, "A{}", NETLIB_DELEGATE(addr)) , m_CEQ(*this, 1, D::chip_enable_mask::value ^ static_cast(0xffff), pstring("CE{}"), - std::array{ NETLIB_DELEGATE(ce<0>), - NETLIB_DELEGATE(ce<1>), - NETLIB_DELEGATE(ce<2>)}) + // Causes a expected primary expression before { with gcc9 + //std::array{NETLIB_DELEGATE(ce<0>), + // NETLIB_DELEGATE(ce<1>), + // NETLIB_DELEGATE(ce<2>)}) + std::array{nl_delegate(& NETLIB_NAME(generic_prom) :: ce<0>, this), + nl_delegate(& NETLIB_NAME(generic_prom) :: ce<1>, this), + nl_delegate(& NETLIB_NAME(generic_prom) :: ce<2>, this)}) , m_O(*this, D::data_name_offset::value, "O{}", m_TE()) , m_ROM(*this, "ROM") , m_power_pins(*this) diff --git a/src/lib/netlist/devices/nld_schmitt.cpp b/src/lib/netlist/devices/nld_schmitt.cpp index f3d3a1e7a57..a6134f3a953 100644 --- a/src/lib/netlist/devices/nld_schmitt.cpp +++ b/src/lib/netlist/devices/nld_schmitt.cpp @@ -66,18 +66,18 @@ namespace netlist::devices { connect("A", "RVI.1"); // FIXME: need a symbolic reference from connect as well - connect(m_supply.GND(), m_RVI.N()); - connect(m_supply.GND(), m_RVO.N()); + connect(m_supply.GND(), m_RVI().N()); + connect(m_supply.GND(), m_RVO().N()); } protected: NETLIB_RESETI() { m_last_state = 1; - m_RVI.reset(); - m_RVO.reset(); - m_RVI.set_G_V_I(plib::reciprocal(m_modacc.m_RI()), m_modacc.m_VI, nlconst::zero()); - m_RVO.set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); + m_RVI().reset(); + m_RVO().reset(); + m_RVI().set_G_V_I(plib::reciprocal(m_modacc.m_RI()), m_modacc.m_VI, nlconst::zero()); + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); } private: @@ -89,9 +89,9 @@ namespace netlist::devices { if (va < m_modacc.m_VTM) { m_last_state = 0; - m_RVO.change_state([this]() + m_RVO().change_state([this]() { - m_RVO.set_G_V_I(plib::reciprocal(m_modacc.m_ROH()), m_modacc.m_VOH, nlconst::zero()); + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROH()), m_modacc.m_VOH, nlconst::zero()); }); } } @@ -100,9 +100,9 @@ namespace netlist::devices { if (va > m_modacc.m_VTP) { m_last_state = 1; - m_RVO.change_state([this]() + m_RVO().change_state([this]() { - m_RVO.set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); }); } } @@ -110,8 +110,8 @@ namespace netlist::devices { analog_input_t m_A; NETLIB_NAME(power_pins) m_supply; - analog::NETLIB_SUB(two_terminal) m_RVI; - analog::NETLIB_SUB(two_terminal) m_RVO; + NETLIB_SUB_NS(analog, two_terminal) m_RVI; + NETLIB_SUB_NS(analog, two_terminal) m_RVO; param_model_t m_stmodel; schmitt_trigger_model_t m_modacc; state_var m_last_state; diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index 96ec987df8e..0ab77e84e7d 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -21,9 +21,9 @@ namespace netlist::devices { static constexpr std::array, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}}; - nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name, + nld_base_proxy::nld_base_proxy(device_param_t data, const logic_t *inout_proxied) - : device_t(anetlist, name, inout_proxied->logic_family()) + : device_t(data, inout_proxied->logic_family()) , m_tp(nullptr) , m_tn(nullptr) { @@ -32,15 +32,14 @@ namespace netlist::devices { throw nl_exception(MF_NULLPTR_FAMILY_NP("nld_base_proxy")); } - bool f = false; for (const auto & pwr_sym : power_syms) { pstring devname = inout_proxied->device().name(); - auto *tp_ct(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.first), + auto *tp_ct(state().setup().find_terminal(devname + "." + pstring(pwr_sym.first), /*detail::terminal_type::INPUT,*/ false)); - auto *tp_cn(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.second), + auto *tp_cn(state().setup().find_terminal(devname + "." + pstring(pwr_sym.second), /*detail::terminal_type::INPUT,*/ false)); if ((tp_ct != nullptr) && (tp_cn != nullptr)) { @@ -49,23 +48,23 @@ namespace netlist::devices { if (!tp_cn->is_analog()) throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_cn->name())); - auto *tp_t = dynamic_cast(tp_ct); - auto *tn_t = dynamic_cast(tp_cn); - if (f && (tp_t != nullptr && tn_t != nullptr)) + auto tp_t = plib::dynamic_downcast(tp_ct); + auto tn_t = plib::dynamic_downcast(tp_cn); + if (f && (tp_t && tn_t)) log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(), m_tp->name(), m_tn->name(), - tp_t != nullptr ? tp_t->name() : "", - tn_t != nullptr ? tn_t->name() : "")); - else if (tp_t != nullptr && tn_t != nullptr) + tp_t ? (*tp_t)->name() : "", + tn_t ? (*tn_t)->name() : "")); + else if (tp_t && tn_t) { - m_tp = tp_t; - m_tn = tn_t; + m_tp = *tp_t; + m_tn = *tn_t; f = true; } } } if (!f) - throw nl_exception(MF_NO_POWER_TERMINALS_ON_DEVICE_2(name, anetlist.setup().de_alias(inout_proxied->device().name()))); + throw nl_exception(MF_NO_POWER_TERMINALS_ON_DEVICE_2(name(), state().setup().de_alias(inout_proxied->device().name()))); log().verbose("D/A Proxy: Found power terminals on device {1}", inout_proxied->device().name()); } @@ -74,14 +73,14 @@ namespace netlist::devices { // nld_a_to_d_proxy // ---------------------------------------------------------------------------------------- - nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, + nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied) - : nld_base_proxy(anetlist, name, in_proxied) + : nld_base_proxy(data, in_proxied) { } - nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *in_proxied) - : nld_base_a_to_d_proxy(anetlist, name, in_proxied) + nld_a_to_d_proxy::nld_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied) + : nld_base_a_to_d_proxy(data, in_proxied) , m_Q(*this, "Q") , m_I(*this, "I", nl_delegate(&nld_a_to_d_proxy::input, this)) { @@ -107,14 +106,14 @@ namespace netlist::devices { // nld_d_to_a_proxy // ---------------------------------------------------------------------------------------- - nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, + nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied) - : nld_base_proxy(anetlist, name, out_proxied) + : nld_base_proxy(data, out_proxied) { } - nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, const logic_output_t *out_proxied) - : nld_base_d_to_a_proxy(anetlist, name, out_proxied) + nld_d_to_a_proxy::nld_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied) + : nld_base_d_to_a_proxy(data, out_proxied) , m_I(*this, "I", nl_delegate(&nld_d_to_a_proxy :: input, this)) , m_RP(*this, "RP") , m_RN(*this, "RN") @@ -122,10 +121,10 @@ namespace netlist::devices { { register_sub_alias("Q", "RN.1"); - connect(m_RN.N(), *m_tn); - connect(m_RP.P(), *m_tp); + connect(m_RN().N(), *m_tn); + connect(m_RP().P(), *m_tp); - connect(m_RN.P(), m_RP.N()); + connect(m_RN().P(), m_RP().N()); } @@ -133,11 +132,11 @@ namespace netlist::devices { { //m_Q.initial(0.0); m_last_state = terminal_t::OUT_TRISTATE(); - m_RN.reset(); - m_RP.reset(); - m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()), + m_RN().reset(); + m_RP().reset(); + m_RN().set_G_V_I(plib::reciprocal(logic_family()->R_low()), logic_family()->low_offset_V(), nlconst::zero()); - m_RP.set_G_V_I(G_OFF, + m_RP().set_G_V_I(G_OFF, nlconst::zero(), nlconst::zero()); } @@ -148,29 +147,29 @@ namespace netlist::devices { if (state != m_last_state) { // RN, RP are connected ... - m_RN.change_state([this, &state]() + m_RN().change_state([this, &state]() { switch (state) { case 0: - m_RN.set_G_V_I(plib::reciprocal(logic_family()->R_low()), + m_RN().set_G_V_I(plib::reciprocal(logic_family()->R_low()), logic_family()->low_offset_V(), nlconst::zero()); - m_RP.set_G_V_I(G_OFF, + m_RP().set_G_V_I(G_OFF, nlconst::zero(), nlconst::zero()); break; case 1: - m_RN.set_G_V_I(G_OFF, + m_RN().set_G_V_I(G_OFF, nlconst::zero(), nlconst::zero()); - m_RP.set_G_V_I(plib::reciprocal(logic_family()->R_high()), + m_RP().set_G_V_I(plib::reciprocal(logic_family()->R_high()), logic_family()->high_offset_V(), nlconst::zero()); break; case terminal_t::OUT_TRISTATE(): - m_RN.set_G_V_I(G_OFF, + m_RN().set_G_V_I(G_OFF, nlconst::zero(), nlconst::zero()); - m_RP.set_G_V_I(G_OFF, + m_RP().set_G_V_I(G_OFF, nlconst::zero(), nlconst::zero()); break; diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h index aea5b6f11d8..0f1b2ffeacd 100644 --- a/src/lib/netlist/devices/nlid_proxy.h +++ b/src/lib/netlist/devices/nlid_proxy.h @@ -25,8 +25,7 @@ namespace netlist::devices { class nld_base_proxy : public device_t { public: - nld_base_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_t *inout_proxied); + nld_base_proxy(device_param_t data, const logic_t *inout_proxied); // only used during setup virtual detail::core_terminal_t &proxy_term() noexcept = 0; @@ -49,16 +48,14 @@ namespace netlist::devices { virtual logic_output_t &out() noexcept = 0; protected: - nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_input_t *in_proxied); + nld_base_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied); }; class nld_a_to_d_proxy : public nld_base_a_to_d_proxy { public: - nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_input_t *in_proxied); + nld_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied); logic_output_t &out() noexcept override { return m_Q; } @@ -87,22 +84,20 @@ namespace netlist::devices { virtual logic_input_t &in() noexcept = 0; protected: - nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_output_t *out_proxied); + nld_base_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied); }; class nld_d_to_a_proxy : public nld_base_d_to_a_proxy { public: - nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, - const logic_output_t *out_proxied); + nld_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied); logic_input_t &in() noexcept override { return m_I; } detail::core_terminal_t &proxy_term() noexcept override { - return m_RN.setup_P(); + return m_RN().setup_P(); } protected: @@ -115,8 +110,8 @@ namespace netlist::devices { static constexpr const nl_fptype G_OFF = nlconst::cgmin(); logic_input_t m_I; - analog::NETLIB_NAME(two_terminal) m_RP; - analog::NETLIB_NAME(two_terminal) m_RN; + NETLIB_SUB_NS(analog, two_terminal) m_RP; + NETLIB_SUB_NS(analog, two_terminal) m_RN; state_var m_last_state; }; diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index c87bbcfbd9b..fee4fad0333 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -84,7 +84,7 @@ namespace netlist::devices { for (std::uint64_t i=0; i < m_N(); i++) { pstring input_name = plib::pfmt("A{1}")(i); - m_I.push_back(owner.template make_pool_object(*this, input_name, NETLIB_DELEGATE(fb))); + m_I.push_back(state().make_pool_object(*this, input_name, NETLIB_DELEGATE(fb))); inputs.push_back(input_name); m_vals.push_back(nlconst::zero()); } @@ -303,7 +303,7 @@ namespace netlist::devices { for (uint64_t i=0; i < m_N(); i++) { pstring input_name = plib::pfmt("A{1}")(i); - m_I.push_back(owner.template make_pool_object(*this, input_name, NETLIB_DELEGATE(inputs))); + m_I.push_back(state().make_pool_object(*this, input_name, NETLIB_DELEGATE(inputs))); inputs.push_back(input_name); m_values.push_back(nlconst::zero()); } @@ -364,15 +364,15 @@ namespace netlist::devices { NETLIB_RESETI() { m_last_state = 0; - m_R.set_R(m_ROFF()); + m_R().set_R(m_ROFF()); } //NETLIB_UPDATE_PARAMI(); //FIXME: used by 74123 - const terminal_t &P() const noexcept { return m_R.P(); } - const terminal_t &N() const noexcept { return m_R.N(); } + const terminal_t &P() const noexcept { return m_R().P(); } + const terminal_t &N() const noexcept { return m_R().N(); } const logic_input_t &I() const noexcept { return m_I; } param_fp_t m_RON; @@ -387,14 +387,14 @@ namespace netlist::devices { m_last_state = state; const nl_fptype R = (state != 0) ? m_RON() : m_ROFF(); - m_R.change_state([this, &R]() + m_R().change_state([this, &R]() { - m_R.set_R(R); + m_R().set_R(R); }); } } - analog::NETLIB_SUB(R_base) m_R; + NETLIB_SUB_NS(analog, R_base) m_R; logic_input_t m_I; state_var m_last_state; @@ -424,8 +424,8 @@ namespace netlist::devices { private: NETLIB_RESETI() { - m_R1.set_G(m_GOFF()); - m_R2.set_G(m_GON()); + m_R1().set_G(m_GOFF()); + m_R2().set_G(m_GON()); } //NETLIB_UPDATE_PARAMI(); @@ -437,29 +437,29 @@ namespace netlist::devices { //printf("Here %d\n", state); const nl_fptype G1 = (state != 0) ? m_GON() : m_GOFF(); const nl_fptype G2 = (state != 0) ? m_GOFF() : m_GON(); - if (m_R1.solver() == m_R2.solver()) + if (m_R1().solver() == m_R2().solver()) { - m_R1.change_state([this, &G1, &G2]() + m_R1().change_state([this, &G1, &G2]() { - m_R1.set_G(G1); - m_R2.set_G(G2); + m_R1().set_G(G1); + m_R2().set_G(G2); }); } else { - m_R1.change_state([this, &G1]() + m_R1().change_state([this, &G1]() { - m_R1.set_G(G1); + m_R1().set_G(G1); }); - m_R2.change_state([this, &G2]() + m_R2().change_state([this, &G2]() { - m_R2.set_G(G2); + m_R2().set_G(G2); }); } } - analog::NETLIB_SUB(R_base) m_R1; - analog::NETLIB_SUB(R_base) m_R2; + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; logic_input_t m_I; param_fp_t m_GON; param_fp_t m_GOFF; @@ -570,18 +570,18 @@ namespace netlist::devices { NETLIB_HANDLERI(input) { nl_fptype val = m_dis()(m_mt()); - m_T.change_state([this, val]() + m_T().change_state([this, val]() { - m_T.set_G_V_I(plib::reciprocal(m_RI()), val, nlconst::zero()); + m_T().set_G_V_I(plib::reciprocal(m_RI()), val, nlconst::zero()); }); } NETLIB_RESETI() { - m_T.set_G_V_I(plib::reciprocal(m_RI()), nlconst::zero(), nlconst::zero()); + m_T().set_G_V_I(plib::reciprocal(m_RI()), nlconst::zero(), nlconst::zero()); } - analog::NETLIB_SUB(two_terminal) m_T; + NETLIB_SUB_NS(analog, two_terminal) m_T; logic_input_t m_I; param_fp_t m_RI; param_fp_t m_sigma; diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 0f68517cb1f..072fa148d75 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -36,11 +36,9 @@ namespace netlist::devices { std::array m_timing_nt; }; - template - nld_truth_table_t(C &owner, const pstring &name, - const pstring &model, + nld_truth_table_t(device_param_t data, const pstring &model, truth_table_t &ttp, const std::vector &desc) - : device_t(owner, name, model) + : device_t(data, model) #if NL_USE_TT_ALTERNATIVE , m_state(*this, "m_state", 0) #endif @@ -272,8 +270,8 @@ namespace netlist::devices { return ret; } - static constexpr const pbitset all_bits() noexcept { return pbitset(~static_cast(0)); } - static constexpr const pbitset no_bits() noexcept{ return pbitset(static_cast(0)); } + static constexpr pbitset all_bits() noexcept { return pbitset(~static_cast(0)); } + static constexpr pbitset no_bits() noexcept{ return pbitset(static_cast(0)); } private: T m_bs; }; @@ -414,7 +412,7 @@ namespace netlist::devices { // Connect output "Q" to input "_Q" if this exists // This enables timed state without having explicit state .... pstring tmp = "_" + outputs[i]; - const std::size_t idx = plib::container::indexof(inout, tmp); + const std::size_t idx = plib::container::index_of(inout, tmp); if (idx != plib::container::npos) connect(m_Q[i], m_I[idx]); } @@ -426,10 +424,10 @@ namespace netlist::devices { // ---------------------------------------------------------------------------------------- template - class netlist_factory_truth_table_t : public factory::truth_table_base_element_t + class factory_truth_table_t : public factory::truth_table_base_element_t { public: - netlist_factory_truth_table_t(const pstring &name, + factory_truth_table_t(const pstring &name, factory::properties &&props) : truth_table_base_element_t(name, std::move(props)) { } @@ -448,7 +446,7 @@ namespace netlist::devices { desc_s.parse(m_desc); } - return plib::make_unique(pool, anetlist, name, m_family_name, *m_table, m_desc); + return plib::make_unique(pool, device_data_t{anetlist, name}, m_family_name, *m_table, m_desc); } private: device_arena::unique_ptr::truth_table_t> m_table; @@ -667,7 +665,7 @@ namespace netlist::factory { } #define ENTRYY(n, m, s) case (n * 100 + m): \ - { using dev_type = devices::netlist_factory_truth_table_t; \ + { using dev_type = devices::factory_truth_table_t; \ auto cs=s; \ ret = plib::make_unique(desc.name, std::move(cs)); } \ break diff --git a/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp b/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp index 707d57cfd9f..c918d5015e6 100644 --- a/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp +++ b/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp @@ -21,6 +21,7 @@ //- +---+---++---+ //- static NETLIST_START(TTL_7400_DIP) +{ TTL_7400_NAND(A) TTL_7400_NAND(B) TTL_7400_NAND(C) @@ -39,6 +40,7 @@ static NETLIST_START(TTL_7400_DIP) A.GND, /* GND |7 8| Y3 */ C.Q /* +--------------+ */ ) +} NETLIST_END() //- Identifier: TTL_7402_DIP @@ -2091,20 +2093,15 @@ NETLIST_END() //- static NETLIST_START(TTL_74174_DIP) TTL_74174(A) - TTL_74174(B) - TTL_74174(C) - TTL_74174(D) - TTL_74174(E) - TTL_74174(F) DIPPINS( /* +--------------+ */ - A.CLRQ, /* CLRQ |1 ++ 16| VCC */ A.VCC, - A.Q, /* Q1 |2 15| Q6 */ F.Q, - A.D, /* D1 |3 14| D6 */ F.D, - B.D, /* D2 |4 74174 13| D5 */ E.D, - B.Q, /* Q2 |5 12| Q5 */ E.Q, - C.D, /* D3 |6 11| D4 */ D.D, - C.Q, /* Q3 |7 10| Q4 */ D.Q, + A.CLRQ, /* CLRQ |1 ++ 16| VCC */ A.VCC + A.Q1, /* Q1 |2 15| Q6 */ A.Q6, + A.D1, /* D1 |3 14| D6 */ A.D6, + A.D2, /* D2 |4 74174 13| D5 */ A.D5, + A.Q2, /* Q2 |5 12| Q5 */ A.Q5, + A.D3, /* D3 |6 11| D4 */ A.D4, + A.Q3, /* Q3 |7 10| Q4 */ A.Q4, A.GND, /* GND |8 9| CLK */ A.CLK /* +--------------+ */ ) @@ -3147,6 +3144,7 @@ static TRUTHTABLE_START(TTL_74279B, 4, 1, "") TRUTHTABLE_END() static TRUTHTABLE_START(TTL_9312, 12, 2, "+A,+B,+C,+G,+D0,+D1,+D2,+D3,+D4,+D5,+D6,+D7,@VCC,@GND") +{ TT_HEAD(" C, B, A, G,D0,D1,D2,D3,D4,D5,D6,D7| Y,YQ") TT_LINE(" X, X, X, 1, X, X, X, X, X, X, X, X| 0, 1|33,19") TT_LINE(" 0, 0, 0, 0, 0, X, X, X, X, X, X, X| 0, 1|33,28") @@ -3166,6 +3164,7 @@ static TRUTHTABLE_START(TTL_9312, 12, 2, "+A,+B,+C,+G,+D0,+D1,+D2,+D3,+D4,+D5,+D TT_LINE(" 1, 1, 1, 0, X, X, X, X, X, X, X, 0| 0, 1|33,28") TT_LINE(" 1, 1, 1, 0, X, X, X, X, X, X, X, 1| 1, 0|33,28") TT_FAMILY("74XX") +} TRUTHTABLE_END() NETLIST_START(ttl74xx_lib) diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index c60162efb0c..96790951b33 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -1,6 +1,14 @@ // license:BSD-3-Clause // copyright-holders:Couriersud +#include "nl_errstr.h" + +#include "core/devices.h" +#include "core/logic.h" +#include "core/setup.h" + +#include "devices/nlid_proxy.h" + #include "solver/nld_matrix_solver.h" #include "solver/nld_solver.h" @@ -10,13 +18,6 @@ #include "plib/pmempool.h" #include "plib/putil.h" -#include "core/devices.h" -#include "core/logic.h" -#include "core/setup.h" -#include "devices/nlid_proxy.h" - -#include "nl_errstr.h" - #include NETLIST_EXTERNAL(base_lib) @@ -24,31 +25,32 @@ NETLIST_EXTERNAL(base_lib) namespace netlist { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // detail::core_terminal_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- detail::terminal_type detail::core_terminal_t::type() const noexcept(false) { - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return terminal_type::TERMINAL; - if (dynamic_cast(this) != nullptr - || dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this) + || plib::dynamic_downcast(this)) return terminal_type::INPUT; - if (dynamic_cast(this) != nullptr - || dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this) + || plib::dynamic_downcast(this)) return terminal_type::OUTPUT; state().log().fatal(MF_UNKNOWN_TYPE_FOR_OBJECT(name())); throw nl_exception(MF_UNKNOWN_TYPE_FOR_OBJECT(name())); - //return terminal_type::TERMINAL; // please compiler + // return terminal_type::TERMINAL; // please compiler } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // detail::device_object_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - detail::device_object_t::device_object_t(core_device_t *dev, const pstring &aname) + detail::device_object_t::device_object_t(core_device_t *dev, + const pstring & aname) : object_t(aname) , m_device(dev) { @@ -64,23 +66,23 @@ namespace netlist return m_device->state(); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // detail::netlist_object_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - netlist_state_t & detail::netlist_object_t::state() noexcept + netlist_state_t &detail::netlist_object_t::state() noexcept { return m_netlist.nl_state(); } - const netlist_state_t & detail::netlist_object_t::state() const noexcept + const netlist_state_t &detail::netlist_object_t::state() const noexcept { return m_netlist.nl_state(); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // netlist_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- netlist_t::netlist_t(netlist_state_t &state, const pstring &aname) : m_state(state) @@ -89,28 +91,33 @@ namespace netlist , m_main_clock(nullptr) , m_use_stats(false) , m_queue(state.pool(), config::max_queue_size::value, - detail::queue_t::id_delegate(&netlist_state_t :: find_net_id, &state), - detail::queue_t::obj_delegate(&netlist_state_t :: net_by_id, &state)) + detail::queue_t::id_delegate(&netlist_state_t ::find_net_id, &state), + detail::queue_t::obj_delegate(&netlist_state_t ::net_by_id, &state)) { - state.save(*this, static_cast(m_queue), aname, "m_queue"); + state.save(*this, + static_cast(m_queue), aname, + "m_queue"); state.save(*this, m_time, aname, "m_time"); } void netlist_t::reset() { log().debug("Searching for main clock\n"); - m_main_clock = m_state.get_single_device("mainclock"); + m_main_clock = m_state + .get_single_device( + "mainclock"); log().debug("Searching for solver\n"); - m_solver = m_state.get_single_device("solver"); + m_solver = m_state.get_single_device( + "solver"); // Don't reset time - //m_time = netlist_time_ext::zero(); + // m_time = netlist_time_ext::zero(); m_queue.clear(); if (m_main_clock != nullptr) m_main_clock->m_Q.net().set_next_scheduled_time(m_time); - //if (m_solver != nullptr) - // m_solver->reset(); + // if (m_solver != nullptr) + // m_solver->reset(); m_state.reset(); } @@ -128,19 +135,22 @@ namespace netlist { if (m_use_stats) { - netlist_state_t::stats_info si{m_queue, m_stat_mainloop, m_perf_out_processed}; + netlist_state_t::stats_info si{m_queue, m_stat_mainloop, + m_perf_out_processed}; m_state.print_stats(si); } - log().verbose("Current pool memory allocated: {1:12} kB", nl_state().pool().cur_alloc() >> 10); - log().verbose("Maximum pool memory allocated: {1:12} kB", nl_state().pool().max_alloc() >> 10); + log().verbose("Current pool memory allocated: {1:12} kB", + nl_state().pool().cur_alloc() >> 10); + log().verbose("Maximum pool memory allocated: {1:12} kB", + nl_state().pool().max_alloc() >> 10); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // netlist_state_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- netlist_state_t::netlist_state_t(const pstring &name, - plib::plog_delegate logger) + plib::plog_delegate logger) : m_log(logger) , m_dummy_version(1) { @@ -156,47 +166,59 @@ namespace netlist devices::initialize_factory(m_setup->parser().factory()); // Add default include file - const pstring content = - "#define RES_R(res) (res) \n" - "#define RES_K(res) ((res) * 1e3) \n" - "#define RES_M(res) ((res) * 1e6) \n" - "#define CAP_U(cap) ((cap) * 1e-6) \n" - "#define CAP_N(cap) ((cap) * 1e-9) \n" - "#define CAP_P(cap) ((cap) * 1e-12) \n" - "#define IND_U(ind) ((ind) * 1e-6) \n" - "#define IND_N(ind) ((ind) * 1e-9) \n" - "#define IND_P(ind) ((ind) * 1e-12) \n"; - m_setup->parser().add_include("netlist/devices/net_lib.h", content); + const pstring content + = "#define RES_R(res) (res) \n" + "#define RES_K(res) ((res) * 1e3) \n" + "#define RES_M(res) ((res) * 1e6) \n" + "#define CAP_U(cap) ((cap) * 1e-6) \n" + "#define CAP_N(cap) ((cap) * 1e-9) \n" + "#define CAP_P(cap) ((cap) * 1e-12) \n" + "#define IND_U(ind) ((ind) * 1e-6) \n" + "#define IND_N(ind) ((ind) * 1e-9) \n" + "#define IND_P(ind) ((ind) * 1e-12) \n"; + m_setup->parser().add_include( + "netlist/devices/net_lib.h", content); // This is for core macro libraries - m_setup->parser().add_include("devices/net_lib.h", content); + m_setup->parser().add_include("devices/net_lib.h", + content); #if 1 NETLIST_NAME(base_lib)(m_setup->parser()); //#m_setup->parser().register_source("../macro/modules/nlmod_{1}.cpp"); //#m_setup->parser().register_source("../macro/nlm_{1}.cpp"); #else -#if 1 + #if 1 pstring dir = "src/lib/netlist/"; - m_setup->parser().register_source(dir + "/macro/nlm_{1}.cpp", true); - m_setup->parser().register_source(dir + "/generated/nlm_{1}.cpp", true); - m_setup->parser().register_source(dir + "/macro/modules/nlmod_{1}.cpp", true); + m_setup->parser().register_source( + dir + "/macro/nlm_{1}.cpp", true); + m_setup->parser().register_source( + dir + "/generated/nlm_{1}.cpp", true); + m_setup->parser().register_source( + dir + "/macro/modules/nlmod_{1}.cpp", true); m_setup->parser().include("base_lib"); -#else + #else // FIXME: This is very slow - need optimized parsing scanning pstring dir = "src/lib/netlist/macro/"; - //m_setup->parser().register_source("src/lib/netlist/macro/nlm_{}.cpp"); - m_setup->parser().register_source(dir + "nlm_base_lib.cpp"); - m_setup->parser().register_source(dir + "nlm_opamp_lib.cpp"); - m_setup->parser().register_source(dir + "nlm_roms_lib.cpp"); - m_setup->parser().register_source(dir + "nlm_cd4xxx_lib.cpp"); - m_setup->parser().register_source(dir + "nlm_otheric_lib.cpp"); - m_setup->parser().register_source(dir + "nlm_ttl74xx_lib.cpp"); + // m_setup->parser().register_source("src/lib/netlist/macro/nlm_{}.cpp"); + m_setup->parser().register_source( + dir + "nlm_base_lib.cpp"); + m_setup->parser().register_source( + dir + "nlm_opamp_lib.cpp"); + m_setup->parser().register_source( + dir + "nlm_roms_lib.cpp"); + m_setup->parser().register_source( + dir + "nlm_cd4xxx_lib.cpp"); + m_setup->parser().register_source( + dir + "nlm_otheric_lib.cpp"); + m_setup->parser().register_source( + dir + "nlm_ttl74xx_lib.cpp"); m_setup->parser().include("base_lib"); -#endif + #endif #endif } - void netlist_state_t::set_static_solver_lib(std::unique_ptr &&lib) + void netlist_state_t::set_static_solver_lib( + std::unique_ptr &&lib) { m_lib = std::move(lib); } @@ -225,16 +247,20 @@ namespace netlist void netlist_state_t::rebuild_lists() { - for (auto & net : m_nets) + for (auto &net : m_nets) net->rebuild_list(); } - void netlist_state_t::compile_defines(std::vector> &defs) + void netlist_state_t::compile_defines( + std::vector> &defs) { - #define ENTRY(x) if (pstring(#x) != PSTRINGIFY(x)) \ - defs.emplace_back(std::pair(#x, PSTRINGIFY(x))); \ - else defs.emplace_back(std::pair(#x, "")); - #define ENTRY_EX(x) defs.emplace_back(std::pair(#x, plib::pfmt("{}")(x))); +#define ENTRY(x) \ + if (pstring(#x) != PSTRINGIFY(x)) \ + defs.emplace_back(std::pair(#x, PSTRINGIFY(x))); \ + else \ + defs.emplace_back(std::pair(#x, "")); +#define ENTRY_EX(x) \ + defs.emplace_back(std::pair(#x, plib::pfmt("{}")(x))); ENTRY(NL_VERSION_MAJOR) ENTRY(NL_VERSION_MINOR) ENTRY(NL_VERSION_PATCHLEVEL) @@ -267,10 +293,10 @@ namespace netlist ENTRY(__clang_patchlevel__) ENTRY(__clang_version__) - ENTRY(OPENMP ) - ENTRY(_OPENMP ) + ENTRY(OPENMP) + ENTRY(_OPENMP) - ENTRY(__x86_64__ ) + ENTRY(__x86_64__) ENTRY(__i386__) ENTRY(_WIN32) ENTRY(_MSC_VER) @@ -295,8 +321,8 @@ namespace netlist ENTRY(PPMF_FORCE_TYPE) ENTRY(PHAS_PMF_INTERNAL) - #undef ENTRY - #undef ENTRY_EX +#undef ENTRY +#undef ENTRY_EX } pstring netlist_state_t::version() @@ -306,24 +332,22 @@ namespace netlist pstring netlist_state_t::version_patchlevel() { - return plib::pfmt("{1}.{2}.{3}")(NL_VERSION_MAJOR, NL_VERSION_MINOR, NL_VERSION_PATCHLEVEL); + return plib::pfmt("{1}.{2}.{3}")(NL_VERSION_MAJOR, NL_VERSION_MINOR, + NL_VERSION_PATCHLEVEL); } - void netlist_state_t::free_setup_resources() - { - m_setup = nullptr; - } + void netlist_state_t::free_setup_resources() { m_setup = nullptr; } void netlist_state_t::reset() { // Reset all nets once ! log().verbose("Call reset on all nets:"); - for (auto & n : nets()) + for (auto &n : nets()) n->reset(); // Reset all devices once ! log().verbose("Call reset on all devices:"); - for (auto & dev : m_devices) + for (auto &dev : m_devices) dev.second->reset(); // Make sure everything depending on parameters is set @@ -332,7 +356,7 @@ namespace netlist std::vector devices_called; log().verbose("Call update_param on all devices:"); - for (auto & dev : m_devices) + for (auto &dev : m_devices) { dev.second->update_param(); if (!plib::container::contains(devices_called, dev.second.get())) @@ -344,7 +368,8 @@ namespace netlist // INFO: The order here affects power up of e.g. breakout. However, such // variations are explicitly stated in the breakout manual. - auto *netlist_params = get_single_device("parameter"); + auto *netlist_params = get_single_device< + devices::NETLIB_NAME(netlistparams)>("parameter"); switch (netlist_params->m_startup_strategy()) { @@ -354,8 +379,9 @@ namespace netlist log().verbose("Using default startup strategy"); for (auto &n : m_nets) { - n->update_inputs(); // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1 - for (detail::core_terminal_t * term : n->core_terms_copy()) + n->update_inputs(); // only used if + // USE_COPY_INSTEAD_OF_REFERENCE == 1 + for (detail::core_terminal_t *term : n->core_terms_copy()) { if (!plib::container::contains(t, &term->delegate())) { @@ -363,19 +389,22 @@ namespace netlist term->run_delegate(); } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - auto *dev = reinterpret_cast(term->delegate().object()); + auto *dev = reinterpret_cast( + term->delegate().object()); if (!plib::container::contains(devices_called, dev)) devices_called.push_back(dev); } } log().verbose("Devices not yet updated:"); for (auto &dev : m_devices) - if (!plib::container::contains(devices_called, dev.second.get())) + if (!plib::container::contains(devices_called, + dev.second.get())) { // FIXME: doesn't seem to be needed, use cases include // analog output devices. Check and remove - log().error("\t Device {1} not yet updated", dev.second->name()); - //dev.second->update(); + log().error("\t Device {1} not yet updated", + dev.second->name()); + // dev.second->update(); } } break; @@ -383,40 +412,52 @@ namespace netlist // the above may screw up m_active and the list rebuild_lists(); - } void netlist_state_t::print_stats(stats_info &si) const { std::vector index; - for (size_t i=0; i < this->m_devices.size(); i++) + for (size_t i = 0; i < this->m_devices.size(); i++) index.push_back(i); std::sort(index.begin(), index.end(), - [&](size_t i1, size_t i2) { return this->m_devices[i1].second->stats()->m_stat_total_time.total() < this->m_devices[i2].second->stats()->m_stat_total_time.total(); }); + [&](size_t i1, size_t i2) + { + return this->m_devices[i1] + .second->stats() + ->m_stat_total_time.total() + < this->m_devices[i2] + .second->stats() + ->m_stat_total_time.total(); + }); - plib::pperftime_t::type total_time(0); + plib::pperftime_t::type total_time(0); plib::pperftime_t::ctype total_count(0); - for (auto & j : index) + for (auto &j : index) { auto *entry = this->m_devices[j].second.get(); auto *stats = entry->stats(); - log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(), - stats->m_stat_call_count(), stats->m_stat_total_time.count(), - stats->m_stat_total_time.total(), stats->m_stat_inc_active()); + log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", + entry->name(), stats->m_stat_call_count(), + stats->m_stat_total_time.count(), + stats->m_stat_total_time.total(), stats->m_stat_inc_active()); total_time += stats->m_stat_total_time.total(); total_count += stats->m_stat_total_time.count(); } log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count, - total_time, total_time / gsl::narrow((total_count > 0) ? total_count : 1)); + total_time, + total_time + / gsl::narrow( + (total_count > 0) ? total_count : 1)); log().verbose("Total loop {1:15}", si.m_stat_mainloop()); log().verbose("Total time {1:15}", total_time); // FIXME: clang complains about unreachable code without - const bool clang_workaround_unreachable_code(config::use_queue_stats::value); + const bool clang_workaround_unreachable_code( + config::use_queue_stats::value); if (clang_workaround_unreachable_code) { // Only one serialization should be counted in total time @@ -425,26 +466,32 @@ namespace netlist plib::pperftime_t test; { auto overhead_guard(overhead.guard()); - for (int j=0; j<100000;j++) + for (int j = 0; j < 100000; j++) { auto test_guard(test.guard()); } } - plib::pperftime_t::type total_overhead = overhead() - * gsl::narrow::type>(total_count) - / gsl::narrow::type>(200000); + plib::pperftime_t::type total_overhead + = overhead() + * gsl::narrow::type>(total_count) + / gsl::narrow::type>(200000); log().verbose("Queue Pushes {1:15}", si.m_queue.m_prof_call()); - log().verbose("Queue Moves {1:15}", si.m_queue.m_prof_sort_move()); + log().verbose("Queue Moves {1:15}", + si.m_queue.m_prof_sort_move()); log().verbose("Queue Removes {1:15}", si.m_queue.m_prof_remove()); log().verbose(""); - log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation."); + log().verbose( + "Take the next lines with a grain of salt. They depend on the measurement implementation."); log().verbose("Total overhead {1:15}", total_overhead); - plib::pperftime_t::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) - / gsl::narrow::type>(si.m_queue.m_prof_call()); - log().verbose("Overhead per pop {1:11}", overhead_per_pop ); + plib::pperftime_t::type overhead_per_pop + = (si.m_stat_mainloop() - 2 * total_overhead + - (total_time - total_overhead)) + / gsl::narrow::type>( + si.m_queue.m_prof_call()); + log().verbose("Overhead per pop {1:11}", overhead_per_pop); log().verbose(""); } @@ -454,16 +501,21 @@ namespace netlist auto *ep = entry.second.get(); auto *stats = ep->stats(); // Factor of 3 offers best performance increase - if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count() + if (stats->m_stat_inc_active() + > 3 * stats->m_stat_total_time.count() && stats->m_stat_inc_active() > trigger) log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(), - gsl::narrow(stats->m_stat_inc_active()) / gsl::narrow(stats->m_stat_total_time.count()), - stats->m_stat_inc_active(), stats->m_stat_total_time.count()); + gsl::narrow(stats->m_stat_inc_active()) + / gsl::narrow( + stats->m_stat_total_time.count()), + stats->m_stat_inc_active(), + stats->m_stat_total_time.count()); } log().verbose(""); } - core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const + core_device_t *netlist_state_t::get_single_device(const pstring &classname, + bool (*cc)(core_device_t *)) const { core_device_t *ret = nullptr; for (const auto &d : m_devices) @@ -473,7 +525,8 @@ namespace netlist if (ret != nullptr) { m_log.fatal(MF_MORE_THAN_ONE_1_DEVICE_FOUND(classname)); - throw nl_exception(MF_MORE_THAN_ONE_1_DEVICE_FOUND(classname)); + throw nl_exception( + MF_MORE_THAN_ONE_1_DEVICE_FOUND(classname)); } ret = d.second.get(); } @@ -481,8 +534,11 @@ namespace netlist return ret; } - nlparse_t &netlist_state_t::parser() { return m_setup->parser(); } - const nlparse_t &netlist_state_t::parser() const { return m_setup->parser(); } + nlparse_t &netlist_state_t::parser() noexcept { return m_setup->parser(); } + const nlparse_t &netlist_state_t::parser() const noexcept + { + return m_setup->parser(); + } void netlist_state_t::remove_device(core_device_t *dev) { @@ -495,50 +551,32 @@ namespace netlist } } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // core_device_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - core_device_t::core_device_t(netlist_state_t &owner, const pstring &name) - : netlist_object_t(owner.exec(), name) - , m_hint_deactivate(false) - , m_active_outputs(*this, "m_active_outputs", 1) + core_device_t::core_device_t(core_device_param_t data) + : netlist_object_t(data.owner.exec(), data.name) + , m_hint_deactivate(false) + , m_active_outputs(*this, "m_active_outputs", 1) { if (exec().stats_enabled()) - m_stats = owner.make_pool_object(); + m_stats = state().make_pool_object(); } - core_device_t::core_device_t(core_device_t &owner, const pstring &name) - : netlist_object_t(owner.state().exec(), owner.name() + "." + name) - , m_hint_deactivate(false) - , m_active_outputs(*this, "m_active_outputs", 1) - { - //printf("owned device: %s\n", this->name().c_str()); - owner.state().register_device(this->name(), device_arena::owned_ptr(this, false)); - if (exec().stats_enabled()) - m_stats = owner.state().make_pool_object(); - } + log_type &core_device_t::log() { return state().log(); } - log_type & core_device_t::log() - { - return state().log(); - } - - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // base_device_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - base_device_t::base_device_t(netlist_state_t &owner, const pstring &name) - : core_device_t(owner, name) + base_device_t::base_device_t(base_device_param_t data) + : core_device_t(data) { } - base_device_t::base_device_t(base_device_t &owner, const pstring &name) - : core_device_t(owner, name) - { - } - - void base_device_t::register_sub_alias(const pstring &name, const detail::core_terminal_t &term) + void base_device_t::register_sub_alias(const pstring &name, + const detail::core_terminal_t & term) { pstring alias = this->name() + "." + name; @@ -546,7 +584,8 @@ namespace netlist state().parser().register_alias_no_fqn(alias, term.name()); } - void base_device_t::register_sub_alias(const pstring &name, const pstring &aliased) + void base_device_t::register_sub_alias(const pstring &name, + const pstring & aliased) { pstring alias = this->name() + "." + name; pstring aliased_fqn = this->name() + "." + aliased; @@ -555,23 +594,24 @@ namespace netlist state().parser().register_alias_no_fqn(alias, aliased_fqn); } - void base_device_t::connect(const detail::core_terminal_t &t1, const detail::core_terminal_t &t2) + void base_device_t::connect(const detail::core_terminal_t &t1, + const detail::core_terminal_t & t2) { state().parser().register_link_fqn(t1.name(), t2.name()); } void base_device_t::connect(const pstring &t1, const pstring &t2) { - state().parser().register_link_fqn(name() + "." + t1, name() + "." + t2); + state().parser().register_link_fqn(name() + "." + t1, + name() + "." + t2); } - - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // device_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - device_t::device_t(netlist_state_t &owner, const pstring &name) - : base_device_t(owner, name) + device_t::device_t(device_param_t data) + : base_device_t(data) , m_model(*this, "MODEL", pstring(config::DEFAULT_LOGIC_FAMILY())) { set_logic_family(state().setup().family_from_model(m_model())); @@ -579,9 +619,8 @@ namespace netlist throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model())); } - device_t::device_t(netlist_state_t &owner, const pstring &name, - const pstring &model) - : base_device_t(owner, name) + device_t::device_t(device_param_t data, const pstring &model) + : base_device_t(data) , m_model(*this, "MODEL", model) { set_logic_family(state().setup().family_from_model(m_model())); @@ -589,67 +628,50 @@ namespace netlist throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model())); } - device_t::device_t(netlist_state_t &owner, const pstring &name, - const logic_family_desc_t *desc) - : base_device_t(owner, name) + device_t::device_t(device_param_t data, const logic_family_desc_t *desc) + : base_device_t(data) , m_model(*this, "MODEL", pstring("")) { set_logic_family(desc); if (logic_family() == nullptr) - throw nl_exception(MF_NULLPTR_FAMILY(this->name(), "")); + throw nl_exception(MF_NULLPTR_FAMILY(this->name(), + "")); } - device_t::device_t(device_t &owner, const pstring &name) - : base_device_t(owner, name) - , m_model(*this, "MODEL", pstring("")) - { - set_logic_family(owner.logic_family()); - if (logic_family() == nullptr) - throw nl_exception(MF_NULLPTR_FAMILY(this->name(), "")); - } - - device_t::device_t(device_t &owner, const pstring &name, const pstring &model) - : base_device_t(owner, name) - , m_model(*this, "MODEL", model) - { - set_logic_family(state().setup().family_from_model(m_model())); - if (logic_family() == nullptr) - throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model())); - } - - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - analog_t::analog_t(core_device_t &dev, const pstring &aname, const state_e state, - nl_delegate delegate) + analog_t::analog_t(core_device_t &dev, const pstring &aname, + const state_e state, nl_delegate delegate) : core_terminal_t(dev, aname, state, delegate) { } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // net_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *rail_terminal) - : netlist_object_t(nl.exec(), aname) - , m_new_Q(*this, "m_new_Q", netlist_sig_t(0)) - , m_cur_Q (*this, "m_cur_Q", netlist_sig_t(0)) - , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED) - , m_next_scheduled_time(*this, "m_time", netlist_time_ext::zero()) - , m_rail_terminal(rail_terminal) + detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, + core_terminal_t *rail_terminal) + : netlist_object_t(nl.exec(), aname) + , m_new_Q(*this, "m_new_Q", netlist_sig_t(0)) + , m_cur_Q(*this, "m_cur_Q", netlist_sig_t(0)) + , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED) + , m_next_scheduled_time(*this, "m_time", netlist_time_ext::zero()) + , m_rail_terminal(rail_terminal) { props::add(this, props::value_type()); } bool detail::net_t::is_logic() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::net_t::is_analog() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } void detail::net_t::rebuild_list() @@ -657,7 +679,7 @@ namespace netlist // rebuild m_list m_list_active.clear(); - for (core_terminal_t * term : core_terms_ref()) + for (core_terminal_t *term : core_terms_ref()) if (term->terminal_state() != logic_t::STATE_INP_PASSIVE) { m_list_active.push_back(term); @@ -673,15 +695,13 @@ namespace netlist m_new_Q = 0; m_cur_Q = 0; - auto *p = dynamic_cast(this); - - if (p != nullptr) - p->set_Q_Analog(nlconst::zero()); + if (auto p = plib::dynamic_downcast(this)) + (*p)->set_Q_Analog(nlconst::zero()); // rebuild m_list and reset terminals to active or analog out state m_list_active.clear(); - for (core_terminal_t * ct : core_terms_copy()) + for (core_terminal_t *ct : core_terms_copy()) { ct->reset(); if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE) @@ -696,18 +716,17 @@ namespace netlist m_core_terms.remove(&term); } - void detail::net_t::remove_all_terminals() - { - m_core_terms.clear(); - } + void detail::net_t::remove_all_terminals() { m_core_terms.clear(); } void detail::net_t::add_terminal(detail::core_terminal_t &terminal) { - for (detail::core_terminal_t * t : m_core_terms) + for (detail::core_terminal_t *t : m_core_terms) if (t == &terminal) { - state().log().fatal(MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); - throw nl_exception(MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); + state().log().fatal( + MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); + throw nl_exception( + MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); } terminal.set_net(this); @@ -718,8 +737,9 @@ namespace netlist #else void detail::net_t::remove_terminal(detail::core_terminal_t &term) { - //net.core_terms().remove(p); - for (auto pp = state().core_terms(*this).begin(); pp != state().core_terms(*this).end(); pp++) + // net.core_terms().remove(p); + for (auto pp = state().core_terms(*this).begin(); + pp != state().core_terms(*this).end(); pp++) if (*pp == &term) { state().core_terms(*this).erase(pp); @@ -734,11 +754,13 @@ namespace netlist void detail::net_t::add_terminal(detail::core_terminal_t &terminal) { - for (detail::core_terminal_t * t : state().core_terms(*this)) + for (detail::core_terminal_t *t : core_terms_ref()) if (t == &terminal) { - state().log().fatal(MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); - throw nl_exception(MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); + state().log().fatal( + MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); + throw nl_exception( + MF_NET_1_DUPLICATE_TERMINAL_2(this->name(), t->name())); } terminal.set_net(this); @@ -747,23 +769,25 @@ namespace netlist } #endif - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_net_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal) - : net_t(nl, aname, rail_terminal) + logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, + detail::core_terminal_t *rail_terminal) + : net_t(nl, aname, rail_terminal) { } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_net_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal) - : net_t(nl, aname, rail_terminal) - , m_cur_Analog(*this, "m_cur_Analog", nlconst::zero()) - , m_solver(nullptr) + analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, + detail::core_terminal_t *rail_terminal) + : net_t(nl, aname, rail_terminal) + , m_cur_Analog(*this, "m_cur_Analog", nlconst::zero()) + , m_solver(nullptr) { } @@ -773,12 +797,12 @@ namespace netlist m_cur_Analog = nlconst::zero(); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // core_terminal_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &aname, - const state_e state, nl_delegate delegate) + detail::core_terminal_t::core_terminal_t(core_device_t &dev, + const pstring &aname, const state_e state, nl_delegate delegate) : device_object_t(&dev, dev.name() + "." + aname) , m_Q_CIR(*this, "m_Q", 0) , m_delegate(delegate) @@ -789,52 +813,52 @@ namespace netlist bool detail::core_terminal_t::is_logic() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_logic_input() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_logic_output() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_tristate_output() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_analog() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_analog_input() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } bool detail::core_terminal_t::is_analog_output() const noexcept { - return dynamic_cast(this) != nullptr; + return bool(plib::dynamic_downcast(this)); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // terminal_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- terminal_t::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *other_terminal, nl_delegate delegate) - : terminal_t(dev, aname, other_terminal, { nullptr, nullptr }, delegate) + : terminal_t(dev, aname, other_terminal, {nullptr, nullptr}, delegate) { } terminal_t::terminal_t(core_device_t &dev, const pstring &aname, - terminal_t *other_terminal, const std::array &splitter_terms, - nl_delegate delegate) + terminal_t * other_terminal, + const std::array &splitter_terms, nl_delegate delegate) : analog_t(dev, aname, STATE_BIDIR, delegate) , m_Idr(nullptr) , m_go(nullptr) @@ -843,12 +867,15 @@ namespace netlist state().setup().register_term(*this, other_terminal, splitter_terms); } - void terminal_t::set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false) + void terminal_t::set_ptrs(nl_fptype *gt, nl_fptype *go, + nl_fptype *Idr) noexcept(false) { // NOLINTNEXTLINE(readability-implicit-bool-conversion) if (!(gt && go && Idr) && (gt || go || Idr)) { - throw nl_exception("Either all pointers must be set or none for terminal {}", name()); + throw nl_exception( + "Either all pointers must be set or none for terminal {}", + name()); } m_gt = gt; @@ -856,46 +883,40 @@ namespace netlist m_Idr = Idr; } - // ---------------------------------------------------------------------------------------- - // net_input_t - // ---------------------------------------------------------------------------------------- - - // ---------------------------------------------------------------------------------------- - // net_output_t - // ---------------------------------------------------------------------------------------- - - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - logic_t::logic_t(device_t &dev, const pstring &aname, const state_e terminal_state, - nl_delegate delegate) - : core_terminal_t(dev, aname, terminal_state, delegate) - , logic_family_t(dev.logic_family()) + logic_t::logic_t(device_t &dev, const pstring &aname, + const state_e terminal_state, nl_delegate delegate) + : core_terminal_t(dev, aname, terminal_state, delegate) + , logic_family_t(dev.logic_family()) { } - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_input_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- logic_input_t::logic_input_t(device_t &dev, const pstring &aname, - nl_delegate delegate) - : logic_t(dev, aname, STATE_INP_ACTIVE, delegate) + nl_delegate delegate) + : logic_t(dev, aname, STATE_INP_ACTIVE, delegate) { state().setup().register_term(*this); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_output_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - logic_output_t::logic_output_t(device_t &dev, const pstring &aname, [[maybe_unused]] bool dummy) - : logic_t(dev, aname, STATE_OUT, nl_delegate()) - , m_my_net(dev.state(), name() + ".net", this) + logic_output_t::logic_output_t(device_t &dev, const pstring &aname, + [[maybe_unused]] bool dummy) + : logic_t(dev, aname, STATE_OUT, nl_delegate()) + , m_my_net(dev.state(), name() + ".net", this) { this->set_net(&m_my_net); - state().register_net(device_arena::owned_ptr(&m_my_net, false)); + state().register_net( + device_arena::owned_ptr(&m_my_net, false)); state().setup().register_term(*this); } @@ -905,20 +926,23 @@ namespace netlist net().initial(val); } - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // tristate_output_t - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - tristate_output_t::tristate_output_t(device_t &dev, const pstring &aname, bool force_logic) + tristate_output_t::tristate_output_t(device_t &dev, const pstring &aname, + bool force_logic) : logic_output_t(dev, aname) , m_last_logic(dev, name() + "." + "m_last_logic", 1) // force change - , m_tristate(dev, name() + "." + "m_tristate", force_logic ? 0 : 2) // force change + , m_tristate(dev, name() + "." + "m_tristate", + force_logic ? 0 : 2) // force change , m_force_logic(force_logic) - {} + { + } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_input_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- analog_input_t::analog_input_t(core_device_t &dev, const pstring &aname, nl_delegate delegate) @@ -927,18 +951,19 @@ namespace netlist state().setup().register_term(*this); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // analog_output_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname) - : analog_t(dev, aname, STATE_OUT, nl_delegate()) - , m_my_net(dev.state(), name() + ".net", this) + : analog_t(dev, aname, STATE_OUT, nl_delegate()) + , m_my_net(dev.state(), name() + ".net", this) { - state().register_net(device_arena::owned_ptr(&m_my_net, false)); + state().register_net( + device_arena::owned_ptr(&m_my_net, false)); this->set_net(&m_my_net); - //net().m_cur_Analog = NL_FCONST(0.0); + // net().m_cur_Analog = NL_FCONST(0.0); state().setup().register_term(*this); } @@ -947,18 +972,18 @@ namespace netlist net().set_Q_Analog(val); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Parameters ... - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // device-less, it's the responsibility of the owner to register! param_t::param_t(const pstring &name) - : device_object_t(nullptr, name) + : device_object_t(nullptr, name) { } param_t::param_t(core_device_t &device, const pstring &name) - : device_object_t(&device, device.name() + "." + name) + : device_object_t(&device, device.name() + "." + name) { device.state().setup().register_param_t(*this); } @@ -968,57 +993,57 @@ namespace netlist param_t::param_type_t param_t::param_type() const noexcept(false) { - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return STRING; - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return DOUBLE; - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return INTEGER; - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return LOGIC; - if (dynamic_cast(this) != nullptr) + if (plib::dynamic_downcast(this)) return POINTER; state().log().fatal(MF_UNKNOWN_PARAM_TYPE(name())); throw nl_exception(MF_UNKNOWN_PARAM_TYPE(name())); } - pstring param_t::get_initial(const core_device_t *dev, bool *found) const { - pstring res = dev->state().setup().get_initial_param_val(this->name(), ""); + pstring res = dev->state().setup().get_initial_param_val(this->name(), + ""); *found = (!res.empty()); return res; } - param_str_t::param_str_t(core_device_t &device, const pstring &name, const pstring &val) + param_str_t::param_str_t(core_device_t &device, const pstring &name, + const pstring &val) : param_t(device, name) { m_param = plib::make_unique(val); - *m_param = device.state().setup().get_initial_param_val(this->name(),val); + *m_param = device.state().setup().get_initial_param_val(this->name(), + val); } - param_str_t::param_str_t(netlist_state_t &state, const pstring &name, const pstring &val) + param_str_t::param_str_t(netlist_state_t &state, const pstring &name, + const pstring &val) : param_t(name) { // device-less parameter, no registration, owner is responsible m_param = plib::make_unique(val); - *m_param = state.setup().get_initial_param_val(this->name(),val); + *m_param = state.setup().get_initial_param_val(this->name(), val); } - void param_str_t::changed() noexcept - { - } + void param_str_t::changed() noexcept {} - param_ptr_t::param_ptr_t(core_device_t &device, const pstring &name, uint8_t * val) + param_ptr_t::param_ptr_t(core_device_t &device, const pstring &name, + uint8_t *val) : param_t(device, name) , m_param(val) { } - void param_model_t::changed() noexcept - { - } + void param_model_t::changed() noexcept {} pstring param_model_t::type() { @@ -1041,13 +1066,13 @@ namespace netlist return device().state().parser().get_data_stream(str()); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // netlist_t // // Hot section // // Any changes below will impact performance. - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- template void netlist_t::process_queue_stats(const netlist_time_ext delta) noexcept @@ -1075,9 +1100,9 @@ namespace netlist } else { - logic_net_t &mc_net(m_main_clock->m_Q.net()); + logic_net_t & mc_net(m_main_clock->m_Q.net()); const netlist_time inc(m_main_clock->m_inc); - netlist_time_ext mc_time(mc_net.next_scheduled_time()); + netlist_time_ext mc_time(mc_net.next_scheduled_time()); do { diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index c19fe296aa7..01bc99dc706 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -18,22 +18,22 @@ /// /// \brief Version - Major. /// -#define NL_VERSION_MAJOR 0 +#define NL_VERSION_MAJOR 0 /// /// \brief Version - Minor. /// -#define NL_VERSION_MINOR 14 +#define NL_VERSION_MINOR 14 /// \brief Version - Patch level. /// -#define NL_VERSION_PATCHLEVEL 0 +#define NL_VERSION_PATCHLEVEL 0 /// /// \addtogroup compiledefine /// \{ -//============================================================ -// GENERAL -//============================================================ +// ----------------------------------------------------------------------------- +// General +// ----------------------------------------------------------------------------- /// \brief Compile in academic solvers /// @@ -48,20 +48,19 @@ /// time significantly. /// #ifndef NL_USE_ACADEMIC_SOLVERS -#define NL_USE_ACADEMIC_SOLVERS (1) + #define NL_USE_ACADEMIC_SOLVERS (1) #endif /// \brief Use backward Euler integration /// /// This will use backward Euler instead of trapezoidal integration. /// -/// FIXME: Long term this will become a runtime setting. Only the capacitor model -/// currently has a trapezoidal version and there is no support currently for -/// variable capacitors. -/// The change will have impact on timings since trapezoidal improves timing -/// accuracy. +/// FIXME: Long term this will become a runtime setting. Only the capacitor +/// model currently has a trapezoidal version and there is no support currently +/// for variable capacitors. The change will have impact on timings since +/// trapezoidal improves timing accuracy. #ifndef NL_USE_BACKWARD_EULER -#define NL_USE_BACKWARD_EULER (1) // FIXME: Move to config struct later + #define NL_USE_BACKWARD_EULER (1) // FIXME: Move to config struct later #endif /// \brief Compile with core terminals owned by net_t @@ -78,7 +77,7 @@ /// By default the setting is currently disabled. /// #ifndef NL_USE_INPLACE_CORE_TERMS -#define NL_USE_INPLACE_CORE_TERMS (0) + #define NL_USE_INPLACE_CORE_TERMS (0) #endif /// \brief Use alternative truth table execution approach @@ -90,26 +89,25 @@ /// Unfortunately this has to be macro since it needs another member variable. /// #ifndef NL_USE_TT_ALTERNATIVE -#define NL_USE_TT_ALTERNATIVE (0) + #define NL_USE_TT_ALTERNATIVE (0) #endif /// \brief Compile matrix solvers using the __float128 type. /// /// Defaults to \ref PUSE_FLOAT128 #ifndef NL_USE_FLOAT128 -#define NL_USE_FLOAT128 PUSE_FLOAT128 + #define NL_USE_FLOAT128 PUSE_FLOAT128 #endif - -//============================================================ +// ----------------------------------------------------------------------------- // DEBUGGING -//============================================================ +// ----------------------------------------------------------------------------- /// \brief Enable compile time debugging code /// #ifndef NL_DEBUG -#define NL_DEBUG (false) + #define NL_DEBUG (false) #endif /// @@ -118,9 +116,9 @@ namespace netlist { - //============================================================ - // GENERAL - //============================================================ + // ------------------------------------------------------------------------- + // GENERAL + // ------------------------------------------------------------------------- struct config_default { @@ -136,10 +134,11 @@ namespace netlist /// brief default minimum alignment of mempool_arena /// /// 256 is the best compromise between logic applications like MAME - /// TTL games (e.g. pong) and analog applications like e.g. kidnikik sound. + /// TTL games (e.g. pong) and analog applications like e.g. kidnikik + /// sound. /// - /// Best performance for pong is achieved with a value of 16, but this degrades - /// kidniki performance by ~10%. + /// Best performance for pong is achieved with a value of 16, but this + /// degrades kidniki performance by ~10%. /// /// More work is needed here. using mempool_align = std::integral_constant; @@ -159,9 +158,9 @@ namespace netlist /// using use_queue_stats = std::integral_constant; - //============================================================ + // --------------------------------------------------------------------- // Time resolution - //============================================================ + // --------------------------------------------------------------------- /// \brief Resolution as clocks per second for timing /// @@ -178,15 +177,17 @@ namespace netlist /// | 63 | 100,000,000,000 | 92,233,720 | 1,068| 2.9 | /// | 63 | 1,000,000,000,000 | 9,223,372 | 107| 0.3 | /// - using INTERNAL_RES = std::integral_constant; // NOLINT + using INTERNAL_RES = std::integral_constant; // NOLINT /// \brief Recommended clock to be used /// - /// This is the recommended clock to be used in fixed clock applications limited - /// to 32 bit clock resolution. The MAME code (netlist.cpp) contains code - /// illustrating how to deal with remainders if \ref INTERNAL_RES is bigger than - /// NETLIST_CLOCK. - using DEFAULT_CLOCK = std::integral_constant; // NOLINT + /// This is the recommended clock to be used in fixed clock applications + /// limited to 32 bit clock resolution. The MAME code (netlist.cpp) + /// contains code illustrating how to deal with remainders if \ref + /// INTERNAL_RES is bigger than NETLIST_CLOCK. + using DEFAULT_CLOCK = std::integral_constant; // NOLINT /// \brief Default logic family /// @@ -194,23 +195,28 @@ namespace netlist /// \brief Maximum queue size /// - using max_queue_size = std::integral_constant; // NOLINT + using max_queue_size = std::integral_constant; // NOLINT /// \brief Maximum queue size for solvers /// - using max_solver_queue_size = std::integral_constant; // NOLINT + using max_solver_queue_size = std::integral_constant; // NOLINT /// \brief Support float type for matrix calculations. /// /// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times - using use_float_matrix = std::integral_constant; + using use_float_matrix = std::integral_constant; /// \brief Support long double type for matrix calculations. /// /// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times - using use_long_double_matrix = std::integral_constant; + using use_long_double_matrix = std::integral_constant; - using use_float128_matrix = std::integral_constant; + using use_float128_matrix = std::integral_constant; /// \brief Floating point types used /// @@ -235,7 +241,8 @@ namespace netlist /// By default it is disabled since it is not as fast as /// the default approach. It is ~20% slower. /// - using use_copy_instead_of_reference = std::integral_constant; + using use_copy_instead_of_reference = std::integral_constant; /// \brief Avoid unnecessary queue pushes /// @@ -268,9 +275,10 @@ namespace netlist /// struct config : public config_default { - //using mempool_align = std::integral_constant; - //using avoid_noop_queue_pushes = std::integral_constant; - //using use_copy_instead_of_reference = std::integral_constant; + // using mempool_align = std::integral_constant; + // using avoid_noop_queue_pushes = std::integral_constant; + // using use_copy_instead_of_reference = std::integral_constant; }; using nl_fptype = config::fptype; @@ -281,21 +289,34 @@ namespace netlist /// template struct fp_constants - { }; + { + }; /// \brief Specific constants for long double floating point type /// template <> struct fp_constants { - static constexpr long double DIODE_MAXDIFF() noexcept { return 1e100L; } // NOLINT - static constexpr long double DIODE_MAXVOLT() noexcept { return 300.0L; } // NOLINT + static constexpr long double DIODE_MAXDIFF() noexcept + { + return 1e100L; + } // NOLINT + static constexpr long double DIODE_MAXVOLT() noexcept + { + return 300.0L; + } // NOLINT - static constexpr long double TIMESTEP_MAXDIFF() noexcept { return 1e100L; } // NOLINT - static constexpr long double TIMESTEP_MINDIV() noexcept { return 1e-60L; } // NOLINT + static constexpr long double TIMESTEP_MAXDIFF() noexcept + { + return 1e100L; + } // NOLINT + static constexpr long double TIMESTEP_MINDIV() noexcept + { + return 1e-60L; + } // NOLINT - static constexpr const char * name() noexcept { return "long double"; } - static constexpr const char * suffix() noexcept { return "L"; } + static constexpr const char *name() noexcept { return "long double"; } + static constexpr const char *suffix() noexcept { return "L"; } }; /// \brief Specific constants for double floating point type @@ -303,14 +324,26 @@ namespace netlist template <> struct fp_constants { - static constexpr double DIODE_MAXDIFF() noexcept { return 1e100; } // NOLINT - static constexpr double DIODE_MAXVOLT() noexcept { return 300.0; } // NOLINT + static constexpr double DIODE_MAXDIFF() noexcept + { + return 1e100; + } // NOLINT + static constexpr double DIODE_MAXVOLT() noexcept + { + return 300.0; + } // NOLINT - static constexpr double TIMESTEP_MAXDIFF() noexcept { return 1e100; } // NOLINT - static constexpr double TIMESTEP_MINDIV() noexcept { return 1e-60; } // NOLINT + static constexpr double TIMESTEP_MAXDIFF() noexcept + { + return 1e100; + } // NOLINT + static constexpr double TIMESTEP_MINDIV() noexcept + { + return 1e-60; + } // NOLINT - static constexpr const char * name() noexcept { return "double"; } - static constexpr const char * suffix() noexcept { return ""; } + static constexpr const char *name() noexcept { return "double"; } + static constexpr const char *suffix() noexcept { return ""; } }; /// \brief Specific constants for float floating point type @@ -318,14 +351,26 @@ namespace netlist template <> struct fp_constants { - static constexpr float DIODE_MAXDIFF() noexcept { return 1e20F; } // NOLINT - static constexpr float DIODE_MAXVOLT() noexcept { return 90.0F; } // NOLINT + static constexpr float DIODE_MAXDIFF() noexcept + { + return 1e20F; + } // NOLINT + static constexpr float DIODE_MAXVOLT() noexcept + { + return 90.0F; + } // NOLINT - static constexpr float TIMESTEP_MAXDIFF() noexcept { return 1e30F; } // NOLINT - static constexpr float TIMESTEP_MINDIV() noexcept { return 1e-8F; } // NOLINT + static constexpr float TIMESTEP_MAXDIFF() noexcept + { + return 1e30F; + } // NOLINT + static constexpr float TIMESTEP_MINDIV() noexcept + { + return 1e-8F; + } // NOLINT - static constexpr const char * name() noexcept { return "float"; } - static constexpr const char * suffix() noexcept { return "f"; } + static constexpr const char *name() noexcept { return "float"; } + static constexpr const char *suffix() noexcept { return "f"; } }; #if (NL_USE_FLOAT128) @@ -334,7 +379,7 @@ namespace netlist template <> struct fp_constants { -#if 0 + #if 0 // MAME compile doesn't support Q static constexpr FLOAT128 DIODE_MAXDIFF() noexcept { return 1e100Q; } static constexpr FLOAT128 DIODE_MAXVOLT() noexcept { return 300.0Q; } @@ -344,17 +389,29 @@ namespace netlist static constexpr const char * name() noexcept { return "FLOAT128"; } static constexpr const char * suffix() noexcept { return "Q"; } -#else - static constexpr FLOAT128 DIODE_MAXDIFF() noexcept { return static_cast(1e100L); } - static constexpr FLOAT128 DIODE_MAXVOLT() noexcept { return static_cast(300.0L); } + #else + static constexpr FLOAT128 DIODE_MAXDIFF() noexcept + { + return static_cast(1e100L); + } + static constexpr FLOAT128 DIODE_MAXVOLT() noexcept + { + return static_cast(300.0L); + } - static constexpr FLOAT128 TIMESTEP_MAXDIFF() noexcept { return static_cast(1e100L); } - static constexpr FLOAT128 TIMESTEP_MINDIV() noexcept { return static_cast(1e-60L); } + static constexpr FLOAT128 TIMESTEP_MAXDIFF() noexcept + { + return static_cast(1e100L); + } + static constexpr FLOAT128 TIMESTEP_MINDIV() noexcept + { + return static_cast(1e-60L); + } - static constexpr const char * name() noexcept { return "__float128"; } - static constexpr const char * suffix() noexcept { return "Q"; } + static constexpr const char *name() noexcept { return "__float128"; } + static constexpr const char *suffix() noexcept { return "Q"; } -#endif + #endif }; #endif } // namespace netlist @@ -363,7 +420,12 @@ namespace netlist // Asserts //============================================================ -#define nl_assert(x) do { if (NL_DEBUG) passert_always(x); } while (0) +#define nl_assert(x) \ + do \ + { \ + if (NL_DEBUG) \ + passert_always(x); \ + } while (0) #define nl_assert_always(x, msg) passert_always_msg(x, msg) #endif // NLCONFIG_H_ diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h index bca9d5c93ce..46f2ac3e5e1 100644 --- a/src/lib/netlist/nl_errstr.h +++ b/src/lib/netlist/nl_errstr.h @@ -108,6 +108,7 @@ namespace netlist PERRMSGV(MW_TERMINAL_1_WITHOUT_CONNECTIONS, 1, "Found terminal {1} without connections") PERRMSGV(ME_TERMINAL_1_WITHOUT_NET, 1, "Found terminal {1} without a net") + PERRMSGV(ME_TERMINALS_1_2_WITHOUT_NET, 2, "Found terminals {1} and {2} without a net") PERRMSGV(MF_TERMINALS_WITHOUT_NET, 0, "Found terminals without a net") PERRMSGV(ME_TRISTATE_NO_PROXY_FOUND_2, 2, "Tristate output {1} on device {2} is not connected to a proxy. You " diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp index 2a1cde5bb42..6ab9e84cafd 100644 --- a/src/lib/netlist/nl_factory.cpp +++ b/src/lib/netlist/nl_factory.cpp @@ -5,26 +5,30 @@ /// \file nl_factory.cpp /// -#include "nl_errstr.h" #include "nl_factory.h" + +#include "nl_errstr.h" #include "nl_setup.h" #include "core/core_device.h" #include "plib/putil.h" -namespace netlist::factory { +namespace netlist::factory +{ // FIXME: this doesn't do anything, check how to remove - class NETLIB_NAME(wrapper) : public base_device_t + class NETLIB_NAME(wrapper) + : public base_device_t { public: - NETLIB_NAME(wrapper)(netlist_state_t &anetlist, const pstring &name) - : base_device_t(anetlist, name) + NETLIB_NAME(wrapper)(base_device_param_t data) + : base_device_t(data) { } + protected: - //NETLIB_RESETI() {} + // NETLIB_RESETI() {} }; element_t::element_t(const pstring &name, properties &&props) @@ -33,9 +37,9 @@ namespace netlist::factory { { } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // net_device_t_base_factory - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- list_t::list_t(log_type &alog) : m_log(alog) @@ -46,7 +50,7 @@ namespace netlist::factory { bool list_t::exists(const pstring &name) const noexcept { - for (const auto & e : *this) + for (const auto &e : *this) if (e->name() == name) return true; return false; @@ -62,9 +66,9 @@ namespace netlist::factory { push_back(std::move(factory)); } - factory::element_t * list_t::factory_by_name(const pstring &devname) + factory::element_t *list_t::factory_by_name(const pstring &devname) { - for (auto & e : *this) + for (auto &e : *this) { if (e->name() == devname) return e.get(); @@ -74,19 +78,22 @@ namespace netlist::factory { throw nl_exception(MF_CLASS_1_NOT_FOUND(devname)); } - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // library_element_t: factory class to wrap macro based chips/elements - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - library_element_t::library_element_t(const pstring &name, properties &&props) - : element_t(name, std::move(properties(props).set_type(element_type::MACRO))) + library_element_t::library_element_t(const pstring &name, + properties && props) + : element_t(name, + std::move(properties(props).set_type(element_type::MACRO))) { } - device_arena::unique_ptr library_element_t::make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) + device_arena::unique_ptr library_element_t::make_device( + device_arena &pool, netlist_state_t &anetlist, const pstring &name) { - return plib::make_unique(pool, anetlist, name); + return plib::make_unique(pool, + base_device_data_t{anetlist, name}); } - } // namespace netlist::factory diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index 1a3cd74ae1f..0141a168c2c 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -9,6 +9,7 @@ #define NLFACTORY_H_ #include "nltypes.h" + #include "plib/palloc.h" #include "plib/pmempool.h" #include "plib/psource.h" @@ -18,30 +19,28 @@ #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_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) \ +#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_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 { +#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::factory +{ enum class element_type { BUILTIN, @@ -50,11 +49,13 @@ namespace factory { struct properties { - properties(const pstring &default_parameter, plib::source_location &&location) + properties(const pstring & default_parameter, + plib::source_location &&location) : m_default_parameter(default_parameter) , m_location(std::move(location)) , m_type(element_type::BUILTIN) - { } + { + } ~properties() = default; PCOPYASSIGNMOVE(properties, default) @@ -64,10 +65,7 @@ namespace factory { return m_default_parameter; } - plib::source_location source() const noexcept - { - return m_location; - } + plib::source_location source() const noexcept { return m_location; } element_type type() const noexcept { return m_type; } @@ -76,20 +74,20 @@ namespace factory { m_type = t; return *this; } + private: - pstring m_default_parameter; + pstring m_default_parameter; plib::source_location m_location; - element_type m_type; + 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 *; @@ -99,57 +97,71 @@ namespace factory { PCOPYASSIGNMOVE(element_t, default) - virtual dev_uptr make_device(device_arena &pool, - netlist_state_t &anetlist, - const pstring &name) = 0; + 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.default_parameter(); } - plib::source_location source() const noexcept { return m_properties.source(); } + pstring param_desc() const noexcept + { + return m_properties.default_parameter(); + } + 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 + pstring m_name; ///< device name + properties m_properties; ///< source file and other information and + ///< settings }; template class device_element_t : public element_t { public: + using constructor_data_t = typename C::constructor_data_t; - device_element_t(const pstring &name, properties &&props, Args&&... args) + 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) + 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 plib::make_unique( + pool, constructor_data_t{anetlist, name}, + std::forward(std::get(args))...); } - dev_uptr make_device(device_arena &pool, - netlist_state_t &anetlist, - const pstring &name, std::tuple& 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{}); + 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 + 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) + static uptr + create(const pstring &name, properties &&props, Args &&...args) { - return plib::make_unique, host_arena>(name, - std::move(props), std::forward(args)...); + return plib::make_unique, host_arena>( + name, std::move(props), std::forward(args)...); } + private: std::tuple m_args; }; @@ -162,60 +174,61 @@ namespace factory { PCOPYASSIGNMOVE(list_t, delete) - template - void add(const pstring &name, properties &&props, Args&&... args) + template + void add(const pstring &name, properties &&props, Args &&...args) { - add(device_element_t::create(name, std::move(props), - std::forward(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); + 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; + return bool(plib::dynamic_downcast *>(f)); } 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)); + 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; + dev_uptr make_device(device_arena &pool, netlist_state_t &anetlist, + const pstring &name) override; }; - } // namespace factory +} // namespace netlist::factory - namespace devices { - void initialize_factory(factory::list_t &factory); - } // namespace devices -} // namespace netlist +namespace netlist::devices +{ + void initialize_factory(factory::list_t &factory); +} // namespace netlist::devices #endif // NLFACTORY_H_ diff --git a/src/lib/netlist/nl_interface.h b/src/lib/netlist/nl_interface.h index a9acb0bd564..eb187bad241 100644 --- a/src/lib/netlist/nl_interface.h +++ b/src/lib/netlist/nl_interface.h @@ -11,232 +11,238 @@ #define NLINTERFACE_H_ #include "nl_setup.h" + #include "core/analog.h" #include "core/device.h" #include "core/device_macros.h" #include "core/logic.h" #include "core/setup.h" -#include #include +#include -namespace netlist +namespace netlist::interface { + /// \brief analog_callback device + /// + /// This device is used to call back into the application which + /// is controlling the execution of the netlist. + /// + /// The device will call the provided lambda with a reference to + /// itself and the current value of the net it is connected to. + /// + /// The following code is an example on how to add the device to + /// the netlist factory. + /// + /// ``` + /// const pstring pin(m_in); + /// pstring dname = pstring("OUT_") + pin; + /// + /// const auto lambda = [this](auto &in, netlist::nl_fptype val) + /// { + /// this->cpu()->update_icount(in.exec().time()); + /// this->m_delegate(val, this->cpu()->local_time()); + /// this->cpu()->check_mame_abort_slice(); + /// }; + /// + /// using lb_t = decltype(lambda); + /// using cb_t = + /// netlist::interface::NETLIB_NAME(analog_callback); + /// + /// parser.factory().add(dname, + /// netlist::factory::properties("-", PSOURCELOC()), 1e-6, + /// std::forward(lambda)); + /// ``` - namespace interface + template + class nld_analog_callback : public device_t { - /// \brief analog_callback device - /// - /// This device is used to call back into the application which - /// is controlling the execution of the netlist. - /// - /// The device will call the provided lambda with a reference to - /// itself and the current value of the net it is connected to. - /// - /// The following code is an example on how to add the device to - /// the netlist factory. - /// - /// ``` - /// const pstring pin(m_in); - /// pstring dname = pstring("OUT_") + pin; - /// - /// const auto lambda = [this](auto &in, netlist::nl_fptype val) - /// { - /// this->cpu()->update_icount(in.exec().time()); - /// this->m_delegate(val, this->cpu()->local_time()); - /// this->cpu()->check_mame_abort_slice(); - /// }; - /// - /// using lb_t = decltype(lambda); - /// using cb_t = netlist::interface::NETLIB_NAME(analog_callback); - /// - /// parser.factory().add(dname, - /// netlist::factory::properties("-", PSOURCELOC()), 1e-6, std::forward(lambda)); - /// ``` - - template - NETLIB_OBJECT(analog_callback) + public: + nld_analog_callback(constructor_param_t data, nl_fptype threshold, + FUNC &&func) + : device_t(data) + , m_in(*this, "IN", NETLIB_DELEGATE(in)) + , m_threshold(threshold) + , m_last(*this, "m_last", 0) + , m_func(func) { - public: - NETLIB_CONSTRUCTOR_EX(analog_callback, nl_fptype threshold, FUNC &&func) - , m_in(*this, "IN", NETLIB_DELEGATE(in)) - , m_threshold(threshold) - , m_last(*this, "m_last", 0) - , m_func(func) - { - } + } - NETLIB_RESETI() - { - m_last = 0.0; - } + NETLIB_RESETI() { m_last = 0.0; } - NETLIB_HANDLERI(in) - { - const nl_fptype cur = m_in(); - if (plib::abs(cur - m_last) > m_threshold) - { - m_last = cur; - m_func(*this, cur); - } - } - - private: - analog_input_t m_in; - nl_fptype m_threshold; - state_var m_last; - FUNC m_func; - }; - - - /// \brief logic_callback device - /// - /// This device must be connected to a logic net. It has no power terminals - /// and conversion with proxies will not work. - /// - /// Background: This device may be inserted later into the driver and should - /// not modify the resulting analog representation of the netlist. - /// - /// If you get error messages on missing power terminals you have to use the - /// analog callback device instead. - - template - NETLIB_OBJECT(logic_callback) + NETLIB_HANDLERI(in) { - public: - NETLIB_CONSTRUCTOR_EX(logic_callback, FUNC &&func) - , m_in(*this, "IN", NETLIB_DELEGATE(in)) - , m_func(func) + const nl_fptype cur = m_in(); + if (plib::abs(cur - m_last) > m_threshold) { - } - - NETLIB_HANDLERI(in) - { - const netlist_sig_t cur = m_in(); + m_last = cur; m_func(*this, cur); } + } - private: - logic_input_t m_in; - FUNC m_func; - }; + private: + analog_input_t m_in; + nl_fptype m_threshold; + state_var m_last; + FUNC m_func; + }; - /// \brief Set parameters to buffers contents at regular intervals - /// - /// This device will update a parameter from a buffers passed to the device. - /// It is the responsibility of the controlling application to ensure that - /// the buffer is filled at regular intervals. - /// - /// \tparam T The buffer type - /// \tparam N Maximum number of supported buffers - /// - template - NETLIB_OBJECT(buffered_param_setter) + /// \brief logic_callback device + /// + /// This device must be connected to a logic net. It has no power + /// terminals and conversion with proxies will not work. + /// + /// Background: This device may be inserted later into the driver and + /// should not modify the resulting analog representation of the + /// netlist. + /// + /// If you get error messages on missing power terminals you have to use + /// the analog callback device instead. + + template + class nld_logic_callback : public device_t + { + public: + nld_logic_callback(constructor_param_t data, FUNC &&func) + : device_t(data) + , m_in(*this, "IN", NETLIB_DELEGATE(in)) + , m_func(func) { - public: + } - NETLIB_CONSTRUCTOR(buffered_param_setter) - , m_sample_time(netlist_time::zero()) - , m_feedback(*this, "FB", NETLIB_DELEGATE(feedback)) // clock part - , m_Q(*this, "Q") - , m_pos(0) - , m_samples(0) - , m_param_name(*this, "CHAN", "") - , m_param_mult(*this, "MULT", 1.0) - , m_param_offset(*this, "OFFSET", 0.0) - , m_param(nullptr) - , m_id(*this, "ID", 0) - { - connect("FB", "Q"); - m_buffer = nullptr; - } + NETLIB_HANDLERI(in) + { + const netlist_sig_t cur = m_in(); + m_func(*this, cur); + } - protected: - NETLIB_RESETI() - { - } + private: + logic_input_t m_in; + FUNC m_func; + }; - NETLIB_HANDLERI(feedback) + /// \brief Set parameters to buffers contents at regular intervals + /// + /// This device will update a parameter from a buffer passed to the + /// device. It is the responsibility of the controlling application to + /// ensure that the buffer is filled at regular intervals. + /// + /// \tparam T The buffer type + /// \tparam N Maximum number of supported buffers + /// + template + class nld_buffered_param_setter : public device_t + { + public: + nld_buffered_param_setter(constructor_param_t data) + : device_t(data) + , m_sample_time(netlist_time::zero()) + , m_feedback(*this, "FB", NETLIB_DELEGATE(feedback)) // clock part + , m_Q(*this, "Q") + , m_pos(0) + , m_samples(0) + , m_param_name(*this, "CHAN", "") + , m_param_mult(*this, "MULT", 1.0) + , m_param_offset(*this, "OFFSET", 0.0) + , m_param(nullptr) + , m_id(*this, "ID", 0) + { + connect("FB", "Q"); + m_buffer = nullptr; + } + + protected: + NETLIB_RESETI() {} + + NETLIB_HANDLERI(feedback) + { + if (m_pos < m_samples) { - if (m_pos < m_samples) + // check if called outside of stream_update + if (m_buffer != nullptr) { - // check if called outside of stream_update - if (m_buffer != nullptr) - { - const nl_fptype v = (*m_buffer)[m_pos]; - m_param_setter(v * m_param_mult() + m_param_offset()); - } - } - else - { - // FIXME: The logic has a rounding issue because time resolution divided - // by 48,000 is not a natural number. The fractional part - // adds up to one samples every 13 seconds for 100 ps resolution. - // Fixing this is possible but complicated and expensive. - } - m_pos++; - - m_Q.net().toggle_and_push_to_queue(m_sample_time); - } - - public: - /// \brief resolve parameter names to pointers - /// - /// This function must be called after all device were constructed but - /// before reset is called. - void resolve_params(netlist_time sample_time) - { - m_pos = 0; - m_sample_time = sample_time; - if (m_param_name() != pstring("")) - { - param_t *p = &state().setup().find_param(m_param_name()).param(); - m_param = p; - if (dynamic_cast(p) != nullptr) - m_param_setter = setter_t(&NETLIB_NAME(buffered_param_setter)::setter, this); - else if (dynamic_cast(p) != nullptr) - m_param_setter = setter_t(&NETLIB_NAME(buffered_param_setter)::setter, this); + const nl_fptype v = (*m_buffer)[m_pos]; + m_param_setter(v * m_param_mult() + m_param_offset()); } } - - void buffer_reset(netlist_time sample_time, std::size_t num_samples, T *inputs) + else { - m_samples = num_samples; - m_sample_time = sample_time; - m_pos = 0; - m_buffer = inputs; + // FIXME: The logic has a rounding issue because time + // resolution divided by 48,000 is not a natural + // number. The fractional part adds up to one samples + // every 13 seconds for 100 ps resolution. Fixing + // this is possible but complicated and expensive. } + m_pos++; - std::size_t id() const { return m_id; } - private: - using setter_t = plib::pmfp; + m_Q.net().toggle_and_push_to_queue(m_sample_time); + } - template - void setter(nl_fptype v) + public: + /// \brief resolve parameter names to pointers + /// + /// This function must be called after all device were constructed + /// but before reset is called. + void resolve_params(netlist_time sample_time) + { + m_pos = 0; + m_sample_time = sample_time; + if (m_param_name() != pstring("")) { - static_cast(m_param)->set(v); + param_t *p = &state() + .setup() + .find_param(m_param_name()) + .param(); + m_param = p; + if (plib::dynamic_downcast(p)) + m_param_setter = setter_t( + &NETLIB_NAME(buffered_param_setter)::setter, + this); + else if (plib::dynamic_downcast(p)) + m_param_setter = setter_t( + &NETLIB_NAME(buffered_param_setter)::setter< + param_logic_t>, + this); } + } - netlist_time m_sample_time; + void buffer_reset(netlist_time sample_time, std::size_t num_samples, + T *inputs) + { + m_samples = num_samples; + m_sample_time = sample_time; + m_pos = 0; + m_buffer = inputs; + } - logic_input_t m_feedback; - logic_output_t m_Q; + std::size_t id() const { return m_id; } - std::size_t m_pos; - std::size_t m_samples; + private: + using setter_t = plib::pmfp; - param_str_t m_param_name; - param_fp_t m_param_mult; - param_fp_t m_param_offset; - param_t * m_param; - setter_t m_param_setter; - T * m_buffer; - param_num_t m_id; - }; + template + void setter(nl_fptype v) + { + static_cast(m_param)->set(v); + } - } // namespace interface + netlist_time m_sample_time; -} // namespace netlist + logic_input_t m_feedback; + logic_output_t m_Q; + std::size_t m_pos; + std::size_t m_samples; + + param_str_t m_param_name; + param_fp_t m_param_mult; + param_fp_t m_param_offset; + param_t * m_param; + setter_t m_param_setter; + T * m_buffer; + param_num_t m_id; + }; + +} // namespace netlist::interface #endif // NLINTERFACE_H_ diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 02c7d11f2b2..3e4ecd0937c 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -1,16 +1,17 @@ // license:BSD-3-Clause // copyright-holders:Couriersud +#include "nl_parser.h" + #include "nl_errstr.h" #include "nl_factory.h" -#include "nl_parser.h" #include "nl_setup.h" namespace netlist { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // A netlist parser - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- void parser_t::verror(const pstring &msg) { @@ -19,12 +20,16 @@ namespace netlist } parser_t::parser_t(nlparse_t &setup) - : m_setup(setup) - , m_cur_local(nullptr) + : m_setup(setup) + , m_cur_local(nullptr) { - m_tokenizer.identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-$@") - .number_chars(".0123456789", "0123456789eE-.") //FIXME: processing of numbers - .whitespace(pstring("") + ' ' + static_cast(9) + static_cast(10) + static_cast(13)) + m_tokenizer + .identifier_chars( + "abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-$@") + .number_chars(".0123456789", "0123456789eE-.") // FIXME: processing + // of numbers + .whitespace(pstring("") + ' ' + static_cast(9) + + static_cast(10) + static_cast(13)) .comment("/*", "*/", "//"); m_tok_paren_left = m_tokenizer.register_token("("); m_tok_paren_right = m_tokenizer.register_token(")"); @@ -43,7 +48,8 @@ namespace netlist m_tok_INCLUDE = m_tokenizer.register_token("INCLUDE"); m_tok_LOCAL_SOURCE = m_tokenizer.register_token("LOCAL_SOURCE"); m_tok_LOCAL_LIB_ENTRY = m_tokenizer.register_token("LOCAL_LIB_ENTRY"); - m_tok_EXTERNAL_LIB_ENTRY = m_tokenizer.register_token("EXTERNAL_LIB_ENTRY"); + m_tok_EXTERNAL_LIB_ENTRY = m_tokenizer.register_token( + "EXTERNAL_LIB_ENTRY"); m_tok_SUBMODEL = m_tokenizer.register_token("SUBMODEL"); m_tok_NETLIST_START = m_tokenizer.register_token("NETLIST_START"); m_tok_NETLIST_END = m_tokenizer.register_token("NETLIST_END"); @@ -62,7 +68,6 @@ namespace netlist m_tokenizer.register_token("CAP_U"); m_tokenizer.register_token("CAP_N"); m_tokenizer.register_token("CAP_P"); - } bool parser_t::parse(plib::istream_uptr &&strm, const pstring &nlname) @@ -72,15 +77,16 @@ namespace netlist return parse(tokstor, nlname); } - void parser_t::parse_tokens(plib::istream_uptr &&strm, token_store_t &tokstor) + void parser_t::parse_tokens(plib::istream_uptr &&strm, + token_store_t & tokstor) { plib::putf8_reader u8reader(strm.release_stream()); m_tokenizer.append_to_store(&u8reader, tokstor); } - bool parser_t::parse(const token_store_t &tokstor, const pstring &nlname) + bool parser_t::parse(const token_store_t &store, const pstring &nlname) { - set_token_source(&tokstor); + set_token_source(&store); bool in_nl = false; @@ -97,7 +103,7 @@ namespace netlist if (token.is(m_tok_NETLIST_END) || token.is(m_tok_TRUTHTABLE_END)) { if (!in_nl) - error (MF_PARSER_UNEXPECTED_1(token.str())); + error(MF_PARSER_UNEXPECTED_1(token.str())); else { in_nl = false; @@ -108,15 +114,16 @@ namespace netlist m_cur_local->push_back(token); m_cur_local->push_back(token_t(m_tok_paren_left)); m_cur_local->push_back(token_t(m_tok_paren_right)); - } - else if (token.is(m_tok_NETLIST_START) || token.is(m_tok_TRUTHTABLE_START)) + else if (token.is(m_tok_NETLIST_START) + || token.is(m_tok_TRUTHTABLE_START)) { if (in_nl) - error (MF_PARSER_UNEXPECTED_1(token.str())); + error(MF_PARSER_UNEXPECTED_1(token.str())); require_token(m_tok_paren_left); token_t name = get_token(); - if (token.is(m_tok_NETLIST_START) && (name.str() == nlname || nlname.empty())) + if (token.is(m_tok_NETLIST_START) + && (name.str() == nlname || nlname.empty())) { require_token(m_tok_paren_right); parse_netlist(); @@ -132,29 +139,32 @@ namespace netlist m_local.emplace(name.str(), token_store_t()); m_cur_local = &m_local[name.str()]; auto sl = location(); - auto li = plib::pfmt("# {1} \"{2}\"")(sl.line(), sl.file_name()); + auto li = plib::pfmt( + "# {1} \"{2}\"")(sl.line(), sl.file_name()); m_cur_local->push_back(token_t(token_type::LINEMARKER, li)); m_cur_local->push_back(token); m_cur_local->push_back(token_t(m_tok_paren_left)); m_cur_local->push_back(name); - //m_cur_local->push_back(token_t(m_tok_paren_right)); + // m_cur_local->push_back(token_t(m_tok_paren_right)); in_nl = true; } - // FIXME: do we really need this going forward ? there should be no need + // FIXME: do we really need this going forward ? there should be no + // need // for NETLIST_EXTERNAL in netlist files else if (token.is(m_tok_NETLIST_EXTERNAL)) { if (in_nl) - error (MF_UNEXPECTED_NETLIST_EXTERNAL()); + error(MF_UNEXPECTED_NETLIST_EXTERNAL()); require_token(m_tok_paren_left); token_t name = get_token(); require_token(m_tok_paren_right); } else if (!in_nl) { - if (!token.is(m_tok_static) && !token.is_type(token_type::SOURCELINE) - && !token.is_type(token_type::LINEMARKER)) + if (!token.is(m_tok_static) + && !token.is_type(token_type::SOURCELINE) + && !token.is_type(token_type::LINEMARKER)) error(MF_EXPECTED_NETLIST_START_1(token.str())); } else @@ -171,7 +181,7 @@ namespace netlist token_t token = get_token(); if (token.is_type(token_type::ENDOFFILE)) - error (MF_UNEXPECTED_END_OF_FILE()); + error(MF_UNEXPECTED_END_OF_FILE()); m_setup.log().debug("Parser: Device: {1}\n", token.str()); @@ -237,7 +247,8 @@ namespace netlist else if (m_local.find(name) != m_local.end()) error(MF_EXTERNAL_SOURCE_IS_LOCAL_1(name)); - // FIXME: Need to pass in parameter definition FIXME: get line number right + // FIXME: Need to pass in parameter definition FIXME: get line number + // right m_setup.register_lib_entry(name, "", location()); require_token(m_tok_paren_right); } @@ -376,7 +387,6 @@ namespace netlist require_token(m_tok_paren_left); pstring name(get_identifier()); require_token(m_tok_paren_right); - } void parser_t::net_alias() @@ -403,7 +413,7 @@ namespace netlist while (true) { pstring t1 = get_identifier(); - m_setup.register_link(first , t1); + m_setup.register_link(first, t1); m_setup.log().debug("Parser: Connect: {1} {2}\n", first, t1); token_t n = get_token(); if (n.is(m_tok_paren_right)) @@ -411,7 +421,6 @@ namespace netlist if (!n.is(m_tok_comma)) error(MF_EXPECTED_COMMA_OR_RP_1(n.str())); } - } void parser_t::dip_pins() @@ -437,8 +446,8 @@ namespace netlist std::size_t n = pins.size(); for (std::size_t i = 0; i < n / 2; i++) { - m_setup.register_alias(plib::pfmt("{1}")(i+1), pins[i*2]); - m_setup.register_alias(plib::pfmt("{1}")(n-i), pins[i*2 + 1]); + m_setup.register_alias(plib::pfmt("{1}")(i + 1), pins[i * 2]); + m_setup.register_alias(plib::pfmt("{1}")(n - i), pins[i * 2 + 1]); } } @@ -471,7 +480,8 @@ namespace netlist token_t tok = get_token(); if (tok.is_type(token_type::STRING)) { - m_setup.log().debug("Parser: DefParam: {1} {2}\n", param, tok.str()); + m_setup.log().debug("Parser: DefParam: {1} {2}\n", param, + tok.str()); m_setup.register_default_param(param, tok.str()); require_token(m_tok_paren_right); } @@ -535,13 +545,13 @@ namespace netlist m_setup.register_dev(dev_type, devname, params); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // private - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- pstring parser_t::stringify_expression(token_t &tok) { - int pc(0); + int pc(0); pstring ret; while (!tok.is(m_tok_comma)) { @@ -549,7 +559,7 @@ namespace netlist pc++; else if (tok.is(m_tok_paren_right)) { - if (pc<=0) + if (pc <= 0) break; pc--; } @@ -559,9 +569,9 @@ namespace netlist return ret; } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // source_token_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- bool source_token_t::parse(nlparse_t &setup, const pstring &name) { @@ -574,7 +584,8 @@ namespace netlist return false; } - plib::istream_uptr source_token_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr source_token_t::stream( + [[maybe_unused]] const pstring &name) { return plib::istream_uptr(); } diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h index 0f5e135e9a6..87997866e32 100644 --- a/src/lib/netlist/nl_parser.h +++ b/src/lib/netlist/nl_parser.h @@ -8,8 +8,10 @@ #ifndef NL_PARSER_H_ #define NL_PARSER_H_ -#include "core/setup.h" #include "nltypes.h" // for setup_t + +#include "core/setup.h" + #include "plib/ptokenizer.h" #include @@ -51,6 +53,7 @@ namespace netlist void net_truth_table_start(const pstring &nlname); void verror(const pstring &msg) override; + private: void register_local_as_source(const pstring &name); @@ -86,16 +89,17 @@ namespace netlist token_id_t m_tok_TT_FAMILY; plib::tokenizer_t m_tokenizer; - nlparse_t &m_setup; + nlparse_t & m_setup; std::unordered_map m_local; - token_store_t *m_cur_local; + token_store_t * m_cur_local; }; class source_token_t : public source_netlist_t { public: - source_token_t(const pstring &name, const parser_t::token_store_t &store) + source_token_t(const pstring & name, + const parser_t::token_store_t &store) : m_store(store) , m_name(name) { @@ -108,10 +112,9 @@ namespace netlist private: parser_t::token_store_t m_store; - pstring m_name; + pstring m_name; }; - } // namespace netlist #endif // NL_PARSER_H_ diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index d8040258568..19ed531b853 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -1,35 +1,40 @@ // license:BSD-3-Clause // copyright-holders:Couriersud -#include "plib/palloc.h" -#include "core/devices.h" -#include "core/setup.h" -#include "devices/nlid_proxy.h" -#include "devices/nlid_truthtable.h" +#include "nl_setup.h" + #include "nl_errstr.h" #include "nl_factory.h" #include "nl_parser.h" -#include "nl_setup.h" + +#include "core/devices.h" +#include "core/setup.h" + +#include "devices/nlid_proxy.h" +#include "devices/nlid_truthtable.h" + +#include "solver/nld_solver.h" + +#include "plib/palloc.h" #include "plib/penum.h" #include "plib/pstonum.h" #include "plib/pstrutil.h" #include "plib/putil.h" -#include "solver/nld_solver.h" - #include namespace netlist { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // nl_parse_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- nlparse_t::nlparse_t(log_type &log, detail::abstract_t &abstract) : m_abstract(abstract) , m_log(log) , m_frontier_cnt(0) - { } + { + } void nlparse_t::register_alias(const pstring &alias, const pstring &out) { @@ -40,26 +45,29 @@ namespace netlist void nlparse_t::register_dip_alias_arr(const pstring &terms) { - const auto list(plib::psplit(terms,pstring(", "))); + const auto list(plib::psplit(terms, pstring(", "))); if (list.empty() || (list.size() % 2) == 1) { - log().fatal(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1(build_fqn(""))); - throw nl_exception(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1(build_fqn(""))); + log().fatal( + MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1(build_fqn(""))); + throw nl_exception( + MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1(build_fqn(""))); } std::size_t n = list.size(); for (std::size_t i = 0; i < n / 2; i++) { - register_alias(plib::pfmt("{1}")(i+1), list[i * 2]); - register_alias(plib::pfmt("{1}")(n-i), list[i * 2 + 1]); + register_alias(plib::pfmt("{1}")(i + 1), list[i * 2]); + register_alias(plib::pfmt("{1}")(n - i), list[i * 2 + 1]); } } - void nlparse_t::register_dev(const pstring &classname, - std::initializer_list more_parameters) + void + nlparse_t::register_dev(const pstring & classname, + std::initializer_list more_parameters) { std::vector params; - const auto *i(more_parameters.begin()); - pstring name(*i); + const auto * i(more_parameters.begin()); + pstring name(*i); ++i; for (; i != more_parameters.end(); ++i) { @@ -68,9 +76,10 @@ namespace netlist register_dev(classname, name, params); } - void nlparse_t::register_dev(const pstring &classname, const pstring &name, - const std::vector ¶ms_and_connections, - factory::element_t **factory_element) + void + nlparse_t::register_dev(const pstring &classname, const pstring &name, + const std::vector ¶ms_and_connections, + factory::element_t ** factory_element) { auto *f = factory().factory_by_name(classname); @@ -92,7 +101,8 @@ namespace netlist throw nl_exception(MF_DEVICE_ALREADY_EXISTS_1(key)); } - m_abstract.m_device_factory.insert(m_abstract.m_device_factory.end(), {key, f}); + m_abstract.m_device_factory.insert(m_abstract.m_device_factory.end(), + {key, f}); auto parameter_list = plib::psplit(f->param_desc(), ','); @@ -107,10 +117,11 @@ namespace netlist { if (token_ptr == token_end) { - auto err = MF_PARAM_COUNT_MISMATCH_2(name, params_and_connections.size()); + auto err = MF_PARAM_COUNT_MISMATCH_2( + name, params_and_connections.size()); log().fatal(err); throw nl_exception(err); - //break; + // break; } pstring output_name = *token_ptr; log().debug("Link: {1} {2}", tp, output_name); @@ -129,13 +140,15 @@ namespace netlist { if (token_ptr == token_end) { - auto err = MF_PARAM_COUNT_MISMATCH_2(name, params_and_connections.size()); + auto err = MF_PARAM_COUNT_MISMATCH_2( + name, params_and_connections.size()); log().fatal(err); throw nl_exception(err); } pstring fully_qualified_name = name + "." + tp; - log().debug("Default parameter: {1}\n", fully_qualified_name); + log().debug("Default parameter: {1}\n", + fully_qualified_name); register_param(fully_qualified_name, *token_ptr); @@ -144,7 +157,8 @@ namespace netlist } if (token_ptr != params_and_connections.end()) { - MF_PARAM_COUNT_EXCEEDED_2 err(name, params_and_connections.size()); + MF_PARAM_COUNT_EXCEEDED_2 err(name, + params_and_connections.size()); log().fatal(err); throw nl_exception(err); } @@ -153,7 +167,8 @@ namespace netlist *factory_element = f; } - void nlparse_t::register_hint(const pstring &object_name, const pstring &hint_name) + void nlparse_t::register_hint(const pstring &object_name, + const pstring &hint_name) { const auto name = build_fqn(object_name) + hint_name; if (!m_abstract.m_hints.insert({name, false}).second) @@ -165,12 +180,13 @@ namespace netlist void nlparse_t::register_link(const pstring &sin, const pstring &sout) { - register_link_fqn(build_fqn(plib::trim(sin)), build_fqn(plib::trim(sout))); + register_link_fqn(build_fqn(plib::trim(sin)), + build_fqn(plib::trim(sout))); } void nlparse_t::register_link_arr(const pstring &terms) { - const auto list(plib::psplit(terms,pstring(", "))); + const auto list(plib::psplit(terms, pstring(", "))); if (list.size() < 2) { log().fatal(MF_NET_C_NEEDS_AT_LEAST_2_TERMINAL()); @@ -184,10 +200,9 @@ namespace netlist void nlparse_t::include(const pstring &netlist_name) { - if (m_sources.for_all([this, &netlist_name] (source_netlist_t *src) - { - return src->parse(*this, netlist_name); - })) + if (m_sources.for_all( + [this, &netlist_name](source_netlist_t *src) + { return src->parse(*this, netlist_name); })) return; log().fatal(MF_NOT_FOUND_IN_SOURCE_COLLECTION(netlist_name)); throw nl_exception(MF_NOT_FOUND_IN_SOURCE_COLLECTION(netlist_name)); @@ -196,18 +211,16 @@ namespace netlist void nlparse_t::namespace_push(const pstring &aname) { if (m_namespace_stack.empty()) - //m_namespace_stack.push(netlist().name() + "." + aname); + // m_namespace_stack.push(netlist().name() + "." + aname); m_namespace_stack.push(aname); else m_namespace_stack.push(m_namespace_stack.top() + "." + aname); } - void nlparse_t::namespace_pop() - { - m_namespace_stack.pop(); - } + void nlparse_t::namespace_pop() { m_namespace_stack.pop(); } - void nlparse_t::register_param_fp(const pstring ¶m, const nl_fptype value) + void + nlparse_t::register_param_fp(const pstring ¶m, const nl_fptype value) { if (plib::abs(value - plib::floor(value)) > nlconst::magic(1e-30) || plib::abs(value) > nlconst::magic(1e9)) @@ -233,7 +246,8 @@ namespace netlist if (!m_abstract.m_param_values.insert({fqn, val}).second) { log().fatal(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param)); - throw nl_exception(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param)); + throw nl_exception( + MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param)); } } else @@ -241,14 +255,15 @@ namespace netlist if (idx->second.find("$(") == pstring::npos) { // There may be reason ... so make it an INFO - log().info(MI_OVERWRITING_PARAM_1_OLD_2_NEW_3(fqn, - idx->second, val)); + log().info( + MI_OVERWRITING_PARAM_1_OLD_2_NEW_3(fqn, idx->second, val)); } m_abstract.m_param_values[fqn] = val; } } - void nlparse_t::register_default_param(const pstring &name, const pstring &def) + void + nlparse_t::register_default_param(const pstring &name, const pstring &def) { // strip " from stringified strings pstring val(def); @@ -256,7 +271,8 @@ namespace netlist val = def.substr(1, def.length() - 2); // Replace "@." with the current namespace val = plib::replace_all(val, "@.", namespace_prefix()); - m_abstract.m_default_params.emplace_back(namespace_prefix() + name, val); + m_abstract.m_default_params.emplace_back(namespace_prefix() + name, + val); } factory::list_t &nlparse_t::factory() noexcept @@ -269,14 +285,16 @@ namespace netlist return m_abstract.m_factory; } - - void nlparse_t::register_lib_entry(const pstring &name, const pstring &def_params, plib::source_location &&loc) + void nlparse_t::register_lib_entry(const pstring & name, + const pstring & def_params, + plib::source_location &&loc) { - factory().add(plib::make_unique(name, factory::properties(def_params, std::move(loc)))); + factory().add(plib::make_unique( + name, factory::properties(def_params, std::move(loc)))); } - void nlparse_t::register_frontier(const pstring &attach, const pstring &r_IN, - const pstring &r_OUT) + void nlparse_t::register_frontier(const pstring &attach, + const pstring &r_IN, const pstring &r_OUT) { pstring frontier_name = plib::pfmt("frontier_{1}")(m_frontier_cnt); m_frontier_cnt++; @@ -286,8 +304,8 @@ namespace netlist register_link(frontier_name + ".G", "GND"); pstring attach_fully_qualified_name = build_fqn(attach); pstring front_fqn = build_fqn(frontier_name); - bool found = false; - for (auto & link : m_abstract.m_links) + bool found = false; + for (auto &link : m_abstract.m_links) { if (link.first == attach_fully_qualified_name) { @@ -313,9 +331,11 @@ namespace netlist register_source(name, func); } - void nlparse_t::truth_table_create(tt_desc &desc, const pstring &def_params, plib::source_location &&loc) + void nlparse_t::truth_table_create(tt_desc &desc, const pstring &def_params, + plib::source_location &&loc) { - auto fac = factory::truth_table_create(desc, netlist::factory::properties(def_params, std::move(loc))); + auto fac = factory::truth_table_create( + desc, netlist::factory::properties(def_params, std::move(loc))); factory().add(std::move(fac)); } @@ -329,7 +349,8 @@ namespace netlist return namespace_prefix() + obj_name; } - void nlparse_t::register_alias_no_fqn(const pstring &alias, const pstring &out) + void + nlparse_t::register_alias_no_fqn(const pstring &alias, const pstring &out) { if (!m_abstract.m_alias.insert({alias, out}).second) { @@ -353,13 +374,15 @@ namespace netlist return false; } - bool nlparse_t::parse_tokens(const plib::detail::token_store_t &tokens, const pstring &name) + bool nlparse_t::parse_tokens(const plib::detail::token_store_t &tokens, + const pstring & name) { parser_t parser(*this); return parser.parse(tokens, name); } - bool nlparse_t::parse_stream(plib::istream_uptr &&in_stream, const pstring &name) + bool + nlparse_t::parse_stream(plib::istream_uptr &&in_stream, const pstring &name) { #if 0 auto key = in_stream.filename(); @@ -380,12 +403,14 @@ namespace netlist } #else const auto filename = in_stream.filename(); - auto preprocessed = std::make_unique(putf8string( - plib::ppreprocessor(m_includes, &m_defines).process(std::move(in_stream), filename))); + auto preprocessed = std::make_unique( + putf8string(plib::ppreprocessor(m_includes, &m_defines) + .process(std::move(in_stream), filename))); parser_t::token_store_t st; - parser_t parser(*this); - parser.parse_tokens(plib::istream_uptr(std::move(preprocessed), filename), st); + parser_t parser(*this); + parser.parse_tokens( + plib::istream_uptr(std::move(preprocessed), filename), st); return parser.parse(st, name); #endif } @@ -394,12 +419,13 @@ namespace netlist { auto p = define.find('='); if (p != pstring::npos) - add_define(plib::left(define, p), define.substr(p+1)); + add_define(plib::left(define, p), define.substr(p + 1)); else add_define(define, "1"); } - void nlparse_t::register_dynamic_log_devices(const std::vector &log_list) + void nlparse_t::register_dynamic_log_devices( + const std::vector &log_list) { log().debug("Creating dynamic logs ..."); for (const pstring &ll : log_list) @@ -415,13 +441,16 @@ namespace netlist { // FIXME: check use_cases - remove_connections may be dead pstring pin_fully_qualified_name = build_fqn(pin); - bool found = false; + bool found = false; - for (auto link = m_abstract.m_links.begin(); link != m_abstract.m_links.end(); ) + for (auto link = m_abstract.m_links.begin(); + link != m_abstract.m_links.end();) { - if ((link->first == pin_fully_qualified_name) || (link->second == pin_fully_qualified_name)) + if ((link->first == pin_fully_qualified_name) + || (link->second == pin_fully_qualified_name)) { - log().verbose("removing connection: {1} <==> {2}\n", link->first, link->second); + log().verbose("removing connection: {1} <==> {2}\n", + link->first, link->second); link = m_abstract.m_links.erase(link); found = true; } @@ -445,15 +474,15 @@ namespace netlist if (!m_abstract.m_models.insert({model, def}).second) { // FIXME: Add an directive MODEL_OVERWRITE to netlist language - //throw nl_exception(MF_MODEL_ALREADY_EXISTS_1(model_in)); + // throw nl_exception(MF_MODEL_ALREADY_EXISTS_1(model_in)); log().info(MI_MODEL_OVERWRITE_1(model, model_in)); m_abstract.m_models[model] = def; } } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Sources - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- plib::istream_uptr nlparse_t::get_data_stream(const pstring &name) { @@ -464,17 +493,17 @@ namespace netlist return plib::istream_uptr(); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // setup_t - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- setup_t::setup_t(netlist_state_t &nlstate) - : m_abstract(nlstate.log()) - , m_parser(nlstate.log(), m_abstract) - , m_nlstate(nlstate) - , m_models(m_abstract.m_models) // FIXME : parse abstract_t only - , m_netlist_params(nullptr) - , m_proxy_cnt(0) + : m_abstract(nlstate.log()) + , m_parser(nlstate.log(), m_abstract) + , m_nlstate(nlstate) + , m_models(m_abstract.m_models) // FIXME : parse abstract_t only + , m_netlist_params(nullptr) + , m_proxy_cnt(0) { } @@ -482,33 +511,32 @@ namespace netlist { switch (in.type()) { - case detail::terminal_type::TERMINAL: - return "TERMINAL"; - case detail::terminal_type::INPUT: - return "INPUT"; - case detail::terminal_type::OUTPUT: - return "OUTPUT"; + case detail::terminal_type::TERMINAL: return "TERMINAL"; + case detail::terminal_type::INPUT: return "INPUT"; + case detail::terminal_type::OUTPUT: return "OUTPUT"; } return "Error"; // Tease gcc } - pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def) const + pstring setup_t::get_initial_param_val(const pstring &name, + const pstring &def) const { - // When `get_intial_param_val` is called the parameter `` is already registered - // and the value `(value_string())` is set to the default value, e.g. "74XX" - // If thus `$(IC5E.A.MODEL)` is given for `name=="IC5E.A.MODEL"` `value_string()` below - // will return the default. - // FIXME: It may be more explicit and stable to test if pattern==name and return - // `def` in this case. + // When `get_intial_param_val` is called the parameter `` is + // already registered and the value `(value_string())` is set to the + // default value, e.g. "74XX" If thus `$(IC5E.A.MODEL)` is given for + // `name=="IC5E.A.MODEL"` `value_string()` below will return the + // default. + // FIXME: It may be more explicit and stable to test if pattern==name + // and return `def` in this case. - auto i = m_abstract.m_param_values.find(name); - auto found_pat(false); + auto i = m_abstract.m_param_values.find(name); + auto found_pat(false); pstring v = (i == m_abstract.m_param_values.end()) ? def : i->second; do { found_pat = false; - auto sp(plib::psplit(v, std::vector({"$(", ")"}))); + auto sp(plib::psplit(v, std::vector({"$(", ")"}))); std::size_t p(0); v = ""; while (p < sp.size()) @@ -545,23 +573,31 @@ namespace netlist log().debug("{1} {2}\n", termtype_as_str(term), term.name()); if (!m_terminals.insert({term.name(), &term}).second) { - log().fatal(MF_ADDING_1_2_TO_TERMINAL_LIST(termtype_as_str(term), term.name())); - throw nl_exception(MF_ADDING_1_2_TO_TERMINAL_LIST(termtype_as_str(term), term.name())); + log().fatal(MF_ADDING_1_2_TO_TERMINAL_LIST(termtype_as_str(term), + term.name())); + throw nl_exception(MF_ADDING_1_2_TO_TERMINAL_LIST( + termtype_as_str(term), term.name())); } } - void setup_t::register_term(terminal_t &term, terminal_t *other_term, const std::array &splitter_terms) + void + setup_t::register_term(terminal_t &term, terminal_t *other_term, + const std::array &splitter_terms) { this->register_term(term); - m_connected_terminals.insert({&term, {other_term, splitter_terms[0], splitter_terms[1], nullptr}}); + m_connected_terminals.insert( + {&term, + {other_term, splitter_terms[0], splitter_terms[1], nullptr}}); } void setup_t::register_param_t(param_t ¶m) { - if (!m_params.insert({param.name(), param_ref_t(param.device(), param)}).second) + if (!m_params.insert({param.name(), param_ref_t(param.device(), param)}) + .second) { log().fatal(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param.name())); - throw nl_exception(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param.name())); + throw nl_exception( + MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST(param.name())); } } @@ -571,7 +607,8 @@ namespace netlist pstring ret; // FIXME: Detect endless loop - do { + do + { ret = temp; auto p = m_abstract.m_alias.find(ret); temp = (p != m_abstract.m_alias.end() ? p->second : ""); @@ -587,7 +624,8 @@ namespace netlist pstring ret; // FIXME: Detect endless loop - do { + do + { ret = temp; temp = ""; for (const auto &e : m_abstract.m_alias) @@ -605,32 +643,35 @@ namespace netlist return ret; } - std::vector setup_t::get_terminals_for_device_name(const pstring &devname) const + std::vector + setup_t::get_terminals_for_device_name(const pstring &devname) const { std::vector terms; - for (const auto & t : m_terminals) + for (const auto &t : m_terminals) { if (plib::startsWith(t.second->name(), devname)) { - pstring tn(t.second->name().substr(devname.length()+1)); + pstring tn(t.second->name().substr(devname.length() + 1)); if (tn.find('.') == pstring::npos) terms.push_back(tn); } } - for (const auto & t : m_abstract.m_alias) + for (const auto &t : m_abstract.m_alias) { if (plib::startsWith(t.first, devname)) { - pstring tn(t.first.substr(devname.length()+1)); + pstring tn(t.first.substr(devname.length() + 1)); if (tn.find('.') == pstring::npos) { terms.push_back(tn); pstring resolved = resolve_alias(t.first); if (resolved != t.first) { - auto found = std::find(terms.begin(), terms.end(), resolved.substr(devname.length()+1)); - if (found!=terms.end()) + auto found = std::find( + terms.begin(), terms.end(), + resolved.substr(devname.length() + 1)); + if (found != terms.end()) terms.erase(found); } } @@ -639,10 +680,11 @@ namespace netlist return terms; } - detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool required) const + detail::core_terminal_t * + setup_t::find_terminal(const pstring &terminal_in, bool required) const { const pstring &tname = resolve_alias(terminal_in); - auto ret = m_terminals.find(tname); + auto ret = m_terminals.find(tname); // look for default if (ret == m_terminals.end()) { @@ -650,7 +692,9 @@ namespace netlist ret = m_terminals.find(tname + ".Q"); } - detail::core_terminal_t *term = (ret == m_terminals.end() ? nullptr : ret->second); + detail::core_terminal_t *term = (ret == m_terminals.end() + ? nullptr + : ret->second); if (term == nullptr && required) { @@ -665,11 +709,12 @@ namespace netlist return term; } - detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, - detail::terminal_type atype, bool required) const + detail::core_terminal_t * + setup_t::find_terminal(const pstring & terminal_in, + detail::terminal_type atype, bool required) const { const pstring &tname = resolve_alias(terminal_in); - auto ret = m_terminals.find(tname); + auto ret = m_terminals.find(tname); // look for default if (ret == m_terminals.end() && atype == detail::terminal_type::OUTPUT) { @@ -681,14 +726,17 @@ namespace netlist log().fatal(MF_TERMINAL_1_2_NOT_FOUND(terminal_in, tname)); throw nl_exception(MF_TERMINAL_1_2_NOT_FOUND(terminal_in, tname)); } - detail::core_terminal_t *term = (ret == m_terminals.end() ? nullptr : ret->second); + detail::core_terminal_t *term = (ret == m_terminals.end() + ? nullptr + : ret->second); if (term != nullptr && term->type() != atype) { if (required) { log().fatal(MF_OBJECT_1_2_WRONG_TYPE(terminal_in, tname)); - throw nl_exception(MF_OBJECT_1_2_WRONG_TYPE(terminal_in, tname)); + throw nl_exception( + MF_OBJECT_1_2_WRONG_TYPE(terminal_in, tname)); } term = nullptr; @@ -702,30 +750,34 @@ namespace netlist param_ref_t setup_t::find_param(const pstring ¶m_in) const { const pstring resolved_param_name(resolve_alias(param_in)); - auto ret(m_params.find(resolved_param_name)); + auto ret(m_params.find(resolved_param_name)); if (ret == m_params.end()) { - log().fatal(MF_PARAMETER_1_2_NOT_FOUND(param_in, resolved_param_name)); - throw nl_exception(MF_PARAMETER_1_2_NOT_FOUND(param_in, resolved_param_name)); + log().fatal( + MF_PARAMETER_1_2_NOT_FOUND(param_in, resolved_param_name)); + throw nl_exception( + MF_PARAMETER_1_2_NOT_FOUND(param_in, resolved_param_name)); } return ret->second; } - //NOLINTNEXTLINE(misc-no-recursion) - devices::nld_base_proxy *setup_t::get_d_a_proxy(const detail::core_terminal_t &out) + // NOLINTNEXTLINE(misc-no-recursion) + devices::nld_base_proxy * + setup_t::get_d_a_proxy(const detail::core_terminal_t &out) { - gsl_Expects(out.is_logic()); - - const auto &out_cast = dynamic_cast(out); auto iter_proxy(m_proxies.find(&out)); if (iter_proxy != m_proxies.end()) return iter_proxy->second; // create a new one ... + + auto out_cast = plib::dynamic_downcast(out); + nl_assert_always(bool(out_cast), "Not able to cast to logic_output_t&"); + pstring x = plib::pfmt("proxy_da_{1}_{2}")(out.name())(m_proxy_cnt); - auto new_proxy = - out_cast.logic_family()->create_d_a_proxy(m_nlstate, x, &out_cast); + auto new_proxy = (*out_cast)->logic_family()->create_d_a_proxy( + m_nlstate, x, *out_cast); m_proxy_cnt++; // connect all existing terminals to new net @@ -734,15 +786,15 @@ namespace netlist // remove all terminals from out.net() out.net().remove_all_terminals(); - for (detail::core_terminal_t * p : temp_terminals) + for (detail::core_terminal_t *p : temp_terminals) { p->clear_net(); // de-link from all nets ... if (!connect(new_proxy->proxy_term(), *p)) { - log().fatal(MF_CONNECTING_1_TO_2( - new_proxy->proxy_term().name(), (*p).name())); + log().fatal(MF_CONNECTING_1_TO_2(new_proxy->proxy_term().name(), + (*p).name())); throw nl_exception(MF_CONNECTING_1_TO_2( - new_proxy->proxy_term().name(), (*p).name())); + new_proxy->proxy_term().name(), (*p).name())); } } @@ -754,15 +806,16 @@ namespace netlist m_nlstate.register_device(new_proxy->name(), std::move(new_proxy)); return proxy; - } - //NOLINTNEXTLINE(misc-no-recursion) - devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp) + // NOLINTNEXTLINE(misc-no-recursion) + devices::nld_base_proxy * + setup_t::get_a_d_proxy(detail::core_terminal_t &inp) { gsl_Expects(inp.is_logic()); - const auto &logic_input_terminal = dynamic_cast(inp); + const auto &logic_input_terminal = dynamic_cast( + inp); auto iter_proxy(m_proxies.find(&inp)); @@ -770,10 +823,9 @@ namespace netlist return iter_proxy->second; log().debug("connect_terminal_input: connecting proxy\n"); - auto new_proxy = - logic_input_terminal.logic_family()->create_a_d_proxy(m_nlstate, - plib::pfmt("proxy_ad_{1}_{2}")(inp.name())(m_proxy_cnt), - &logic_input_terminal); + auto new_proxy = logic_input_terminal.logic_family()->create_a_d_proxy( + m_nlstate, plib::pfmt("proxy_ad_{1}_{2}")(inp.name())(m_proxy_cnt), + &logic_input_terminal); auto *ret(new_proxy.get()); @@ -790,7 +842,7 @@ namespace netlist inp.net().remove_all_terminals(); - for (detail::core_terminal_t * p : temp_terminals) + for (detail::core_terminal_t *p : temp_terminals) { // inp may already belongs to the logic net. Thus skip it here. // It will be removed by the clear further down. @@ -800,9 +852,9 @@ namespace netlist if (!connect(ret->proxy_term(), *p)) { log().fatal(MF_CONNECTING_1_TO_2( - ret->proxy_term().name(), (*p).name())); + ret->proxy_term().name(), (*p).name())); throw nl_exception(MF_CONNECTING_1_TO_2( - ret->proxy_term().name(), (*p).name())); + ret->proxy_term().name(), (*p).name())); } } } @@ -813,19 +865,20 @@ namespace netlist return ret; } - detail::core_terminal_t &setup_t::resolve_proxy(detail::core_terminal_t &term) + detail::core_terminal_t & + setup_t::resolve_proxy(detail::core_terminal_t &term) { if (term.is_logic()) { const auto &out = dynamic_cast(term); - auto iter_proxy(m_proxies.find(&out)); + auto iter_proxy(m_proxies.find(&out)); if (iter_proxy != m_proxies.end()) return iter_proxy->second->proxy_term(); } return term; } - //NOLINTNEXTLINE(misc-no-recursion) + // NOLINTNEXTLINE(misc-no-recursion) void setup_t::merge_nets(detail::net_t &this_net, detail::net_t &other_net) { log().debug("merging nets ...\n"); @@ -837,8 +890,10 @@ namespace netlist if (this_net.is_rail_net() && other_net.is_rail_net()) { - log().fatal(MF_MERGE_RAIL_NETS_1_AND_2(this_net.name(), other_net.name())); - throw nl_exception(MF_MERGE_RAIL_NETS_1_AND_2(this_net.name(), other_net.name())); + log().fatal( + MF_MERGE_RAIL_NETS_1_AND_2(this_net.name(), other_net.name())); + throw nl_exception( + MF_MERGE_RAIL_NETS_1_AND_2(this_net.name(), other_net.name())); } if (other_net.is_rail_net()) @@ -852,90 +907,111 @@ namespace netlist } } - //NOLINTNEXTLINE(misc-no-recursion) - void setup_t::connect_input_output(detail::core_terminal_t &in, detail::core_terminal_t &out) + // NOLINTNEXTLINE(misc-no-recursion) + void setup_t::connect_input_output(detail::core_terminal_t &input, + detail::core_terminal_t &output) { - if (out.is_analog() && in.is_logic()) + if (input.has_net() && input.net().is_rail_net()) { - auto *proxy = get_a_d_proxy(in); - - out.net().add_terminal(proxy->proxy_term()); + log().fatal(MF_INPUT_1_ALREADY_CONNECTED(input.name())); + throw nl_exception(MF_INPUT_1_ALREADY_CONNECTED(input.name())); } - else if (out.is_logic() && in.is_analog()) + if (output.is_analog() && input.is_logic()) { - devices::nld_base_proxy *proxy = get_d_a_proxy(out); + auto *proxy = get_a_d_proxy(input); - connect_terminals(proxy->proxy_term(), in); - //proxy->out().net().register_con(in); + output.net().add_terminal(proxy->proxy_term()); + } + else if (output.is_logic() && input.is_analog()) + { + devices::nld_base_proxy *proxy = get_d_a_proxy(output); + + connect_terminals(proxy->proxy_term(), input); } else { - if (in.has_net()) - merge_nets(out.net(), in.net()); + if (input.has_net()) + merge_nets(output.net(), input.net()); + else if (output.has_net()) + output.net().add_terminal(input); else - out.net().add_terminal(in); + { + log().fatal( + ME_TERMINALS_1_2_WITHOUT_NET(input.name(), output.name())); + throw nl_exception( + ME_TERMINALS_1_2_WITHOUT_NET(input.name(), output.name())); + } } } - //NOLINTNEXTLINE(misc-no-recursion) - void setup_t::connect_terminal_input(terminal_t &term, detail::core_terminal_t &inp) + // NOLINTNEXTLINE(misc-no-recursion) + void setup_t::connect_terminal_input(detail::core_terminal_t &terminal, + detail::core_terminal_t &input) { - if (inp.is_analog()) + if (input.is_analog()) { - connect_terminals(inp, term); + connect_terminals(input, terminal); } - else if (inp.is_logic()) + else if (input.is_logic()) { - log().verbose("connect terminal {1} (in, {2}) to {3}\n", inp.name(), - inp.is_analog() ? "analog" : inp.is_logic() ? "logic" : "?", term.name()); - auto *proxy = get_a_d_proxy(inp); - - //out.net().register_con(proxy->proxy_term()); - connect_terminals(term, proxy->proxy_term()); + log().verbose("connect terminal {1} (in, {2}) to {3}\n", + input.name(), + input.is_analog() ? "analog" + : input.is_logic() ? "logic" + : "?", + terminal.name()); + auto *proxy = get_a_d_proxy(input); + // out.net().register_con(proxy->proxy_term()); + connect_terminals(terminal, proxy->proxy_term()); } else { - log().fatal(MF_OBJECT_INPUT_TYPE_1(inp.name())); - throw nl_exception(MF_OBJECT_INPUT_TYPE_1(inp.name())); + log().fatal(MF_OBJECT_INPUT_TYPE_1(input.name())); + throw nl_exception(MF_OBJECT_INPUT_TYPE_1(input.name())); } } - //NOLINTNEXTLINE(misc-no-recursion) - void setup_t::connect_terminal_output(terminal_t &in, detail::core_terminal_t &out) + // NOLINTNEXTLINE(misc-no-recursion) + void setup_t::connect_terminal_output(detail::core_terminal_t &terminal, + detail::core_terminal_t &output) { - if (out.is_analog()) + if (output.is_analog()) { - log().debug("connect_terminal_output: {1} {2}\n", in.name(), out.name()); + log().debug("connect_terminal_output: {1} {2}\n", terminal.name(), + output.name()); // no proxy needed, just merge existing terminal net - if (in.has_net()) + if (terminal.has_net()) { - if (&out.net() != &in.net()) - merge_nets(out.net(), in.net()); + if (&output.net() != &terminal.net()) + merge_nets(output.net(), terminal.net()); else - // Only an info - some ICs (CD4538) connect pins internally to GND - // and the schematics again externally. This will cause this warning. + // Only an info - some ICs (CD4538) connect pins internally + // to GND and the schematics again externally. This will + // cause this warning. // FIXME: Add a hint to suppress the warning. - log().info(MI_CONNECTING_1_TO_2_SAME_NET(in.name(), out.name(), in.net().name())); + log().info(MI_CONNECTING_1_TO_2_SAME_NET( + terminal.name(), output.name(), terminal.net().name())); } else - out.net().add_terminal(in); + output.net().add_terminal(terminal); } - else if (out.is_logic()) + else if (output.is_logic()) { log().debug("connect_terminal_output: connecting proxy\n"); - devices::nld_base_proxy *proxy = get_d_a_proxy(out); + devices::nld_base_proxy *proxy = get_d_a_proxy(output); - connect_terminals(proxy->proxy_term(), in); + connect_terminals(proxy->proxy_term(), terminal); } else { - log().fatal(MF_OBJECT_OUTPUT_TYPE_1(out.name())); - throw nl_exception(MF_OBJECT_OUTPUT_TYPE_1(out.name())); + log().fatal(MF_OBJECT_OUTPUT_TYPE_1(output.name())); + throw nl_exception(MF_OBJECT_OUTPUT_TYPE_1(output.name())); } } - void setup_t::connect_terminals(detail::core_terminal_t &t1,detail::core_terminal_t &t2) + void setup_t::connect_terminals(detail::core_terminal_t &t1, + detail::core_terminal_t &t2) { if (t1.has_net() && t2.has_net()) { @@ -956,7 +1032,8 @@ namespace netlist { log().debug("adding analog net ...\n"); // FIXME: Nets should have a unique name - auto new_net_uptr = plib::make_owned(nlstate().pool(), m_nlstate,"net." + t1.name()); + auto new_net_uptr = plib::make_owned( + nlstate().pool(), m_nlstate, "net." + t1.name()); auto *new_net_ptr = new_net_uptr.get(); m_nlstate.register_net(std::move(new_net_uptr)); t1.set_net(new_net_ptr); @@ -965,35 +1042,48 @@ namespace netlist } } - //NOLINTNEXTLINE(misc-no-recursion) - bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_terminal_t &t2) + // NOLINTNEXTLINE(misc-no-recursion) + bool setup_t::connect_input_input(detail::core_terminal_t &input1, + detail::core_terminal_t &input2) { bool ret = false; - if (t1.has_net()) + if (input1.has_net()) // if input 1 already has a net { - if (t1.net().is_rail_net()) - ret = connect(t2, t1.net().rail_terminal()); + if (input1.net().is_rail_net()) // and the net is a rail net + ret = connect(input2, input1.net().rail_terminal()); // try to + // connect + // input 2 + // to rail + // terminal + // of input + // 1 net if (!ret) { - for (detail::core_terminal_t * t : t1.net().core_terms_copy()) + // the above was not successfull - try to connect input2 to + // TERMINAL type terminals of input 1 net's terminals + for (detail::core_terminal_t *t : + input1.net().core_terms_copy()) { if (t->is_type(detail::terminal_type::TERMINAL)) - ret = connect(t2, *t); + ret = connect(input2, *t); if (ret) break; } } } - if (!ret && t2.has_net()) + // FIXME: We could use a helper connect_input_input_helper(input2, + // input1) here. + if (!ret && input2.has_net()) { - if (t2.net().is_rail_net()) - ret = connect(t1, t2.net().rail_terminal()); + if (input2.net().is_rail_net()) + ret = connect(input1, input2.net().rail_terminal()); if (!ret) { - for (detail::core_terminal_t * t : t2.net().core_terms_copy()) + for (detail::core_terminal_t *t : + input2.net().core_terms_copy()) { if (t->is_type(detail::terminal_type::TERMINAL)) - ret = connect(t1, *t); + ret = connect(input1, *t); if (ret) break; } @@ -1002,59 +1092,67 @@ namespace netlist return ret; } - //NOLINTNEXTLINE(misc-no-recursion) - bool setup_t::connect(detail::core_terminal_t &t1_in, detail::core_terminal_t &t2_in) + // NOLINTNEXTLINE(misc-no-recursion) + bool setup_t::connect(detail::core_terminal_t &t1_in, + detail::core_terminal_t &t2_in) { + using namespace detail; + log().debug("Connecting {1} to {2}\n", t1_in.name(), t2_in.name()); detail::core_terminal_t &t1 = resolve_proxy(t1_in); detail::core_terminal_t &t2 = resolve_proxy(t2_in); - bool ret = true; + detail::terminal_type t1_type = t1.type(); + detail::terminal_type t2_type = t2.type(); + bool ret = true; - if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::INPUT)) + switch (t1_type) { - if (t2.has_net() && t2.net().is_rail_net()) + case terminal_type::TERMINAL: { - log().fatal(MF_INPUT_1_ALREADY_CONNECTED(t2.name())); - throw nl_exception(MF_INPUT_1_ALREADY_CONNECTED(t2.name())); + switch (t2_type) + { + case terminal_type::TERMINAL: + connect_terminals(t1, t2); + break; + case terminal_type::INPUT: + connect_terminal_input(t1, t2); + break; + case terminal_type::OUTPUT: + connect_terminal_output(t1, t2); + break; + } + break; } - connect_input_output(t2, t1); - } - else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::OUTPUT)) - { - if (t1.has_net() && t1.net().is_rail_net()) + case terminal_type::INPUT: { - log().fatal(MF_INPUT_1_ALREADY_CONNECTED(t1.name())); - throw nl_exception(MF_INPUT_1_ALREADY_CONNECTED(t1.name())); + switch (t2_type) + { + case terminal_type::TERMINAL: + connect_terminal_input(t2, t1); + break; + case terminal_type::INPUT: + ret = connect_input_input(t1, t2); + break; + case terminal_type::OUTPUT: + connect_input_output(t1, t2); + break; + } + break; + } + case terminal_type::OUTPUT: + { + switch (t2_type) + { + case terminal_type::TERMINAL: + connect_terminal_output(t2, t1); + break; + case terminal_type::INPUT: + connect_input_output(t2, t1); + break; + case terminal_type::OUTPUT: ret = false; break; + } + break; } - connect_input_output(t1, t2); - } - else if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::TERMINAL)) - { - connect_terminal_output(dynamic_cast(t2), t1); - } - else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::OUTPUT)) - { - connect_terminal_output(dynamic_cast(t1), t2); - } - else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::TERMINAL)) - { - connect_terminal_input(dynamic_cast(t2), t1); - } - else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::INPUT)) - { - connect_terminal_input(dynamic_cast(t1), t2); - } - else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::TERMINAL)) - { - connect_terminals(dynamic_cast(t1), dynamic_cast(t2)); - } - else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::INPUT)) - { - ret = connect_input_input(t1, t2); - } - else - { - ret = false; } return ret; } @@ -1068,7 +1166,7 @@ namespace netlist // after all other terminals were connected. unsigned tries = m_netlist_params->m_max_link_loops(); - #if 0 +#if 0 // This code fails for some netlists when the element at position 0 // is deleted. It will fail somewhere deep in std::pair releasing // std::string called from erase. @@ -1112,30 +1210,35 @@ namespace netlist } tries--; } - #else +#else while (!m_abstract.m_links.empty() && tries > 0) { - for (std::size_t i = 0; i < m_abstract.m_links.size(); ) + for (std::size_t i = 0; i < m_abstract.m_links.size();) { - const pstring t1s(m_abstract.m_links[i].first); - const pstring t2s(m_abstract.m_links[i].second); + const pstring t1s(m_abstract.m_links[i].first); + const pstring t2s(m_abstract.m_links[i].second); detail::core_terminal_t *t1 = find_terminal(t1s); detail::core_terminal_t *t2 = find_terminal(t2s); if (connect(*t1, *t2)) - m_abstract.m_links.erase(m_abstract.m_links.begin() + plib::narrow_cast(i)); + m_abstract.m_links.erase( + m_abstract.m_links.begin() + + plib::narrow_cast(i)); else i++; } tries--; } - #endif +#endif if (tries == 0) { - for (auto & link : m_abstract.m_links) - log().warning(MF_CONNECTING_1_TO_2(de_alias(link.first), de_alias(link.second))); + for (auto &link : m_abstract.m_links) + log().warning(MF_CONNECTING_1_TO_2(de_alias(link.first), + de_alias(link.second))); - log().fatal(MF_LINK_TRIES_EXCEEDED(m_netlist_params->m_max_link_loops())); - throw nl_exception(MF_LINK_TRIES_EXCEEDED(m_netlist_params->m_max_link_loops())); + log().fatal( + MF_LINK_TRIES_EXCEEDED(m_netlist_params->m_max_link_loops())); + throw nl_exception( + MF_LINK_TRIES_EXCEEDED(m_netlist_params->m_max_link_loops())); } log().verbose("deleting empty nets ..."); @@ -1147,11 +1250,13 @@ namespace netlist bool err(false); log().verbose("looking for terminals not connected ..."); - for (auto & i : m_terminals) + for (auto &i : m_terminals) { detail::core_terminal_t *term = i.second; - const pstring name_da = de_alias(term->name()); - bool is_nc_pin(dynamic_cast< devices::NETLIB_NAME(nc_pin) *>(&term->device()) != nullptr); + const pstring name_da = de_alias(term->name()); + bool is_nc_pin( + dynamic_cast(&term->device()) + != nullptr); bool is_nc_flagged(false); auto hnc = m_abstract.m_hints.find(name_da + sHINT_NC); @@ -1178,16 +1283,19 @@ namespace netlist else if (term->net().core_terms_empty()) { if (term->is_logic_input()) - log().warning(MW_LOGIC_INPUT_1_WITHOUT_CONNECTIONS(name_da)); + log().warning( + MW_LOGIC_INPUT_1_WITHOUT_CONNECTIONS(name_da)); else if (term->is_logic_output()) { if (!is_nc_flagged) - log().info(MI_LOGIC_OUTPUT_1_WITHOUT_CONNECTIONS(name_da)); + log().info( + MI_LOGIC_OUTPUT_1_WITHOUT_CONNECTIONS(name_da)); } else if (term->is_analog_output()) { if (!is_nc_flagged) - log().info(MI_ANALOG_OUTPUT_1_WITHOUT_CONNECTIONS(name_da)); + log().info( + MI_ANALOG_OUTPUT_1_WITHOUT_CONNECTIONS(name_da)); } else log().warning(MW_TERMINAL_1_WITHOUT_CONNECTIONS(name_da)); @@ -1195,7 +1303,7 @@ namespace netlist } log().verbose("checking tristate consistency ..."); - for (auto & i : m_terminals) + for (auto &i : m_terminals) { detail::core_terminal_t *term = i.second; if (term->is_tristate_output()) @@ -1206,12 +1314,14 @@ namespace netlist if (iter_proxy == m_proxies.end() && !tri.is_force_logic()) { - log().error(ME_TRISTATE_NO_PROXY_FOUND_2(term->name(), term->device().name())); + log().error(ME_TRISTATE_NO_PROXY_FOUND_2( + term->name(), term->device().name())); err = true; } else if (iter_proxy != m_proxies.end() && tri.is_force_logic()) { - log().error(ME_TRISTATE_PROXY_FOUND_2(term->name(), term->device().name())); + log().error(ME_TRISTATE_PROXY_FOUND_2( + term->name(), term->device().name())); err = true; } } @@ -1221,7 +1331,6 @@ namespace netlist log().fatal(MF_TERMINALS_WITHOUT_NET()); throw nl_exception(MF_TERMINALS_WITHOUT_NET()); } - } void setup_t::move_connections(detail::net_t &net, detail::net_t &dest_net) @@ -1230,30 +1339,31 @@ namespace netlist net.remove_all_terminals(); - for (detail::core_terminal_t * ct : temp) + for (detail::core_terminal_t *ct : temp) { dest_net.add_terminal(*ct); } } - log_type &setup_t::log() noexcept { return m_nlstate.log(); } + log_type & setup_t::log() noexcept { return m_nlstate.log(); } const log_type &setup_t::log() const noexcept { return m_nlstate.log(); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Models - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - //NOLINTNEXTLINE(misc-no-recursion) + // NOLINTNEXTLINE(misc-no-recursion) void models_t::model_parse(const pstring &model_in, map_t &map) { - pstring model = model_in; + pstring model = model_in; std::size_t pos = 0; - pstring key; + pstring key; while (true) { pos = model.find('('); - if (pos != pstring::npos) break; + if (pos != pstring::npos) + break; key = plib::ucase(model); auto i = m_models.find(key); @@ -1283,7 +1393,7 @@ namespace netlist // FIMXE: Not optimal remainder = plib::left(remainder, remainder.length() - 1); - const auto pairs(plib::psplit(remainder,' ', true)); + const auto pairs(plib::psplit(remainder, ' ', true)); for (const pstring &pe : pairs) { auto pose = pe.find('='); @@ -1297,7 +1407,7 @@ namespace netlist { // operator [] has no const implementation pstring ret = map.at("COREMODEL") + "("; - for (const auto & i : map) + for (const auto &i : map) ret += (i.first + '=' + i.second + ' '); return ret + ")"; @@ -1308,18 +1418,20 @@ namespace netlist map_t &map = m_cache[model]; if (map.empty()) - model_parse(model , map); + model_parse(model, map); - return { model, map }; + return {model, map}; } pstring models_t::model_t::value_str(const pstring &entity) const { if (entity != plib::ucase(entity)) - throw nl_exception(MF_MODEL_PARAMETERS_NOT_UPPERCASE_1_2(entity, model_string(m_map))); + throw nl_exception(MF_MODEL_PARAMETERS_NOT_UPPERCASE_1_2( + entity, model_string(m_map))); const auto it(m_map.find(entity)); - if ( it == m_map.end()) - throw nl_exception(MF_ENTITY_1_NOT_FOUND_IN_MODEL_2(entity, model_string(m_map))); + if (it == m_map.end()) + throw nl_exception( + MF_ENTITY_1_NOT_FOUND_IN_MODEL_2(entity, model_string(m_map))); return it->second; } @@ -1329,21 +1441,24 @@ namespace netlist pstring tmp = value_str(entity); nl_fptype factor = nlconst::one(); - auto p = std::next(tmp.begin(), plib::narrow_cast(tmp.length() - 1)); + auto p = std::next( + tmp.begin(), + plib::narrow_cast(tmp.length() - 1)); switch (*p) { case 'M': factor = nlconst::magic(1e6); break; // NOLINT case 'k': - case 'K': factor = nlconst::magic(1e3); break; // NOLINT - case 'm': factor = nlconst::magic(1e-3); break; // NOLINT - case 'u': factor = nlconst::magic(1e-6); break; // NOLINT - case 'n': factor = nlconst::magic(1e-9); break; // NOLINT + case 'K': factor = nlconst::magic(1e3); break; // NOLINT + case 'm': factor = nlconst::magic(1e-3); break; // NOLINT + case 'u': factor = nlconst::magic(1e-6); break; // NOLINT + case 'n': factor = nlconst::magic(1e-9); break; // NOLINT case 'p': factor = nlconst::magic(1e-12); break; // NOLINT case 'f': factor = nlconst::magic(1e-15); break; // NOLINT case 'a': factor = nlconst::magic(1e-18); break; // NOLINT default: if (*p < '0' || *p > '9') - throw nl_exception(MF_UNKNOWN_NUMBER_FACTOR_IN_2(m_model, entity)); + throw nl_exception( + MF_UNKNOWN_NUMBER_FACTOR_IN_2(m_model, entity)); } if (factor != nlconst::one()) tmp = plib::left(tmp, tmp.length() - 1); @@ -1351,22 +1466,17 @@ namespace netlist bool err(false); auto val = plib::pstonum_ne(tmp, err); if (err) - throw nl_exception(MF_MODEL_NUMBER_CONVERSION_ERROR(entity, tmp, "double", m_model)); + throw nl_exception(MF_MODEL_NUMBER_CONVERSION_ERROR( + entity, tmp, "double", m_model)); return val * factor; } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // logic_family_std_proxy_t // // FIXME: all this belongs elsewhere - // ---------------------------------------------------------------------------------------- - PENUM(family_type, - CUSTOM, - TTL, - MOS, - CMOS, - NMOS, - PMOS) + // ------------------------------------------------------------------------- + PENUM(family_type, CUSTOM, TTL, MOS, CMOS, NMOS, PMOS) class logic_family_std_proxy_t : public logic_family_desc_t { @@ -1377,10 +1487,11 @@ namespace netlist } // FIXME: create proxies based on family type (far future) - device_arena::unique_ptr create_d_a_proxy(netlist_state_t &anetlist, - const pstring &name, const logic_output_t *proxied) const override + device_arena::unique_ptr + create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, + const logic_output_t *proxied) const override { - switch(m_family_type) + switch (m_family_type) { case family_type::CUSTOM: case family_type::TTL: @@ -1388,14 +1499,18 @@ namespace netlist case family_type::CMOS: case family_type::NMOS: case family_type::PMOS: - return anetlist.make_pool_object(anetlist, name, proxied); + return anetlist.make_pool_object( + device_data_t{anetlist, name}, proxied); } - return anetlist.make_pool_object(anetlist, name, proxied); + return anetlist.make_pool_object( + device_data_t{anetlist, name}, proxied); } - device_arena::unique_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const override + device_arena::unique_ptr + create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, + const logic_input_t *proxied) const override { - switch(m_family_type) + switch (m_family_type) { case family_type::CUSTOM: case family_type::TTL: @@ -1403,14 +1518,18 @@ namespace netlist case family_type::CMOS: case family_type::NMOS: case family_type::PMOS: - return anetlist.make_pool_object(anetlist, name, proxied); + return anetlist.make_pool_object( + device_data_t{anetlist, name}, proxied); } - return anetlist.make_pool_object(anetlist, name, proxied); + return anetlist.make_pool_object( + device_data_t{anetlist, name}, proxied); } + private: family_type m_family_type; }; + // clang-format off /// \brief Class representing the logic families. /// /// This is the model representation of the logic families. This is a @@ -1426,6 +1545,7 @@ namespace netlist /// | Y |ORL |Output output resistance for logic 0 | | 0| /// | Y |ORH |Output output resistance for logic 1 | | 0| /// + // clang-format on class family_model_t { public: @@ -1438,22 +1558,27 @@ namespace netlist , m_OVH(model, "OVH") , m_ORL(model, "ORL") , m_ORH(model, "ORH") - {} + { + } param_model_t::value_str_t m_TYPE; //!< Family type (TTL, CMOS, ...) - param_model_t::value_t m_IVL; //!< Input voltage low threshold relative to supply voltage - param_model_t::value_t m_IVH; //!< Input voltage high threshold relative to supply voltage - param_model_t::value_t m_OVL; //!< Output voltage minimum voltage relative to supply voltage - param_model_t::value_t m_OVH; //!< Output voltage maximum voltage relative to supply voltage - param_model_t::value_t m_ORL; //!< Output output resistance for logic 0 - param_model_t::value_t m_ORH; //!< Output output resistance for logic 1 + param_model_t::value_t m_IVL; //!< Input voltage low threshold relative + //!< to supply voltage + param_model_t::value_t m_IVH; //!< Input voltage high threshold relative + //!< to supply voltage + param_model_t::value_t m_OVL; //!< Output voltage minimum voltage + //!< relative to supply voltage + param_model_t::value_t m_OVH; //!< Output voltage maximum voltage + //!< relative to supply voltage + param_model_t::value_t m_ORL; //!< Output output resistance for logic 0 + param_model_t::value_t m_ORH; //!< Output output resistance for logic 1 }; const logic_family_desc_t *setup_t::family_from_model(const pstring &model) { family_type ft(family_type::CUSTOM); - auto mod(m_models.get_model(model)); + auto mod(m_models.get_model(model)); family_model_t modv(mod); if (!ft.set_from_string(modv.m_TYPE())) @@ -1495,30 +1620,35 @@ namespace netlist return retp; } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Device handling - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- void setup_t::delete_empty_nets() { m_nlstate.nets().erase( - std::remove_if(m_nlstate.nets().begin(), m_nlstate.nets().end(), + std::remove_if( + m_nlstate.nets().begin(), m_nlstate.nets().end(), [](device_arena::owned_ptr &net) { if (net->core_terms_empty()) { - // FIXME: need to remove from state->m_core_terms as well. - net->state().log().verbose("Deleting net {1} ...", net->name()); - net->state().run_state_manager().remove_save_items(net.get()); + // FIXME: need to remove from state->m_core_terms as + // well. + net->state().log().verbose("Deleting net {1} ...", + net->name()); + net->state().run_state_manager().remove_save_items( + net.get()); return true; } return false; - }), m_nlstate.nets().end()); + }), + m_nlstate.nets().end()); } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // Run preparation - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- void setup_t::prepare_to_run() { @@ -1532,55 +1662,68 @@ namespace netlist // create default parameters first! - for (auto & e : m_abstract.m_default_params) + for (auto &e : m_abstract.m_default_params) { - auto param(plib::make_unique(nlstate(), e.first, e.second)); + auto param(plib::make_unique( + nlstate(), e.first, e.second)); register_param_t(*param); m_defparam_lifetime.push_back(std::move(param)); } // make sure the solver and parameters are started first! - for (auto & e : m_abstract.m_device_factory) + for (auto &e : m_abstract.m_device_factory) { - if ( m_parser.factory().is_class(e.second) - || m_parser.factory().is_class(e.second)) + if (m_parser.factory().is_class( + e.second) + || m_parser.factory() + .is_class(e.second)) { - m_nlstate.register_device(e.first, e.second->make_device(nlstate().pool(), m_nlstate, e.first)); + m_nlstate.register_device( + e.first, e.second->make_device(nlstate().pool(), m_nlstate, + e.first)); } } log().debug("Searching for solver and parameters ...\n"); - auto *solver = m_nlstate.get_single_device("solver"); - m_netlist_params = m_nlstate.get_single_device("parameter"); + auto *solver = m_nlstate + .get_single_device( + "solver"); + m_netlist_params = m_nlstate.get_single_device< + devices::NETLIB_NAME(netlistparams)>("parameter"); // set default model parameters // FIXME: this is not optimal - m_parser.register_model(plib::pfmt("NMOS_DEFAULT _(CAPMOD={1})")(m_netlist_params->m_mos_cap_model())); - m_parser.register_model(plib::pfmt("PMOS_DEFAULT _(CAPMOD={1})")(m_netlist_params->m_mos_cap_model())); + m_parser.register_model(plib::pfmt("NMOS_DEFAULT _(CAPMOD={1})")( + m_netlist_params->m_mos_cap_model())); + m_parser.register_model(plib::pfmt("PMOS_DEFAULT _(CAPMOD={1})")( + m_netlist_params->m_mos_cap_model())); // create devices log().debug("Creating devices ...\n"); - for (auto & e : m_abstract.m_device_factory) + for (auto &e : m_abstract.m_device_factory) { - if ( !m_parser.factory().is_class(e.second) - && !m_parser.factory().is_class(e.second)) + if (!m_parser.factory().is_class( + e.second) + && !m_parser.factory() + .is_class( + e.second)) { - auto dev = e.second->make_device(m_nlstate.pool(), m_nlstate, e.first); + auto dev = e.second->make_device(m_nlstate.pool(), m_nlstate, + e.first); m_nlstate.register_device(dev->name(), std::move(dev)); } } - int error_count(0); - const bool use_deactivate = m_netlist_params->m_use_deactivate(); for (auto &d : m_nlstate.devices()) { - auto p = m_abstract.m_hints.find(d.second->name() + sHINT_NO_DEACTIVATE); + auto p = m_abstract.m_hints.find(d.second->name() + + sHINT_NO_DEACTIVATE); if (p != m_abstract.m_hints.end()) { p->second = true; // mark as used @@ -1590,38 +1733,36 @@ namespace netlist d.second->set_hint_deactivate(use_deactivate); } - if (error_count > 0) - { - log().fatal(MF_ERRORS_FOUND(error_count)); - throw nl_exception(MF_ERRORS_FOUND(error_count)); - } - // resolve inputs resolve_inputs(); log().verbose("looking for two terms connected to rail nets ..."); - for (auto & t : m_nlstate.get_device_list()) + for (auto &t : + m_nlstate.get_device_list()) { if (t->N().net().is_rail_net() && t->P().net().is_rail_net()) { log().info(MI_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3( t->name(), t->N().net().name(), t->P().net().name())); - // The following would remove internal devices in e.g. MOSFETs as well. - #if 0 + // The following would remove internal devices in e.g. MOSFETs + // as well. +#if 0 remove_terminal(t->setup_N().net(), t->setup_N()); remove_terminal(t->setup_P().net(), t->setup_P()); m_nlstate.remove_device(t); - #endif +#endif } } + int error_count = 0; + log().verbose("looking for unused hints ..."); for (auto &h : m_abstract.m_hints) { if (!h.second) { - log().fatal(MF_UNUSED_HINT_1(h.first)); - throw nl_exception(MF_UNUSED_HINT_1(h.first)); + log().error(MF_UNUSED_HINT_1(h.first)); + error_count++; } } @@ -1632,14 +1773,13 @@ namespace netlist for (auto &p : m_nlstate.nets()) if (p->is_analog()) { - log().fatal(MF_NO_SOLVER()); - throw nl_exception(MF_NO_SOLVER()); + log().error(MF_NO_SOLVER()); + error_count++; } } else solver->post_start(); - error_count = 0; log().debug("Looking for unknown parameters ...\n"); for (auto &p : m_abstract.m_param_values) { @@ -1650,66 +1790,78 @@ namespace netlist error_count++; } } + + for (auto &n : m_nlstate.nets()) + { + for (detail::core_terminal_t *term : n->core_terms_copy()) + if (term->delegate().isnull()) + { + log().error(MF_DELEGATE_NOT_SET_1(term->name())); + error_count++; + } + n->rebuild_list(); + } + if (error_count > 0) { log().fatal(MF_ERRORS_FOUND(error_count)); throw nl_exception(MF_ERRORS_FOUND(error_count)); } - - for (auto &n : m_nlstate.nets()) - { - for (detail::core_terminal_t * term : n->core_terms_copy()) - if (term->delegate().isnull()) - { - log().fatal(MF_DELEGATE_NOT_SET_1(term->name())); - throw nl_exception(MF_DELEGATE_NOT_SET_1(term->name())); - } - n->rebuild_list(); - } } - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // base sources - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- bool source_netlist_t::parse(nlparse_t &setup, const pstring &name) { auto strm(stream(name)); - return (!strm.empty()) ? setup.parse_stream(std::move(strm), name) : false; + return (!strm.empty()) ? setup.parse_stream(std::move(strm), name) + : false; } - plib::istream_uptr source_string_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr + source_string_t::stream([[maybe_unused]] const pstring &name) { - plib::istream_uptr ret(std::make_unique(putf8string(m_str)), name); + plib::istream_uptr ret( + std::make_unique(putf8string(m_str)), name); ret->imbue(std::locale::classic()); return ret; } - plib::istream_uptr source_mem_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr + source_mem_t::stream([[maybe_unused]] const pstring &name) { - plib::istream_uptr ret(std::make_unique(m_str, std::ios_base::binary), name); + plib::istream_uptr ret( + std::make_unique(m_str, std::ios_base::binary), + name); ret->imbue(std::locale::classic()); return ret; } - plib::istream_uptr source_file_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr + source_file_t::stream([[maybe_unused]] const pstring &name) { - auto f = std::make_unique(plib::filesystem::u8path(m_filename)); + auto f = std::make_unique( + plib::filesystem::u8path(m_filename)); if (f->is_open()) { - return { std::move(f), m_filename }; + return {std::move(f), m_filename}; } return plib::istream_uptr(); } - plib::istream_uptr source_pattern_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr + source_pattern_t::stream([[maybe_unused]] const pstring &name) { - pstring filename = plib::pfmt(m_pattern)(m_force_lowercase ? plib::lcase(name) : name); - auto f = std::make_unique(plib::filesystem::u8path(filename)); + pstring filename = plib::pfmt(m_pattern)( + m_force_lowercase ? plib::lcase(name) : name); + auto f = std::make_unique( + plib::filesystem::u8path(filename)); if (f->is_open()) { - return { std::move(f), filename }; + return {std::move(f), filename}; } return plib::istream_uptr(); @@ -1726,10 +1878,10 @@ namespace netlist return false; } - plib::istream_uptr source_proc_t::stream([[maybe_unused]] const pstring &name) + plib::istream_uptr + source_proc_t::stream([[maybe_unused]] const pstring &name) { return plib::istream_uptr(); } } // namespace netlist - diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index d22b78c3703..dad4f894375 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -107,15 +107,26 @@ void NETLIST_NAME(name)([[maybe_unused]] netlist::nlparse_t &setup) \ // truth table defines // ----------------------------------------------------------------------------- +#if 0 #define TRUTHTABLE_START(cname, in, out, pdef_params) \ - NETLIST_START(cname) \ - netlist::tt_desc desc; \ - desc.name = #cname ; \ - desc.ni = in; \ - desc.no = out; \ - desc.family = ""; \ + void NETLIST_NAME(cname ## _impl)(netlist::tt_desc &desc); \ + static NETLIST_START(cname) \ + netlist::tt_desc xdesc{ #cname, in, out, "" }; \ auto sloc = PSOURCELOC(); \ - const pstring def_params = pdef_params; + const pstring def_params = pdef_params; \ + NETLIST_NAME(cname ## _impl)(xdesc); \ + setup.truth_table_create(xdesc, def_params, std::move(sloc)); \ + NETLIST_END() \ + static void NETLIST_NAME(cname ## _impl)(netlist::tt_desc &desc) \ + { +#else +#define TRUTHTABLE_START(cname, in, out, pdef_params) \ + NETLIST_START(cname) \ + netlist::tt_desc desc{ #cname, in, out, "", {} }; \ + auto sloc = PSOURCELOC(); \ + const pstring def_params = pdef_params; \ + plib::functor_guard lg([&](){ setup.truth_table_create(desc, def_params, std::move(sloc)); }); +#endif #define TT_HEAD(x) \ desc.desc.emplace_back(x); @@ -127,7 +138,6 @@ void NETLIST_NAME(name)([[maybe_unused]] netlist::nlparse_t &setup) \ desc.family = x; #define TRUTHTABLE_END() \ - setup.truth_table_create(desc, def_params, std::move(sloc)); \ NETLIST_END() #define TRUTHTABLE_ENTRY(name) \ @@ -143,12 +153,11 @@ namespace netlist struct tt_desc { - tt_desc() : ni(0), no(0) { } pstring name; unsigned long ni; unsigned long no; - std::vector desc; pstring family; + std::vector desc; }; // ---------------------------------------------------------------------------------------- @@ -174,7 +183,7 @@ namespace netlist // last argument only needed by nltool void register_dev(const pstring &classname, const pstring &name, const std::vector ¶ms_and_connections, - factory::element_t **felem = nullptr); + factory::element_t **factory_element = nullptr); void register_dev(const pstring &classname, std::initializer_list more_parameters); void register_dev(const pstring &classname, const pstring &name) { diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 6dcef5ad1df..3e36fd912d9 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -24,8 +24,7 @@ /// \brief Construct a netlist device name /// -#define NETLIB_NAME(chip) nld_ ## chip - +#define NETLIB_NAME(chip) nld_##chip namespace netlist { @@ -43,14 +42,24 @@ namespace netlist class netlist_t; class netlist_state_t; class core_device_t; + class base_device_t; class device_t; class netlist_state_t; class param_t; class logic_family_desc_t; + class logic_family_std_proxy_t; class terminal_t; + template + struct sub_device_wrapper; + class models_t; + namespace analog + { + class NETLIB_NAME(two_terminal); + } // namespace analog + namespace devices { class nld_solver; @@ -59,6 +68,9 @@ namespace netlist class nld_base_d_to_a_proxy; class nld_base_a_to_d_proxy; class nld_netlistparams; + + template + class factory_truth_table_t; } // namespace devices namespace solver @@ -76,20 +88,15 @@ namespace netlist namespace factory { + template + class device_element_t; + class library_element_t; + class list_t; class element_t; struct properties; } // namespace factory - template - class delegator_t : public CX - { - protected: - using base_type = delegator_t; - using delegated_type = CX; - using delegated_type::delegated_type; - }; - } // namespace netlist @@ -98,15 +105,20 @@ namespace netlist /// \brief Constants and const calculations for the library /// - template + template struct nlconst_base : public plib::constants { using BC = plib::constants; - static constexpr T np_VT(T n=BC::one(), T temp=BC::T0()) noexcept - { return n * temp * BC::k_b() / BC::Q_e(); } + static constexpr T np_VT(T n = BC::one(), T temp = BC::T0()) noexcept + { + return n * temp * BC::k_b() / BC::Q_e(); + } - static constexpr T np_Is() noexcept { return static_cast(1e-15); } // NOLINT + static constexpr T np_Is() noexcept + { + return static_cast(1e-15); + } // NOLINT /// \brief constant startup gmin /// @@ -114,20 +126,32 @@ namespace netlist /// conductivities with a reasonable value. /// During reset, the object should than make use of exec().gmin() /// to use the actual gmin() value. - static constexpr T cgmin() noexcept { return BC::magic(1e-9); } // NOLINT + static constexpr T cgmin() noexcept + { + return BC::magic(1e-9); + } // NOLINT // FIXME: Some objects used 1e-15 for initial gmin. Needs to be // aligned with cgmin - static constexpr T cgminalt() noexcept { return BC::magic(1e-15); } // NOLINT + static constexpr T cgminalt() noexcept + { + return BC::magic(1e-15); + } // NOLINT - /// \brief Multiplier applied to VT in np diode models to determine range for constant model + /// \brief Multiplier applied to VT in np diode models to determine + /// range for constant model /// - static constexpr T diode_min_cutoff_mult() noexcept { return BC::magic(-5.0); } // NOLINT + static constexpr T diode_min_cutoff_mult() noexcept + { + return BC::magic(-5.0); + } // NOLINT /// \brief Startup voltage used by np diode models /// - static constexpr T diode_start_voltage() noexcept { return BC::magic(0.7); } // NOLINT - + static constexpr T diode_start_voltage() noexcept + { + return BC::magic(0.7); + } // NOLINT }; /// \brief nlconst_base struct specialized for nl_fptype. @@ -149,11 +173,12 @@ namespace netlist /// using device_arena = std::conditional_t, config::mempool_align::value>, + plib::mempool_arena, + config::mempool_align::value>, plib::aligned_arena<>>; - using host_arena = plib::aligned_arena<>; + using host_arena = plib::aligned_arena<>; - using log_type = plib::plog_base; + using log_type = plib::plog_base; //============================================================ // Types needed by various includes @@ -165,49 +190,69 @@ namespace netlist /// enum class time_step_type { - FORWARD, ///< forward time - RESTORE ///< restore state before last forward + FORWARD, ///< forward time + RESTORE ///< restore state before last forward }; /// \brief Delegate type for device notification. /// - using nl_delegate = plib::pmfp; - using nl_delegate_ts = plib::pmfp; - using nl_delegate_dyn = plib::pmfp; + using nl_delegate = plib::pmfp; + using nl_delegate_ts = plib::pmfp; + using nl_delegate_dyn = plib::pmfp; - namespace detail { + namespace detail + { /// \brief Enum specifying the type of object /// - enum class terminal_type { + enum class terminal_type + { TERMINAL = 0, ///< object is an analog terminal - INPUT = 1, ///< object is an input - OUTPUT = 2, ///< object is an output + INPUT = 1, ///< object is an input + OUTPUT = 2, ///< object is an output }; } // namespace detail using netlist_time = plib::ptime; - using netlist_time_ext = plib::ptime::type, config::INTERNAL_RES::value>; + using netlist_time_ext = plib::ptime< + std::conditional::type, + config::INTERNAL_RES::value>; - static_assert(noexcept(netlist_time::from_nsec(1)), "Not evaluated as constexpr"); + static_assert(noexcept(netlist_time::from_nsec(1)), + "Not evaluated as constexpr"); //============================================================ // MACROS //============================================================ - template constexpr netlist_time NLTIME_FROM_NS(T &&t) noexcept { return netlist_time::from_nsec(t); } - template constexpr netlist_time NLTIME_FROM_US(T &&t) noexcept { return netlist_time::from_usec(t); } - template constexpr netlist_time NLTIME_FROM_MS(T &&t) noexcept { return netlist_time::from_msec(t); } + template + constexpr netlist_time NLTIME_FROM_NS(T &&t) noexcept + { + return netlist_time::from_nsec(t); + } + template + constexpr netlist_time NLTIME_FROM_US(T &&t) noexcept + { + return netlist_time::from_usec(t); + } + template + constexpr netlist_time NLTIME_FROM_MS(T &&t) noexcept + { + return netlist_time::from_msec(t); + } struct desc_base { /// \brief: used to hold one static netlist_time value /// - template + template struct times_ns1 { - static constexpr netlist_time value([[maybe_unused]] std::size_t N = 0) + static constexpr netlist_time value( + [[maybe_unused]] std::size_t N = 0) { return NLTIME_FROM_NS(value0); } @@ -218,8 +263,8 @@ namespace netlist /// \brief: used to hold two static netlist_time values /// - template + template struct times_ns2 { static constexpr netlist_time value(std::size_t N) @@ -230,16 +275,16 @@ namespace netlist /// \brief: used to hold three static netlist_time values /// - template + template struct times_ns3 { static constexpr netlist_time value(std::size_t N) { - return N == 0 ? NLTIME_FROM_NS(value0) : - N == 1 ? NLTIME_FROM_NS(value1) : - NLTIME_FROM_NS(value2); + return N == 0 ? NLTIME_FROM_NS(value0) + : N == 1 ? NLTIME_FROM_NS(value1) + : NLTIME_FROM_NS(value2); } }; @@ -248,10 +293,10 @@ namespace netlist /// See the 74125 implementation /// template - using desc_const = std::integral_constant; + using desc_const = std::integral_constant; template - using desc_const_t = std::integral_constant; + using desc_const_t = std::integral_constant; }; //============================================================ @@ -268,20 +313,24 @@ namespace netlist /// Allows a descriptive text to be passed to the exception explicit nl_exception(const pstring &text //!< text to be passed - ) - : plib::pexception(text) { } + ) + : plib::pexception(text) + { + } /// \brief Constructor. /// Allows to use \ref plib::pfmt logic to be used in exception - template + template explicit nl_exception(const pstring &fmt //!< format to be used - , Args&&... args //!< arguments to be passed + , + Args &&...args //!< arguments to be passed ) - : plib::pexception(plib::pfmt(fmt)(std::forward(args)...)) { } + : plib::pexception(plib::pfmt(fmt)(std::forward(args)...)) + { + } }; } // namespace netlist - #endif // NLTYPES_H_ diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp index 260fa908bf0..168cb172473 100644 --- a/src/lib/netlist/plib/pexception.cpp +++ b/src/lib/netlist/plib/pexception.cpp @@ -20,7 +20,7 @@ namespace plib { // terminate //============================================================ - void terminate(const char *msg) noexcept + [[noreturn]] void terminate(const char *msg) noexcept { try { diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h index 641d7a70e6d..bf2a286e81e 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -104,7 +104,7 @@ namespace plib { class fp_signal_enabler { public: - explicit fp_signal_enabler(unsigned fpexceptions); + explicit fp_signal_enabler(unsigned fp_exceptions); PCOPYASSIGNMOVE(fp_signal_enabler, delete) diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp index 64a9d8791ae..188c04f4cf7 100644 --- a/src/lib/netlist/plib/pfmtlog.cpp +++ b/src/lib/netlist/plib/pfmtlog.cpp @@ -39,7 +39,7 @@ private: }; #endif -pfmt::rtype pfmt::set_format(std::stringstream &strm, char32_t cfmt_spec) +pfmt::rtype pfmt::set_format(std::stringstream &strm, char32_t char_format) { pstring fmt; pstring search("{"); @@ -92,18 +92,18 @@ pfmt::rtype pfmt::set_format(std::stringstream &strm, char32_t cfmt_spec) // a.b format here ... char32_t pend(0); int width(0); - if (!fmt.empty() && pstring("duxofge").find(static_cast(cfmt_spec)) != pstring::npos) + if (!fmt.empty() && pstring("duxofge").find(static_cast(char_format)) != pstring::npos) { //pend = static_cast(fmt.at(fmt.size() - 1)); pend = plib::right(fmt, 1).at(0); if (pstring("duxofge").find(static_cast(pend)) == pstring::npos) - pend = cfmt_spec; + pend = char_format; else fmt = plib::left(fmt, fmt.length() - 1); } else // FIXME: Error - pend = cfmt_spec; + pend = char_format; auto pdot(fmt.find('.')); diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index 1586deacf3c..2e45498c637 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -375,7 +375,7 @@ namespace plib { if (build_enabled && enabled && m_enabled) { pfmt pf(fmt); - dynamic_cast(*this).upstream_write(log_translate(pf, std::forward(args)...)); + plib::dynamic_downcast(*this).upstream_write(log_translate(pf, std::forward(args)...)); } } diff --git a/src/lib/netlist/plib/pgsl.h b/src/lib/netlist/plib/pgsl.h index 3125df5cc00..b585e3ed9e3 100644 --- a/src/lib/netlist/plib/pgsl.h +++ b/src/lib/netlist/plib/pgsl.h @@ -19,6 +19,7 @@ #include "ptypes.h" #include +#include #include #include @@ -101,6 +102,54 @@ namespace plib { } // namespace pgsl + /// \brief dynamic downcast from base type pointer to derived type pointer + /// + /// This is a `noexcept` dynamic_cast implementation. It will return the cast + /// wrapped into a std::optional type forcing the caller to + /// examine if the conversion was successful. + /// + /// \tparam D Derived type + /// \tparam B Base type + /// \param base pointer to type B + /// \returns return_success_t + /// + template + std::enable_if_t && std::is_pointer_v>, + std::optional> + dynamic_downcast(B base) noexcept + { + D ret = dynamic_cast(base); + if (ret != nullptr) + return ret; + return std::nullopt; + } + + /// \brief dynamic downcast from base type reference to derived type pointer + /// + /// This is a `noexcept` dynamic_cast implementation. It will return the + /// pointer cast wrapped into a std::optional type forcing the caller to + /// examine if the conversion was successful. + /// + /// The return value is a pointer cast since there is no std::optional for + /// references. Such a construct is considered ill-formed according to + /// the std::optional specification (Section 5.2, p1). + /// + /// \tparam D Derived type + /// \tparam B Base type + /// \param base reference of type B + /// \returns return_success_t + /// + template + std::enable_if_t &&!std::is_pointer_v> , + std::optional> + dynamic_downcast(B &base) noexcept + { + D ret = dynamic_cast(&base); + if (ret != nullptr) + return ret; + return std::nullopt; + } + /// \brief downcast from base type to derived type /// /// The cpp core guidelines require a very careful use of static cast @@ -110,8 +159,8 @@ namespace plib { template constexpr D downcast(B && b) noexcept { - static_assert(std::is_pointer::value || std::is_reference::value, "downcast only supports pointers or reference for derived"); - static_assert(std::is_pointer::value || std::is_reference::value, "downcast only supports pointers or reference for base"); + static_assert((std::is_pointer::value && std::is_pointer::value) + || (std::is_reference::value && std::is_reference::value), "downcast only supports pointers or reference for derived"); return static_cast(std::forward(b)); } diff --git a/src/lib/netlist/plib/pmatrix_cr.h b/src/lib/netlist/plib/pmatrix_cr.h index ec1729dae72..74175e07101 100644 --- a/src/lib/netlist/plib/pmatrix_cr.h +++ b/src/lib/netlist/plib/pmatrix_cr.h @@ -505,7 +505,7 @@ namespace plib ~pLUmatrix_cr() = default; template - void build(M &fill, std::size_t ilup) noexcept + void build(M &fill, std::size_t ilup) noexcept(false) { std::size_t p(0); // build ilu_rows diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index 4d9544dd890..a758c446ff9 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -132,7 +132,7 @@ namespace plib { protected: int parse(const pstring &argument) override { - auto raw = plib::container::indexof(limit(), argument); + auto raw = plib::container::index_of(limit(), argument); if (raw != plib::container::npos) { diff --git a/src/lib/netlist/plib/ppmf.cpp b/src/lib/netlist/plib/ppmf.cpp index 05493f98d2f..85088b25638 100644 --- a/src/lib/netlist/plib/ppmf.cpp +++ b/src/lib/netlist/plib/ppmf.cpp @@ -83,8 +83,8 @@ namespace plib { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) std::uint8_t const *const vptr = *reinterpret_cast(byteptr); // and add offset to virtual base from vtable - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) if (sizeof(unknown_base_equiv) == m_size) + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) byteptr += *reinterpret_cast(vptr + m_vt_index); } diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index b0612c6aea9..56f40bde922 100644 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -577,7 +577,7 @@ namespace plib { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto p = reinterpret_cast::traits::template specific_member_function *>(raw); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - auto o = reinterpret_cast(obj); + auto *o = reinterpret_cast(obj); return return_type(*p, o); } diff --git a/src/lib/netlist/plib/psource.h b/src/lib/netlist/plib/psource.h index a26480aaad9..80a313ec415 100644 --- a/src/lib/netlist/plib/psource.h +++ b/src/lib/netlist/plib/psource.h @@ -140,10 +140,9 @@ namespace plib { for (auto &s : m_collection) { - auto *source(dynamic_cast(s.get())); - if (source) + if (auto source = plib::dynamic_downcast(s.get())) { - auto strm = source->stream(name); + auto strm = (*source)->stream(name); if (!strm.empty()) return strm; } @@ -156,10 +155,9 @@ namespace plib { for (auto &s : m_collection) { - auto *source(dynamic_cast(s.get())); - if (source) + if (auto source = plib::dynamic_downcast(s.get())) { - if (lambda(source)) + if (lambda(*source)) return true; } } diff --git a/src/lib/netlist/plib/ptests.h b/src/lib/netlist/plib/ptests.h index 5b385c0b9db..cc05b120b96 100644 --- a/src/lib/netlist/plib/ptests.h +++ b/src/lib/netlist/plib/ptests.h @@ -175,7 +175,14 @@ namespace plib::testing reg_entry_base(const char *n, const char *d, test_location l) : name(n), desc(d), location(l) { - registry().push_back(this); + try + { + registry().push_back(this); + } + catch (...) + { + std::terminate(); + } } reg_entry_base(const reg_entry_base &) = delete; @@ -253,22 +260,22 @@ namespace plib::testing t->set_parameters(¶ms); })).first) { - stream_error(std::cout, e->location) << "unexpected exception thrown during instantiation" << (r.second != "" ? ": " + r.second : "") << std::endl; + stream_error(std::cout, e->location) << "unexpected exception thrown during instantiation" << (!r.second.empty() ? ": " + r.second : "") << std::endl; total_errors++; } else if ((r = catch_exception([&]{ t->SetUp(); })).first) { - stream_error(std::cout, e->location) << "unexpected exception thrown during Setup" << (r.second != "" ? ": " + r.second : "") << std::endl; + stream_error(std::cout, e->location) << "unexpected exception thrown during Setup" << (!r.second.empty() ? ": " + r.second : "") << std::endl; total_errors++; } else if ((r = catch_exception([&]{ t->run(); })).first) { - stream_error(std::cout, params.m_last_source) << "unexpected exception thrown during run after this line" << (r.second != "" ? ": " + r.second : "") << std::endl; + stream_error(std::cout, params.m_last_source) << "unexpected exception thrown during run after this line" << (!r.second.empty() ? ": " + r.second : "") << std::endl; total_errors++; } else if ((r = catch_exception([&]{ t->TearDown(); })).first) { - stream_error(std::cout, e->location) << "unexpected exception thrown during Teardown" << (r.second != "" ? ": " + r.second : "") << std::endl; + stream_error(std::cout, e->location) << "unexpected exception thrown during Teardown" << (!r.second.empty() ? ": " + r.second : "") << std::endl; total_errors++; } diff --git a/src/lib/netlist/plib/ptokenizer.cpp b/src/lib/netlist/plib/ptokenizer.cpp index 98be18b6419..59468bf84cd 100644 --- a/src/lib/netlist/plib/ptokenizer.cpp +++ b/src/lib/netlist/plib/ptokenizer.cpp @@ -69,16 +69,16 @@ namespace plib { m_unget = c; } - void tokenizer_t::append_to_store(putf8_reader *reader, token_store_t &tokstor) + void tokenizer_t::append_to_store(putf8_reader *reader, token_store_t &store) { clear(); m_strm = reader; // Process tokens into queue token_t ret(token_type::UNKNOWN); - m_token_queue = &tokstor; + m_token_queue = &store; do { ret = get_token_comment(); - tokstor.push_back(ret); + store.push_back(ret); } while (!ret.is_type(token_type::token_type::ENDOFFILE)); m_token_queue = nullptr; } @@ -300,28 +300,26 @@ namespace plib { } return { token_type::STRING, tokstr }; } - else + + // read identifier till first identifier char or ws + pstring tokstr = ""; + while ((m_identifier_chars.find(c) == pstring::npos) && (m_whitespace.find(c) == pstring::npos)) { - // read identifier till first identifier char or ws - pstring tokstr = ""; - while ((m_identifier_chars.find(c) == pstring::npos) && (m_whitespace.find(c) == pstring::npos)) + tokstr += c; + // expensive, check for single char tokens + if (tokstr.length() == 1) { - tokstr += c; - // expensive, check for single char tokens - if (tokstr.length() == 1) - { - auto id = m_tokens.find(tokstr); - if (id != m_tokens.end()) - return { id->second, tokstr }; - } - c = getc(); + auto id = m_tokens.find(tokstr); + if (id != m_tokens.end()) + return { id->second, tokstr }; } - ungetc(c); - auto id = m_tokens.find(tokstr); - return (id != m_tokens.end()) ? - token_t(id->second, tokstr) - : token_t(token_type::UNKNOWN, tokstr); + c = getc(); } + ungetc(c); + auto id = m_tokens.find(tokstr); + return (id != m_tokens.end()) ? + token_t(id->second, tokstr) + : token_t(token_type::UNKNOWN, tokstr); } token_reader_t::token_t tokenizer_t::get_token_comment() diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index 734442ff96a..ae383aaf807 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -17,15 +17,18 @@ #include #include -#define PSTRINGIFY_HELP(y) # y +#define PSTRINGIFY_HELP(y) #y #define PSTRINGIFY(x) PSTRINGIFY_HELP(x) -// Discussion and background of this MSVC bug: https://github.com/mamedev/mame/issues/6106 +// Discussion and background of this MSVC bug: +// https://github.com/mamedev/mame/issues/6106 /// /// \brief Macro to work around a bug in MSVC treatment of __VA_ARGS__ /// #define PMSVC_VARARG_BUG(MACRO, ARGS) MACRO ARGS +// clang-format off + /// \brief Determine number of arguments in __VA_ARGS__ /// /// This macro works up to 16 arguments in __VA_ARGS__ @@ -70,13 +73,16 @@ #define PSTRINGIFY_16(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, x10) \ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe, #xf, #x10 +// clang-format on + /// \brief Individually stringify up to 16 arguments /// /// PSTRINGIFY_VA(a, b, c) will be expanded to "a", "b", "c" /// /// \returns List of stringified individual arguments /// -#define PSTRINGIFY_VA(...) PMSVC_VARARG_BUG(PCONCAT, (PSTRINGIFY_, PNARGS(__VA_ARGS__)))(__VA_ARGS__) +#define PSTRINGIFY_VA(...) \ + PMSVC_VARARG_BUG(PCONCAT, (PSTRINGIFY_, PNARGS(__VA_ARGS__)))(__VA_ARGS__) /// \brief Dispatch VARARG macro to specialized macros /// @@ -93,7 +99,8 @@ /// /// \returns result of specialized macro /// -#define PCALLVARARG(MAC, ...) PMSVC_VARARG_BUG(PCONCAT, (MAC, PNARGS(__VA_ARGS__)))(__VA_ARGS__) +#define PCALLVARARG(MAC, ...) \ + PMSVC_VARARG_BUG(PCONCAT, (MAC, PNARGS(__VA_ARGS__)))(__VA_ARGS__) // FIXME:: __FUNCTION__ may be not be supported by all compilers. @@ -107,7 +114,7 @@ namespace plib pstring basename(const pstring &filename, const pstring &suffix = ""); pstring path(const pstring &filename); bool exists(const pstring &filename); - pstring build_path(std::initializer_list list ); + pstring build_path(std::initializer_list list); pstring environment(const pstring &var, const pstring &default_val); } // namespace util @@ -121,7 +128,7 @@ namespace plib static constexpr const std::size_t npos = static_cast(-1); template - std::size_t indexof(C &con, const typename C::value_type &elem) + std::size_t index_of(C &con, const typename C::value_type &elem) { auto it = std::find(con.begin(), con.end(), elem); if (it != con.end()) @@ -130,7 +137,8 @@ namespace plib } template - void insert_at(C &con, const std::size_t index, const typename C::value_type &elem) + void insert_at(C &con, const std::size_t index, + const typename C::value_type &elem) { con.insert(con.begin() + narrow_cast(index), elem); } @@ -142,19 +150,72 @@ namespace plib } } // namespace container - // ---------------------------------------------------------------------------------------- - // simple hash - // ---------------------------------------------------------------------------------------- - + /// \brief Consistent hash implementation + /// + /// Hash implementations in c++ standard libraries may differ and deliver + /// different results. This hash can be used as a replacement hash in e.g. + /// std::map to deliver consistent results. + /// + /// \tparam V result type + /// \tparam T buffer element type + /// \param buf pointer to buffer for which hash should be calculated + /// \param size number of buffer elements + /// \return the hash of the buffer + /// template constexpr V hash(const T *buf, std::size_t size) noexcept { V result = 5381; // NOLINT - for (const T* p = buf; p != buf + size; p++) - result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ narrow_cast(*p); // NOLINT + for (const T *p = buf; p != buf + size; p++) + result = ((result << 5) + result) ^ (result >> (32 - 5)) + ^ narrow_cast(*p); // NOLINT return result; } + /// \brief Execute code at end of block + /// + /// The class can be used to execute code at the end of a block. It follows + /// the same design as std::lock_guard. + /// + /// Since the functor is executed in the destructor of the class the + /// execution is protected by a try catch block. If an exception is raised, + /// \ref plib::terminate is called. + /// + /// \tparam F type of functor - will be derived by template deduction guide + /// + template + struct functor_guard + { + /// \brief constructor + /// + /// \param f functor to execute + functor_guard(F &&f) + : m_f(std::move(f)) + { + } + /// \brief destructor + /// + ~functor_guard() + { + try + { + m_f(); + } + catch (...) + { + plib::terminate("exception raised in lambda_guard"); + } + } + + private: + F m_f; + }; + + /// \brief template deduction guide + /// + template + functor_guard(F f) -> functor_guard; + } // namespace plib #endif // PUTIL_H_ diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index b741259c49e..a918aac1c58 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -50,7 +50,8 @@ namespace netlist::solver matrix_solver_t::matrix_solver_t(devices::nld_solver &main_solver, const pstring &name, const net_list_t &nets, const solver::solver_parameters_t *params) - : device_t(static_cast(main_solver), name) + //: device_t(static_cast(main_solver), name) + : device_t(device_data_t{main_solver.state(), main_solver.name() + "." + name}) , m_params(*params) , m_gonn(m_arena) , m_gtn(m_arena) @@ -126,9 +127,9 @@ namespace netlist::solver if (!plib::container::contains(dynamic_devices, &p->device())) dynamic_devices.push_back(&p->device()); { - auto *pterm = dynamic_cast(p); - nl_assert(pterm != nullptr); - add_term(k, pterm); + auto pterm = plib::dynamic_downcast(p); + nl_assert_always(bool(pterm), "cast to terminal_t * failed"); + add_term(k, *pterm); } log().debug("Added terminal {1}\n", p->name()); break; @@ -145,8 +146,9 @@ namespace netlist::solver if (net_proxy_output == nullptr) { pstring new_name(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inputs.size()))); - nl_assert_always(net.is_analog(), "Net is not an analog net"); - auto net_proxy_output_u = state().make_pool_object(*this, new_name, &dynamic_cast(p->net())); + auto proxied_net = plib::dynamic_downcast(p->net()); + nl_assert_always(proxied_net, "Net is not an analog net"); + auto net_proxy_output_u = state().make_pool_object(*this, new_name, *proxied_net); net_proxy_output = net_proxy_output_u.get(); m_inputs.emplace_back(std::move(net_proxy_output_u)); } @@ -366,6 +368,8 @@ namespace netlist::solver } log().verbose("Number of multiplications/additions for {1}: {2}", name(), m_ops); + // Dumps non zero elements right of diagonal -> to much output, disabled + // NOLINTNEXTLINE(readability-simplify-boolean-expr) if ((false)) for (std::size_t k = 0; k < iN; k++) { diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 6b53fe81ed2..cdee6dbb5ff 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -320,8 +320,8 @@ namespace netlist::solver std::size_t max_rail_start() const noexcept { std::size_t max_rail = 0; - for (std::size_t k = 0; k < m_terms.size(); k++) - max_rail = std::max(max_rail, m_terms[k].rail_start()); + for (const auto &term : m_terms) + max_rail = std::max(max_rail, term.rail_start()); return max_rail; } diff --git a/src/lib/netlist/solver/nld_matrix_solver_ext.h b/src/lib/netlist/solver/nld_matrix_solver_ext.h index e4cfef0701f..3627c0b8e91 100644 --- a/src/lib/netlist/solver/nld_matrix_solver_ext.h +++ b/src/lib/netlist/solver/nld_matrix_solver_ext.h @@ -61,7 +61,7 @@ namespace netlist::solver // FIXME: Not yet working, mat_cr.h needs some more work #if 0 - auto mat_GE = dynamic_cast *>(&mat); + auto mat_GE = plib::dynamic_downcast *>(&mat); #endif std::vector levL(iN, 0); std::vector levU(iN, 0); diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index 61bedfa8d06..a2c5d284c43 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -327,7 +327,7 @@ namespace netlist::solver t.imbue(std::locale::classic()); plib::putf8_fmt_writer w(&t); generate_code(w); - //std::hash::type>::type> h; + //#std::hash::type>::type> h; return plib::pfmt("nl_gcr_{1}_{2}_{3}_{4:x}")(mat.nz_num)(str_fptype)(str_floattype)(plib::hash( t.str().c_str(), t.str().size() )); } diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 445608a2c27..d7381cc813a 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -4,9 +4,10 @@ // Names // spell-checker: words Woodbury, -#include "nl_factory.h" -#include "core/setup.h" +#include "nld_solver.h" + #include "nl_errstr.h" +#include "nl_factory.h" #include "nl_setup.h" // FIXME: only needed for splitter code #include "nld_matrix_solver.h" #include "nld_ms_direct.h" @@ -18,7 +19,9 @@ #include "nld_ms_sor.h" #include "nld_ms_sor_mat.h" #include "nld_ms_w.h" -#include "nld_solver.h" + +#include "core/setup.h" + #include "plib/pomp.h" #include "plib/ptimed_queue.h" @@ -28,9 +31,27 @@ namespace netlist::devices { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // solver - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + + nld_solver::nld_solver(constructor_param_t data) + : device_t(data) + , m_fb_step(*this, "FB_step", NETLIB_DELEGATE(fb_step)) + , m_Q_step(*this, "Q_step") + , m_params(*this, "", solver::solver_parameter_defaults::get_instance()) + , m_queue( + this->state().pool(), config::max_solver_queue_size(), + queue_type::id_delegate(&NETLIB_NAME(solver)::get_solver_id, this), + queue_type::obj_delegate(&NETLIB_NAME(solver)::solver_by_id, this)) + { + // internal stuff + state().save(*this, + static_cast(m_queue), + this->name(), "m_queue"); + + connect("FB_step", "Q_step"); + } NETLIB_RESET(solver) { @@ -54,16 +75,28 @@ namespace netlist::devices NETLIB_HANDLER(solver, fb_step) { const netlist_time_ext now(exec().time()); - const std::size_t nthreads = m_params.m_parallel() < 2 ? 1 : std::min(static_cast(m_params.m_parallel()), plib::omp::get_max_threads()); - const netlist_time_ext sched(now + (nthreads <= 1 ? netlist_time_ext::zero() : netlist_time_ext::from_nsec(100))); - plib::uninitialised_array tmp; //NOLINT - plib::uninitialised_array nt; //NOLINT - std::size_t p=0; + const std::size_t nthreads = m_params.m_parallel() < 2 + ? 1 + : std::min( + static_cast( + m_params.m_parallel()), + plib::omp::get_max_threads()); + const netlist_time_ext sched( + now + + (nthreads <= 1 ? netlist_time_ext::zero() + : netlist_time_ext::from_nsec(100))); + plib::uninitialised_array + tmp; // NOLINT + plib::uninitialised_array + nt; // NOLINT + std::size_t p = 0; while (!m_queue.empty()) { const auto t = m_queue.top().exec_time(); - auto *o = m_queue.top().object(); + auto * o = m_queue.top().object(); if (t != now) if (t > sched) break; @@ -71,14 +104,15 @@ namespace netlist::devices m_queue.pop(); } - // FIXME: Disabled for now since parallel processing will decrease performance + // FIXME: Disabled for now since parallel processing will decrease + // performance // for tested applications. More testing required here if (true || nthreads < 2) { if (!KEEP_STATS) { for (std::size_t i = 0; i < p; i++) - nt[i] = tmp[i]->solve(now, "no-parallel"); + nt[i] = tmp[i]->solve(now, "no-parallel"); } else { @@ -102,10 +136,9 @@ namespace netlist::devices else { plib::omp::set_num_threads(nthreads); - plib::omp::for_static(static_cast(0), p, [&tmp, &nt,now](std::size_t i) - { - nt[i] = tmp[i]->solve(now, "parallel"); - }); + plib::omp::for_static(static_cast(0), p, + [&tmp, &nt, now](std::size_t i) + { nt[i] = tmp[i]->solve(now, "parallel"); }); for (std::size_t i = 0; i < p; i++) { if (nt[i] != netlist_time::zero()) @@ -114,10 +147,12 @@ namespace netlist::devices } } if (!m_queue.empty()) - m_Q_step.net().toggle_and_push_to_queue(static_cast(m_queue.top().exec_time() - now)); + m_Q_step.net().toggle_and_push_to_queue( + static_cast(m_queue.top().exec_time() - now)); } - void NETLIB_NAME(solver) :: reschedule(solver::matrix_solver_t *solv, netlist_time ts) + void NETLIB_NAME(solver)::reschedule(solver::matrix_solver_t *solv, + netlist_time ts) { const netlist_time_ext now(exec().time()); const netlist_time_ext sched(now + ts); @@ -141,78 +176,101 @@ namespace netlist::devices netlist_time_ext now(exec().time()); // force solving during start up if there are no time-step devices // FIXME: Needs a more elegant solution - bool force_solve = (now < netlist_time_ext::from_fp(2 * m_params.m_max_time_step)); + bool force_solve = (now < netlist_time_ext::from_fp< + decltype(m_params.m_max_time_step)>( + 2 * m_params.m_max_time_step)); - std::size_t nthreads = std::min(static_cast(m_params.m_parallel()), plib::omp::get_max_threads()); + std::size_t nthreads = std::min( + static_cast(m_params.m_parallel()), + plib::omp::get_max_threads()); - std::vector &solvers = (force_solve ? m_mat_solvers_all : m_mat_solvers_time_stepping); + std::vector + &solvers = (force_solve ? m_mat_solvers_all + : m_mat_solvers_time_stepping); if (nthreads > 1 && solvers.size() > 1) { plib::omp::set_num_threads(nthreads); - plib::omp::for_static(static_cast(0), solvers.size(), [&solvers, now](std::size_t i) - { - [[maybe_unused]] const netlist_time ts = solvers[i]->ptr->solve(now); + plib::omp::for_static( + static_cast(0), solvers.size(), + [&solvers, now](std::size_t i) { + [[maybe_unused]] const netlist_time ts = solvers[i] + ->ptr->solve( + now); }); } else - for (auto & solver : solvers) + for (auto &solver : solvers) { - [[maybe_unused]] const netlist_time ts = solver->ptr->solve(now); + [[maybe_unused]] const netlist_time ts = solver->ptr->solve( + now); } - for (auto & solver : solvers) + for (auto &solver : solvers) solver->ptr->update_inputs(); // step circuit if (!m_Q_step.net().is_queued()) { - m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_fp(m_params.m_max_time_step)); + m_Q_step.net().toggle_and_push_to_queue( + netlist_time::from_fp(m_params.m_max_time_step)); } } #endif // FIXME: should be created in device space template - NETLIB_NAME(solver)::solver_ptr create_it(A &arena, NETLIB_NAME(solver) &main_solver, pstring name, - NETLIB_NAME(solver)::net_list_t &nets, - const solver::solver_parameters_t *params, std::size_t size) + NETLIB_NAME(solver)::solver_ptr + create_it(A &arena, NETLIB_NAME(solver) &main_solver, pstring name, + NETLIB_NAME(solver)::net_list_t & nets, + const solver::solver_parameters_t *params, std::size_t size) { - return plib::make_unique(arena, main_solver, name, nets, params, size); + return plib::make_unique(arena, main_solver, name, nets, params, + size); } template - NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solver(std::size_t size, - const pstring &solver_name, const solver::solver_parameters_t *params, - NETLIB_NAME(solver)::net_list_t &nets) + NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solver( + std::size_t size, const pstring &solver_name, + const solver::solver_parameters_t *params, + NETLIB_NAME(solver)::net_list_t & nets) { switch (params->m_method()) { case solver::matrix_type_e::MAT_CR: - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); case solver::matrix_type_e::MAT: - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); case solver::matrix_type_e::GMRES: - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); #if (NL_USE_ACADEMIC_SOLVERS) case solver::matrix_type_e::SOR: - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); case solver::matrix_type_e::SOR_MAT: - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); case solver::matrix_type_e::SM: // Sherman-Morrison Formula - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); case solver::matrix_type_e::W: // Woodbury Formula - return create_it>(state().pool(), *this, solver_name, nets, params, size); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); #else - //case solver::matrix_type_e::GMRES: + // case solver::matrix_type_e::GMRES: case solver::matrix_type_e::SOR: case solver::matrix_type_e::SOR_MAT: case solver::matrix_type_e::SM: case solver::matrix_type_e::W: - state().log().warning(MW_SOLVER_METHOD_NOT_SUPPORTED(params->m_method().name(), "MAT_CR")); - return create_it>(state().pool(), *this, solver_name, nets, params, size); + state().log().warning(MW_SOLVER_METHOD_NOT_SUPPORTED( + params->m_method().name(), "MAT_CR")); + return create_it>( + state().pool(), *this, solver_name, nets, params, size); #endif } return solver_ptr(); @@ -228,47 +286,49 @@ namespace netlist::devices { #if !defined(__EMSCRIPTEN__) case 1: - return plib::make_unique>(state().pool(), *this, sname, nets, params); + return plib::make_unique>( + state().pool(), *this, sname, nets, params); case 2: - return plib::make_unique>(state().pool(), *this, sname, nets, params); - case 3: - return create_solver(3, sname, params, nets); - case 4: - return create_solver(4, sname, params, nets); - case 5: - return create_solver(5, sname, params, nets); - case 6: - return create_solver(6, sname, params, nets); - case 7: - return create_solver(7, sname, params, nets); - case 8: - return create_solver(8, sname, params, nets); + return plib::make_unique>( + state().pool(), *this, sname, nets, params); + case 3: return create_solver(3, sname, params, nets); + case 4: return create_solver(4, sname, params, nets); + case 5: return create_solver(5, sname, params, nets); + case 6: return create_solver(6, sname, params, nets); + case 7: return create_solver(7, sname, params, nets); + case 8: return create_solver(8, sname, params, nets); #endif default: log().info(MI_NO_SPECIFIC_SOLVER(net_count)); if (net_count <= 16) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } if (net_count <= 32) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } if (net_count <= 64) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } if (net_count <= 128) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } if (net_count <= 256) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } if (net_count <= 512) { - return create_solver(net_count, sname, params, nets); + return create_solver(net_count, sname, params, + nets); } return create_solver(net_count, sname, params, nets); } @@ -278,18 +338,21 @@ namespace netlist::devices { void run(netlist_state_t &nl_state) { - for (auto & net : nl_state.nets()) + for (auto &net : nl_state.nets()) { nl_state.log().verbose("processing {1}", net->name()); if (!net->is_rail_net() && !net->core_terms_empty()) { nl_state.log().verbose(" ==> not a rail net"); // Must be an analog net - auto &n = dynamic_cast(*net); - if (!already_processed(n)) + auto n = plib::dynamic_downcast(net.get()); + nl_assert_always(bool(n), + "Unable to cast to analog_net_t &"); + if (!already_processed(*(*n))) { - groupspre.emplace_back(NETLIB_NAME(solver)::net_list_t()); - process_net(nl_state, n); + groupspre.emplace_back( + NETLIB_NAME(solver)::net_list_t()); + process_net(nl_state, *(*n)); } } } @@ -301,14 +364,13 @@ namespace netlist::devices std::vector groups; private: - bool already_processed(const analog_net_t &n) const { // no need to process rail nets - these are known variables if (n.is_rail_net()) return true; // if it's already processed - no need to continue - for (const auto & grp : groups) + for (const auto &grp : groups) if (plib::container::contains(grp, &n)) return true; return false; @@ -323,12 +385,13 @@ namespace netlist::devices // In this case we need to merge this group into the current group if (groupspre.size() > 1) { - for (std::size_t i = 0; iname(), static_cast(term->type())); + nl_state.log().verbose("Term {} {}", term->name(), + static_cast(term->type())); // only process analog terminals if (term->is_type(detail::terminal_type::TERMINAL)) { - auto &pt = dynamic_cast(*term); + auto pt = plib::dynamic_downcast(term); + nl_assert_always(bool(pt), + "Error casting *term to terminal_t &"); // check the connected terminal - const auto *const connected_terminals = nl_state.setup().get_connected_terminals(pt); + const auto *const connected_terminals + = nl_state.setup().get_connected_terminals(*(*pt)); // NOLINTNEXTLINE proposal does not work for VS - for (auto ct = connected_terminals->begin(); *ct != nullptr; ct++) + for (auto ct = connected_terminals->begin(); + *ct != nullptr; ct++) { analog_net_t &connected_net = (*ct)->net(); - nl_state.log().verbose(" Connected net {}", connected_net.name()); + nl_state.log().verbose(" Connected net {}", + connected_net.name()); if (!check_if_processed_and_join(connected_net)) process_net(nl_state, connected_net); } @@ -386,40 +456,48 @@ namespace netlist::devices net_splitter splitter; splitter.run(state()); - log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size()); + log().verbose("Found {1} net groups in {2} nets\n", + splitter.groups.size(), state().nets().size()); int num_errors = 0; log().verbose("checking net consistency ..."); for (const auto &grp : splitter.groups) { - int rail_terminals = 0; + int rail_terminals = 0; pstring nets_in_grp; for (const auto &n : grp) { nets_in_grp += (n->name() + " "); if (!n->is_analog()) { - state().log().error(ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n->name())); + state().log().error( + ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n->name())); num_errors++; } if (n->is_rail_net()) { - state().log().error(ME_SOLVER_CONSISTENCY_RAIL_NET(n->name())); + state().log().error( + ME_SOLVER_CONSISTENCY_RAIL_NET(n->name())); num_errors++; } - for (detail::core_terminal_t * t : n->core_terms_copy()) + for (detail::core_terminal_t *t : n->core_terms_copy()) { if (!t->has_net()) { - state().log().error(ME_SOLVER_TERMINAL_NO_NET(t->name())); + state().log().error( + ME_SOLVER_TERMINAL_NO_NET(t->name())); num_errors++; } else { - auto *other_terminal = dynamic_cast(t); - if (other_terminal != nullptr) - if (state().setup().get_connected_terminal(*other_terminal)->net().is_rail_net()) + if (auto other_terminal = plib::dynamic_downcast< + terminal_t *>(t)) + if (state() + .setup() + .get_connected_terminal(*(*other_terminal)) + ->net() + .is_rail_net()) rail_terminals++; } } @@ -433,43 +511,56 @@ namespace netlist::devices if (num_errors > 0) throw nl_exception(MF_SOLVER_CONSISTENCY_ERRORS(num_errors)); - // setup the solvers - for (auto & grp : splitter.groups) + for (auto &grp : splitter.groups) { - solver_ptr ms; - pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); - params_uptr params = plib::make_unique(state().pool(), *this, sname + ".", m_params); + solver_ptr ms; + pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); + params_uptr params = plib::make_unique( + state().pool(), *this, sname + ".", m_params); switch (params->m_fp_type()) { case solver::matrix_fp_type_e::FLOAT: if (!config::use_float_matrix::value) - log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name()); - ms = create_solvers>(sname, params.get(), grp); + log().info("FPTYPE {1} not supported. Using DOUBLE", + params->m_fp_type().name()); + ms = create_solvers>( + sname, params.get(), grp); break; case solver::matrix_fp_type_e::DOUBLE: ms = create_solvers(sname, params.get(), grp); break; case solver::matrix_fp_type_e::LONGDOUBLE: if (!config::use_long_double_matrix::value) - log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name()); - ms = create_solvers>(sname, params.get(), grp); + log().info("FPTYPE {1} not supported. Using DOUBLE", + params->m_fp_type().name()); + ms = create_solvers>(sname, params.get(), grp); break; case solver::matrix_fp_type_e::FLOATQ128: #if (NL_USE_FLOAT128) ms = create_solvers(sname, params.get(), grp); #else - log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name()); + log().info("FPTYPE {1} not supported. Using DOUBLE", + params->m_fp_type().name()); ms = create_solvers(sname, params.get(), grp); #endif break; } + state().register_device( + ms->name(), + device_arena::owned_ptr(ms.get(), false)); + log().verbose("Solver {1}", ms->name()); log().verbose(" ==> {1} nets", grp.size()); - log().verbose(" has {1} dynamic elements", ms->dynamic_device_count()); - log().verbose(" has {1} time step elements", ms->time_step_device_count()); + log().verbose(" has {1} dynamic elements", + ms->dynamic_device_count()); + log().verbose(" has {1} time step elements", + ms->time_step_device_count()); for (auto &n : grp) { log().verbose("Net {1}", n->name()); @@ -482,35 +573,37 @@ namespace netlist::devices m_mat_params.push_back(std::move(params)); m_mat_solvers.push_back(std::move(ms)); } - } - solver::static_compile_container NETLIB_NAME(solver)::create_solver_code(solver::static_compile_target target) + solver::static_compile_container NETLIB_NAME(solver)::create_solver_code( + solver::static_compile_target target) { solver::static_compile_container mp; - for (auto & s : m_mat_solvers) + for (auto &s : m_mat_solvers) { auto r = s->create_solver_code(target); - if (!r.first.empty()) // ignore solvers not supporting static compile + if (!r.first.empty()) // ignore solvers not supporting static + // compile mp.push_back(r); } return mp; } - std::size_t NETLIB_NAME(solver)::get_solver_id(const solver::matrix_solver_t *net) const + std::size_t NETLIB_NAME(solver)::get_solver_id( + const solver::matrix_solver_t *net) const { - for (std::size_t i=0; i < m_mat_solvers.size(); i++) + for (std::size_t i = 0; i < m_mat_solvers.size(); i++) if (m_mat_solvers[i].get() == net) return i; return std::numeric_limits::max(); } - solver::matrix_solver_t * NETLIB_NAME(solver)::solver_by_id(std::size_t id) const + solver::matrix_solver_t *NETLIB_NAME(solver)::solver_by_id( + std::size_t id) const { return m_mat_solvers[id].get(); } - NETLIB_DEVICE_IMPL(solver, "SOLVER", "FREQ") } // namespace netlist::devices diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index 898dac7403f..c4f6c2e5bf1 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -8,49 +8,43 @@ /// \file nld_solver.h /// -#include "../plib/pstream.h" +#include "nld_matrix_solver.h" #include "core/core_device.h" #include "core/logic.h" #include "core/state_var.h" -#include "nld_matrix_solver.h" + +#include "../plib/pstream.h" #include #include #include -// ---------------------------------------------------------------------------------------- -// solver -// ---------------------------------------------------------------------------------------- - namespace netlist::devices { - NETLIB_OBJECT(solver) + // ------------------------------------------------------------------------- + // solver + // ------------------------------------------------------------------------- + + class nld_solver : public device_t { public: using solver_arena = device_arena; - using queue_type = detail::queue_base; + using queue_type = detail::queue_base; - NETLIB_CONSTRUCTOR(solver) - , m_fb_step(*this, "FB_step", NETLIB_DELEGATE(fb_step)) - , m_Q_step(*this, "Q_step") - , m_params(*this, "", solver::solver_parameter_defaults::get_instance()) - , m_queue(this->state().pool(), config::max_solver_queue_size(), - queue_type::id_delegate(&NETLIB_NAME(solver) :: get_solver_id, this), - queue_type::obj_delegate(&NETLIB_NAME(solver) :: solver_by_id, this)) - { - // internal stuff - state().save(*this, static_cast(m_queue), this->name(), "m_queue"); - - connect("FB_step", "Q_step"); - } + nld_solver(constructor_param_t data); void post_start(); void stop(); - auto gmin() const -> decltype(solver::solver_parameters_t::m_gmin()) { return m_params.m_gmin(); } + auto gmin() const -> decltype(solver::solver_parameters_t::m_gmin()) + { + return m_params.m_gmin(); + } - solver::static_compile_container create_solver_code(solver::static_compile_target target); + solver::static_compile_container + create_solver_code(solver::static_compile_target target); NETLIB_RESETI(); // NETLIB_UPDATE_PARAMI(); @@ -62,32 +56,34 @@ namespace netlist::devices void reschedule(solver::matrix_solver_t *solv, netlist_time ts); private: - using params_uptr = solver_arena::unique_ptr; + using params_uptr = solver_arena::unique_ptr< + solver::solver_parameters_t>; - template + template NETLIB_HANDLERI(fb_step); - logic_input_t m_fb_step; + logic_input_t m_fb_step; logic_output_t m_Q_step; // FIXME: these should be created in device space std::vector m_mat_params; - std::vector m_mat_solvers; + std::vector m_mat_solvers; solver::solver_parameters_t m_params; - queue_type m_queue; + queue_type m_queue; template solver_ptr create_solver(std::size_t size, const pstring &solver_name, - const solver::solver_parameters_t *params,net_list_t &nets); + const solver::solver_parameters_t *params, + net_list_t & nets); template - solver_ptr create_solvers(const pstring &sname, - const solver::solver_parameters_t *params, net_list_t &nets); + solver_ptr create_solvers(const pstring & sname, + const solver::solver_parameters_t *params, + net_list_t & nets); std::size_t get_solver_id(const solver::matrix_solver_t *net) const; solver::matrix_solver_t *solver_by_id(std::size_t id) const; - }; } // namespace netlist::devices diff --git a/src/lib/netlist/tests/test_penum.cpp b/src/lib/netlist/tests/test_penum.cpp index 0fafafa97b4..8e90c8537e1 100644 --- a/src/lib/netlist/tests/test_penum.cpp +++ b/src/lib/netlist/tests/test_penum.cpp @@ -14,6 +14,7 @@ #include #include +#include #if 0 namespace plib @@ -166,6 +167,58 @@ operator == (const E &lhs, const char * rhs) } #endif +// --------------------------------------- + +template +struct ret_t +{ + bool success; + T value; +}; + +template +constexpr ret_t stl_h(std::string_view sv) +{ + T r(0); + for (const auto &c : sv) + { + if (c >= '0' && c < '0' + std::min(10,BASE)) + { + r = r * BASE + (c - '0'); + } + else if (c >= 'A' && c < ('A' + BASE - 10)) + { + r = r * BASE + (10 + c - 'A'); + } + else if (c >= 'a' && c < ('a' + BASE - 10)) + { + r = r * BASE + (10 + c - 'a'); + } + else + return { false, T(0) }; + } + return { true, r }; +} + +template +constexpr ret_t stl(std::string_view sv) +{ + if constexpr (BASE == 0) + { + if (sv.size() > 2) + { + if (sv.substr(0,2) == "0x" || sv.substr(0,2) == "0X") + return stl_h(sv.substr(2)); + if (sv.substr(0,2) == "0b") + return stl_h(sv.substr(2)); + } + if (sv.size() > 1 && sv.substr(0,1) == "0" ) + return stl_h(sv.substr(1)); + return stl_h(sv); + } + return stl_h(sv); +} + #include "plib/ptests.h" //PENUM_NS(plibx, teste, A, B, C) @@ -179,6 +232,12 @@ PENUM(testf, A, B, C) PTEST(penum, conversion) { + static_assert(stl("0xa0bc").success,"no"); + static_assert(stl("0xa0bc").value==0xa0bc,"no"); + static_assert(stl("0b1010").value==0b1010,"no"); + static_assert(stl("0123").value==0123,"no"); + //const auto x(stl("123")); + //static_assert(x.value==123,"no"); plibx::teste x = plib::functor("A"); PEXPECT_NE(x, plibx::teste::B); diff --git a/src/lib/netlist/tests/test_precommit.cpp b/src/lib/netlist/tests/test_precommit.cpp index 55f9b596a8c..15575fbbe7f 100644 --- a/src/lib/netlist/tests/test_precommit.cpp +++ b/src/lib/netlist/tests/test_precommit.cpp @@ -7,10 +7,10 @@ /// tests for `plib::pmfp` /// -#include "plib/pconfig.h" -#include "plib/ppmf.h" #include "netlist/nl_config.h" +#include "plib/pconfig.h" +#include "plib/ppmf.h" #include "plib/ptests.h" PTEST(test_precommit, precommit)