From 77ea61bac778e0eccaf2872e6d67c2eec7eb541b Mon Sep 17 00:00:00 2001 From: couriersud Date: Sat, 2 Nov 2019 22:25:11 +0100 Subject: netlist: add RELTOL/VNTOL solver parameters. Type safety. [Couriersud] The newly added RELTOL and VNTOL parameters implement Newton convergence checks comparable following other SPICE implementations. The ACCURACY solver parameter now is only used for convergence checks in iterative solvers. In addition, type safety was significantly improved and a lot of "magic" numbers are identifiable now. --- src/lib/netlist/analog/nld_bjt.cpp | 50 +++++---- src/lib/netlist/analog/nld_generic_models.h | 52 ++++----- src/lib/netlist/analog/nld_mosfet.cpp | 155 ++++++++++++++------------- src/lib/netlist/analog/nld_opamps.cpp | 14 +-- src/lib/netlist/analog/nld_switches.cpp | 2 +- src/lib/netlist/analog/nld_twoterm.h | 18 ++-- src/lib/netlist/analog/nlid_fourterm.cpp | 7 +- src/lib/netlist/analog/nlid_fourterm.h | 12 +-- src/lib/netlist/analog/nlid_twoterm.cpp | 18 ++-- src/lib/netlist/analog/nlid_twoterm.h | 55 +++++----- src/lib/netlist/devices/nld_4066.cpp | 4 +- src/lib/netlist/devices/nld_4316.cpp | 2 +- src/lib/netlist/devices/nld_74123.cpp | 8 +- src/lib/netlist/devices/nld_74ls629.cpp | 28 ++--- src/lib/netlist/devices/nld_mm5837.cpp | 10 +- src/lib/netlist/devices/nld_ne555.cpp | 18 ++-- src/lib/netlist/devices/nld_r2r_dac.cpp | 6 +- src/lib/netlist/devices/nld_schmitt.cpp | 8 +- src/lib/netlist/devices/nlid_proxy.cpp | 27 +++-- src/lib/netlist/devices/nlid_proxy.h | 2 +- src/lib/netlist/devices/nlid_system.h | 38 +++---- src/lib/netlist/nl_base.cpp | 32 +++--- src/lib/netlist/nl_base.h | 4 +- src/lib/netlist/nl_config.h | 3 + src/lib/netlist/nl_parser.cpp | 12 ++- src/lib/netlist/nl_setup.cpp | 26 ++--- src/lib/netlist/nl_setup.h | 11 +- src/lib/netlist/plib/pchrono.h | 8 +- src/lib/netlist/plib/pfunction.cpp | 5 +- src/lib/netlist/plib/pfunction.h | 4 +- src/lib/netlist/plib/ptime.h | 2 +- src/lib/netlist/plib/putil.h | 7 +- src/lib/netlist/prg/nltool.cpp | 12 +-- src/lib/netlist/solver/nld_matrix_solver.cpp | 4 +- src/lib/netlist/solver/nld_matrix_solver.h | 107 ++++++++++-------- src/lib/netlist/solver/nld_ms_direct.h | 32 +++--- src/lib/netlist/solver/nld_ms_direct1.h | 14 +-- src/lib/netlist/solver/nld_ms_direct2.h | 13 ++- src/lib/netlist/solver/nld_ms_gcr.h | 34 +++--- src/lib/netlist/solver/nld_ms_gmres.h | 14 +-- src/lib/netlist/solver/nld_ms_sm.h | 14 +-- src/lib/netlist/solver/nld_ms_sor.h | 22 ++-- src/lib/netlist/solver/nld_ms_sor_mat.h | 11 +- src/lib/netlist/solver/nld_ms_w.h | 22 ++-- 44 files changed, 510 insertions(+), 437 deletions(-) diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp index f1d66c2344f..2eed4711322 100644 --- a/src/lib/netlist/analog/nld_bjt.cpp +++ b/src/lib/netlist/analog/nld_bjt.cpp @@ -21,17 +21,22 @@ namespace analog class diode { public: - diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(plib::reciprocal(m_VT)) {} + diode() + : m_Is(plib::constants::cast(1e-15)) + , m_VT(plib::constants::cast(0.0258)) + , m_VT_inv(plib::reciprocal(m_VT)) + {} + diode(const nl_fptype Is, const nl_fptype n) { m_Is = Is; - m_VT = 0.0258 * n; + m_VT = plib::constants::cast(0.0258) * n; m_VT_inv = plib::reciprocal(m_VT); } void set(const nl_fptype Is, const nl_fptype n) { m_Is = Is; - m_VT = 0.0258 * n; + m_VT = plib::constants::cast(0.0258) * n; m_VT_inv = plib::reciprocal(m_VT); } nl_fptype I(const nl_fptype V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; } @@ -179,9 +184,9 @@ namespace analog , m_RB(*this, "m_RB", true) , m_RC(*this, "m_RC", true) , m_BC(*this, "m_BC", true) - , m_gB(1e-9) - , m_gC(1e-9) - , m_V(0.0) + , m_gB(plib::constants::cast(1e-9)) + , m_gC(plib::constants::cast(1e-9)) + , m_V(plib::constants::zero()) , m_state_on(*this, "m_state_on", 0) { register_subalias("B", m_RB.m_P); @@ -237,13 +242,13 @@ namespace analog connect(m_D_EB.m_N, m_D_CB.m_N); connect(m_D_CB.m_P, m_D_EC.m_N); - if (m_model.m_CJE > 0.0) + if (m_model.m_CJE > plib::constants::zero()) { create_and_register_subdevice("m_CJE", m_CJE); connect("B", "m_CJE.1"); connect("E", "m_CJE.2"); } - if (m_model.m_CJC > 0.0) + if (m_model.m_CJC > plib::constants::zero()) { create_and_register_subdevice("m_CJC", m_CJC); connect("B", "m_CJC.1"); @@ -292,13 +297,14 @@ namespace analog NETLIB_RESET(QBJT_switch) { NETLIB_NAME(QBJT)::reset(); + const auto zero(plib::constants::zero()); m_state_on = 0; - m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0); - m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0); + m_RB.set_G_V_I(exec().gmin(), zero, zero); + m_RC.set_G_V_I(exec().gmin(), zero, zero); - m_BC.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0); + m_BC.set_G_V_I(exec().gmin() / plib::constants::cast(10.0), zero, zero); } @@ -323,24 +329,25 @@ namespace analog set_qtype((m_model.type() == "NPN") ? BJT_NPN : BJT_PNP); - nl_fptype alpha = BF / (1.0 + BF); + nl_fptype alpha = BF / (plib::constants::one() + BF); diode d(IS, NF); // Assume 5mA Collector current for switch operation - m_V = d.V(0.005 / alpha); + const auto cc(plib::constants::cast(0.005)); + m_V = d.V(cc / alpha); /* Base current is 0.005 / beta * as a rough estimate, we just scale the conductance down */ - m_gB = plib::reciprocal((m_V/(0.005 / BF))); + m_gB = plib::reciprocal((m_V/(cc / BF))); //m_gB = d.gI(0.005 / alpha); if (m_gB < exec().gmin()) m_gB = exec().gmin(); - m_gC = d.gI(0.005); // very rough estimate + m_gC = d.gI(cc); // very rough estimate } NETLIB_UPDATE_TERMINALS(QBJT_switch) @@ -350,12 +357,13 @@ namespace analog const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0; if (m_state_on ^ new_state) { + const auto zero(plib::constants::zero()); const nl_fptype gb = new_state ? m_gB : exec().gmin(); const nl_fptype gc = new_state ? m_gC : exec().gmin(); - const nl_fptype v = new_state ? m_V * m : 0; + const nl_fptype v = new_state ? m_V * m : zero; - m_RB.set_G_V_I(gb, v, 0.0); - m_RC.set_G_V_I(gc, 0.0, 0.0); + m_RB.set_G_V_I(gb, v, zero); + m_RC.set_G_V_I(gc, zero, zero); m_state_on = new_state; } } @@ -395,7 +403,7 @@ namespace analog NETLIB_UPDATE_TERMINALS(QBJT_EB) { - const nl_fptype polarity = (qtype() == BJT_NPN ? 1.0 : -1.0); + const nl_fptype polarity = plib::constants::cast(qtype() == BJT_NPN ? 1.0 : -1.0); m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity); m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity); @@ -431,8 +439,8 @@ namespace analog set_qtype((m_model.type() == "NPN") ? BJT_NPN : BJT_PNP); - m_alpha_f = BF / (1.0 + BF); - m_alpha_r = BR / (1.0 + BR); + m_alpha_f = BF / (plib::constants::one() + BF); + m_alpha_r = BR / (plib::constants::one() + BR); m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin(), constants::T0()); m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin(), constants::T0()); diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h index fe56e25e674..6a5285b94f6 100644 --- a/src/lib/netlist/analog/nld_generic_models.h +++ b/src/lib/netlist/analog/nld_generic_models.h @@ -38,10 +38,10 @@ namespace analog { public: generic_capacitor(device_t &dev, const pstring &name) - : m_h(dev, name + ".m_h", 0.0) - , m_c(dev, name + ".m_c", 0.0) - , m_v(dev, name + ".m_v", 0.0) - , m_gmin(0.0) + : m_h(dev, name + ".m_h", plib::constants::zero()) + , m_c(dev, name + ".m_c", plib::constants::zero()) + , m_v(dev, name + ".m_v", plib::constants::zero()) + , m_gmin(plib::constants::zero()) { } @@ -57,7 +57,7 @@ namespace analog nl_fptype G(nl_fptype cap) const { //return m_h * cap + m_gmin; - return m_h * 0.5 * (cap + m_c) + m_gmin; + return m_h * plib::constants::half() * (cap + m_c) + m_gmin; //return m_h * cap + m_gmin; } @@ -65,7 +65,7 @@ namespace analog { plib::unused_var(v); //return -m_h * 0.5 * ((cap + m_c) * m_v + (cap - m_c) * v) ; - return -m_h * 0.5 * (cap + m_c) * m_v; + return -m_h * plib::constants::half() * (cap + m_c) * m_v; //return -m_h * cap * m_v; } @@ -91,9 +91,9 @@ namespace analog { public: generic_capacitor(device_t &dev, const pstring &name) - : m_h(dev, name + ".m_h", 0.0) - , m_v(dev, name + ".m_v", 0.0) - , m_gmin(0.0) + : m_h(dev, name + ".m_h", plib::constants::zero()) + , m_v(dev, name + ".m_v", plib::constants::zero()) + , m_gmin(plib::constants::zero()) { } @@ -133,25 +133,29 @@ namespace analog { public: generic_diode(device_t &dev, const pstring &name) - : m_Vd(dev, name + ".m_Vd", 0.7) - , m_Id(dev, name + ".m_Id", 0.0) - , m_G(dev, name + ".m_G", 1e-15) - , m_Vt(0.0) - , m_Vmin(0.0) // not used in MOS model - , m_Is(0.0) - , m_logIs(0.0) - , m_n(0.0) - , m_gmin(1e-15) - , m_VtInv(0.0) - , m_Vcrit(0.0) + : m_Vd(dev, name + ".m_Vd", plib::constants::cast(0.7)) + , m_Id(dev, name + ".m_Id", plib::constants::zero()) + , m_G(dev, name + ".m_G", plib::constants::cast(1e-15)) + , m_Vt(plib::constants::zero()) + , m_Vmin(plib::constants::zero()) // not used in MOS model + , m_Is(plib::constants::zero()) + , m_logIs(plib::constants::zero()) + , m_n(plib::constants::zero()) + , m_gmin(plib::constants::cast(1e-15)) + , m_VtInv(plib::constants::zero()) + , m_Vcrit(plib::constants::zero()) , m_name(name) { - set_param(1e-15, 1, 1e-15, 300.0); + set_param( + plib::constants::cast(1e-15) + , plib::constants::cast(1) + , plib::constants::cast(1e-15) + , plib::constants::cast(300.0)); } void update_diode(const nl_fptype nVd) { - nl_fptype IseVDVt(0.0); + nl_fptype IseVDVt(plib::constants::zero()); if (TYPE == diode_e::BIPOLAR) { @@ -160,7 +164,7 @@ namespace analog { const nl_fptype d = std::min(+fp_constants::DIODE_MAXDIFF(), nVd - m_Vd); const nl_fptype a = std::abs(d) * m_VtInv; - m_Vd = m_Vd + (d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt; + m_Vd = m_Vd + plib::constants::cast(d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt; } else m_Vd = std::max(-fp_constants::DIODE_MAXDIFF(), nVd); @@ -205,7 +209,7 @@ namespace analog m_Vt = m_n * temp * constants::k_b() / constants::Q_e(); - m_Vmin = -5.0 * m_Vt; + m_Vmin = plib::constants::cast(-5.0) * m_Vt; m_Vcrit = m_Vt * std::log(m_Vt / m_Is / constants::sqrt2()); m_VtInv = constants::one() / m_Vt; diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index e78de46252f..172f8cd75f0 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -195,20 +195,20 @@ namespace analog , m_cap_gb(*this, "m_cap_gb") , m_cap_gs(*this, "m_cap_gs") , m_cap_gd(*this, "m_cap_gd") - , m_phi(0.0) - , m_gamma(0.0) - , m_vto(0.0) - , m_beta(0.0) - , m_lambda(0.0) - , m_Leff(0.0) - , m_CoxWL(0.0) - , m_polarity(qtype() == FET_NMOS ? 1.0 : -1.0) - , m_Cgb(0.0) - , m_Cgs(0.0) - , m_Cgd(0.0) + , m_phi(plib::constants::zero()) + , m_gamma(plib::constants::zero()) + , m_vto(plib::constants::zero()) + , m_beta(plib::constants::zero()) + , m_lambda(plib::constants::zero()) + , m_Leff(plib::constants::zero()) + , m_CoxWL(plib::constants::zero()) + , m_polarity(plib::constants::cast(qtype() == FET_NMOS ? 1.0 : -1.0)) + , m_Cgb(plib::constants::zero()) + , m_Cgs(plib::constants::zero()) + , m_Cgd(plib::constants::zero()) , m_capmod(2) - , m_Vgs(*this, "m_Vgs", 0.0) - , m_Vgd(*this, "m_Vgd", 0.0) + , m_Vgs(*this, "m_Vgs", plib::constants::zero()) + , m_Vgd(*this, "m_Vgd", plib::constants::zero()) { register_subalias("S", m_SG.m_P); // Source register_subalias("G", m_SG.m_N); // Gate @@ -220,7 +220,7 @@ namespace analog connect(m_DG.m_P, m_SD.m_N); set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS); - m_polarity = qtype() == FET_NMOS ? 1.0 : -1.0; + m_polarity = qtype() == plib::constants::cast(FET_NMOS ? 1.0 : -1.0); m_capmod = m_model.m_CAPMOD; // printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_model.m_VTO, m_polarity); @@ -241,46 +241,49 @@ namespace analog // calculate effective channel length m_Leff = m_model.m_L - 2 * m_model.m_LD; - nl_assert_always(m_Leff > 0.0, "Effective Lateral diffusion would be negative for model " + m_model.name()); + nl_assert_always(m_Leff > plib::constants::zero(), "Effective Lateral diffusion would be negative for model " + m_model.name()); - nl_fptype Cox = (m_model.m_TOX > 0.0) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : 0.0; + nl_fptype Cox = (m_model.m_TOX > plib::constants::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : plib::constants::zero(); // calculate DC transconductance coefficient - if (m_model.m_KP > 0) + if (m_model.m_KP > plib::constants::zero()) m_beta = m_model.m_KP * m_model.m_W / m_Leff; - else if (Cox > 0 && m_model.m_UO > 0) - m_beta = m_model.m_UO * 1e-4 * Cox * m_model.m_W / m_Leff; + else if (Cox > plib::constants::zero() && m_model.m_UO > plib::constants::zero()) + m_beta = m_model.m_UO * plib::constants::cast(1e-4) * Cox * m_model.m_W / m_Leff; else - m_beta = 2e-5 * m_model.m_W / m_Leff; + m_beta = plib::constants::cast(2e-5) * m_model.m_W / m_Leff; //FIXME::UT can disappear const nl_fptype Vt = constants::T0() * constants::k_b() / constants::Q_e(); // calculate surface potential if not given - if (m_model.m_PHI > 0.0) + if (m_model.m_PHI > plib::constants::zero()) m_phi = m_model.m_PHI; - else if (m_model.m_NSUB > 0.0) + else if (m_model.m_NSUB > plib::constants::zero()) { - nl_assert_always(m_model.m_NSUB * 1e6 >= constants::NiSi(), "Error calculating phi for model " + m_model.name()); - m_phi = 2 * Vt * std::log (m_model.m_NSUB * 1e6 / constants::NiSi()); + nl_assert_always(m_model.m_NSUB * plib::constants::cast(1e6) >= constants::NiSi(), "Error calculating phi for model " + m_model.name()); + m_phi = plib::constants::two() * Vt * std::log (m_model.m_NSUB * plib::constants::cast(1e6) / constants::NiSi()); } else - m_phi = 0.6; + m_phi = plib::constants::cast(0.6); // calculate bulk threshold if not given - if (m_model.m_GAMMA > 0.0) + if (m_model.m_GAMMA > plib::constants::zero()) m_gamma = m_model.m_GAMMA; else { - if (Cox > 0.0 && m_model.m_NSUB > 0) - m_gamma = std::sqrt (2.0 * constants::Q_e() * constants::eps_Si() * constants::eps_0() * m_model.m_NSUB * 1e6) / Cox; + if (Cox > plib::constants::zero() && m_model.m_NSUB > plib::constants::zero()) + m_gamma = std::sqrt (plib::constants::two() + * constants::Q_e() * constants::eps_Si() * constants::eps_0() + * m_model.m_NSUB * plib::constants::cast(1e6)) / Cox; else - m_gamma = 0.0; + m_gamma = plib::constants::zero(); } m_vto = m_model.m_VTO; - if(m_vto != 0.0) + // FIXME zero conversion + if(m_vto != plib::constants::zero()) log().warning(MW_MOSFET_THRESHOLD_VOLTAGE(m_model.name())); /* FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models @@ -302,7 +305,7 @@ namespace analog //const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source const nl_fptype Ugd = m_Vgd; // Gate - Drain const nl_fptype Ugs = m_Vgs; // Gate - Source - const nl_fptype Ubs = 0.0; // Bulk - Source == 0 if connected + const nl_fptype Ubs = plib::constants::zero(); // Bulk - Source == 0 if connected const nl_fptype Ugb = Ugs - Ubs; m_cap_gb.timestep(m_Cgb, Ugb, step); @@ -385,21 +388,21 @@ namespace analog if (Vctrl <= -m_phi) { Cgb = m_CoxWL; - Cgs = 0.0; - Cgd = 0.0; + Cgs = plib::constants::zero(); + Cgd = plib::constants::zero(); } - else if (Vctrl <= -m_phi / 2.0) + else if (Vctrl <= -m_phi / plib::constants::two()) { Cgb = -Vctrl * m_CoxWL / m_phi; - Cgs = 0.0; - Cgd = 0.0; + Cgs = plib::constants::zero(); + Cgd = plib::constants::zero(); } // Depletion else if (Vctrl <= 0) { Cgb = -Vctrl * m_CoxWL / m_phi; - Cgs = Vctrl * m_CoxWL * (4.0 / 3.0) / m_phi + (2.0 / 3.0) * m_CoxWL; - Cgd = 0.0; + Cgs = Vctrl * m_CoxWL * plib::constants::cast(4.0 / 3.0) / m_phi + plib::constants::cast(2.0 / 3.0) * m_CoxWL; + Cgd = plib::constants::zero(); } else { @@ -408,18 +411,18 @@ namespace analog // saturation if (Vdsat <= Vds) { - Cgb = 0; - Cgs = (2.0 / 3.0) * m_CoxWL; - Cgd = 0; + Cgb = plib::constants::zero(); + Cgs = plib::constants::cast(2.0 / 3.0) * m_CoxWL; + Cgd = plib::constants::zero(); } else { // linear - const nl_fptype Sqr1 = std::pow(Vdsat - Vds, 2); - const nl_fptype Sqr2 = std::pow(2.0 * Vdsat - Vds, 2); + const nl_fptype Sqr1 = static_cast(std::pow(Vdsat - Vds, 2)); + const nl_fptype Sqr2 = static_cast(std::pow(plib::constants::two() * Vdsat - Vds, 2)); Cgb = 0; - Cgs = m_CoxWL * (1.0 - Sqr1 / Sqr2) * (2.0 / 3.0); - Cgd = m_CoxWL * (1.0 - Vdsat * Vdsat / Sqr2) * (2.0 / 3.0); + Cgs = m_CoxWL * (plib::constants::one() - Sqr1 / Sqr2) * plib::constants::cast(2.0 / 3.0); + Cgd = m_CoxWL * (plib::constants::one() - Vdsat * Vdsat / Sqr2) * plib::constants::cast(2.0 / 3.0); } } } @@ -447,16 +450,16 @@ namespace analog // limit step sizes - const nl_fptype k = 3.5; // see "Circuit Simulation", page 185 + const nl_fptype k = plib::constants::cast(3.5); // see "Circuit Simulation", page 185 nl_fptype d = (Vgs - m_Vgs); - Vgs = m_Vgs + plib::reciprocal(k) * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d)); + Vgs = m_Vgs + plib::reciprocal(k) * plib::constants::cast(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d)); d = (Vgd - m_Vgd); - Vgd = m_Vgd + plib::reciprocal(k) * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d)); + Vgd = m_Vgd + plib::reciprocal(k) * plib::constants::cast(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d)); m_Vgs = Vgs; m_Vgd = Vgd; - const nl_fptype Vbs = 0.0; // Bulk - Source == 0 if connected + const nl_fptype Vbs = plib::constants::zero(); // Bulk - Source == 0 if connected //const nl_nl_fptype Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain const nl_fptype Vds = Vgs - Vgd; const nl_fptype Vbd = -Vds; // Bulk - Drain = Source - Drain @@ -468,11 +471,11 @@ namespace analog // Are we in forward mode ? // in backward mode, just swap source and drain - const bool is_forward = Vds >= 0; + const bool is_forward = Vds >= plib::constants::zero(); // calculate Vth const nl_fptype Vbulk = is_forward ? Vbs : Vbd; - const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : 0.0; + const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : plib::constants::zero(); const nl_fptype Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi)); const nl_fptype Vctrl = (is_forward ? Vgs : Vgd) - Vth; @@ -480,34 +483,34 @@ namespace analog nl_fptype Ids(0), gm(0), gds(0), gmb(0); const nl_fptype absVds = std::abs(Vds); - if (Vctrl <= 0.0) + if (Vctrl <= plib::constants::zero()) { // cutoff region - Ids = 0.0; - gm = 0.0; - gds = 0.0; - gmb = 0.0; + Ids = plib::constants::zero(); + gm = plib::constants::zero(); + gds = plib::constants::zero(); + gmb = plib::constants::zero(); } else { - const nl_fptype beta = m_beta * (1.0 + m_lambda * absVds); + const nl_fptype beta = m_beta * (plib::constants::one() + m_lambda * absVds); if (Vctrl <= absVds) { // saturation region - Ids = beta * Vctrl * Vctrl / 2.0; + Ids = beta * Vctrl * Vctrl / plib::constants::two(); gm = beta * Vctrl; - gds = m_lambda * m_beta * Vctrl * Vctrl / 2.0; + gds = m_lambda * m_beta * Vctrl * Vctrl / plib::constants::two(); } else { // linear region - Ids = beta * absVds * (Vctrl - absVds / 2); + Ids = beta * absVds * (Vctrl - absVds / plib::constants::two()); gm = beta * absVds; - gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / 2.0); + gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / plib::constants::two()); } // backgate transconductance - const nl_fptype bgtc = (phi_m_Vbulk != 0.0) ? (m_gamma / phi_m_Vbulk / 2.0) : 0.0; + const nl_fptype bgtc = (phi_m_Vbulk != plib::constants::zero()) ? (m_gamma / phi_m_Vbulk / plib::constants::two()) : plib::constants::zero(); gmb = gm * bgtc; } @@ -524,27 +527,27 @@ namespace analog const nl_fptype IeqBS = m_D_BS.Ieq(); const nl_fptype gbs = m_D_BS.G(); #else - const nl_fptype IeqBS = 0.0; - const nl_fptype gbs = 0.0; + const nl_fptype IeqBS = plib::constants::zero(); + const nl_fptype gbs = plib::constants::zero(); #endif // exchange controlling nodes if necessary - const nl_fptype gsource = is_forward ? (gm + gmb) : 0; - const nl_fptype gdrain = is_forward ? 0.0 : (gm + gmb); + const nl_fptype gsource = is_forward ? (gm + gmb) : plib::constants::zero(); + const nl_fptype gdrain = is_forward ? plib::constants::zero() : (gm + gmb); const nl_fptype IeqDS = (is_forward) ? Ids - gm * Vgs - gmb * Vbs - gds * Vds : -Ids - gm * Vgd - gmb * Vbd - gds * Vds; // IG = 0 - nl_fptype IG = 0.0; + nl_fptype IG = plib::constants::zero(); nl_fptype ID = (+IeqBD - IeqDS) * m_polarity; nl_fptype IS = (+IeqBS + IeqDS) * m_polarity; nl_fptype IB = (-IeqBD - IeqBS) * m_polarity; - nl_fptype gGG = 0.0; - nl_fptype gGD = 0.0; - nl_fptype gGS = 0.0; - nl_fptype gGB = 0.0; + nl_fptype gGG = plib::constants::zero(); + nl_fptype gGD = plib::constants::zero(); + nl_fptype gGS = plib::constants::zero(); + nl_fptype gGB = plib::constants::zero(); nl_fptype gDG = gm; nl_fptype gDD = gds + gbd - gdrain; @@ -556,7 +559,7 @@ namespace analog nl_fptype gSS = gbs + gds + gsource; const nl_fptype gSB = -gbs - gmb; - nl_fptype gBG = 0.0; + nl_fptype gBG = plib::constants::zero(); const nl_fptype gBD = -gbd; const nl_fptype gBS = -gbs; nl_fptype gBB = gbs + gbd; @@ -577,16 +580,16 @@ namespace analog // Source connected to body, Diode S-B shorted! const nl_fptype gSSBB = gSS + gBB + gBS + gSB; - + const auto zero(plib::constants::zero()); // S 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, 0.0, 0.0 ); // G + gGD, zero, zero ); // G // S D - m_SD.set_mat( 0.0, gSD + gBD, 0.0, // S - gDS + gDB, 0.0, 0.0); // 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 77ca356116c..dfd1e06b139 100644 --- a/src/lib/netlist/analog/nld_opamps.cpp +++ b/src/lib/netlist/analog/nld_opamps.cpp @@ -197,13 +197,13 @@ namespace netlist NETLIB_UPDATE(opamp) { - const nl_fptype cVt = 0.0258 * 1.0; // * m_n; + const nl_fptype cVt = plib::constants::cast(0.0258 * 1.0); // * m_n; const nl_fptype cId = m_model.m_DAB; // 3 mA - const nl_fptype cVd = cVt * std::log(cId / 1e-15 + 1.0); + const nl_fptype cVd = cVt * std::log(cId / plib::constants::cast(1e-15) + plib::constants::one()); m_VH.push(m_VCC() - m_model.m_VLH - cVd); m_VL.push(m_GND() + m_model.m_VLL + cVd); - m_VREF.push((m_VCC() + m_GND()) / 2.0); + m_VREF.push((m_VCC() + m_GND()) / plib::constants::two()); } NETLIB_UPDATE_PARAM(opamp) @@ -220,11 +220,11 @@ namespace netlist if (m_type == 3 || m_type == 2) { nl_fptype CP = m_model.m_DAB / m_model.m_SLEW; - nl_fptype RP = 0.5 / constants::pi() / CP / m_model.m_FPF; + nl_fptype RP = plib::constants::half() / constants::pi() / CP / m_model.m_FPF; nl_fptype G = m_model.m_UGF / m_model.m_FPF / RP; //printf("OPAMP %s: %g %g %g\n", name().c_str(), CP, RP, G); - if (m_model.m_SLEW / (4.0 * constants::pi() * 0.0258) < m_model.m_UGF) + if (m_model.m_SLEW / (plib::constants::four() * constants::pi() * plib::constants::cast(0.0258)) < m_model.m_UGF) log().warning(MW_OPAMP_FAIL_CONVERGENCE(this->name())); m_CP->m_C.setTo(CP); @@ -234,12 +234,12 @@ namespace netlist } if (m_type == 2) { - m_EBUF->m_G.setTo(1.0); + m_EBUF->m_G.setTo(plib::constants::one()); m_EBUF->m_RO.setTo(m_model.m_RO); } if (m_type == 3) { - m_EBUF->m_G.setTo(1.0); + m_EBUF->m_G.setTo(plib::constants::one()); m_EBUF->m_RO.setTo(m_model.m_RO); } } diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp index 9b73eb9650f..8f0647da04c 100644 --- a/src/lib/netlist/analog/nld_switches.cpp +++ b/src/lib/netlist/analog/nld_switches.cpp @@ -13,7 +13,7 @@ /* FIXME : convert to parameters */ #define R_OFF (plib::reciprocal(exec().gmin())) -#define R_ON 0.01 +#define R_ON plib::constants::cast(0.01) namespace netlist { diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h index fbebe8be6cf..39ad2dfc162 100644 --- a/src/lib/netlist/analog/nld_twoterm.h +++ b/src/lib/netlist/analog/nld_twoterm.h @@ -53,15 +53,15 @@ #warning "Do not include rescap.h in a netlist environment" #endif #ifndef RES_R -#define RES_R(res) (static_cast(res)) -#define RES_K(res) (static_cast(res) * 1e3) -#define RES_M(res) (static_cast(res) * 1e6) -#define CAP_U(cap) (static_cast(cap) * 1e-6) -#define CAP_N(cap) (static_cast(cap) * 1e-9) -#define CAP_P(cap) (static_cast(cap) * 1e-12) -#define IND_U(ind) (static_cast(ind) * 1e-6) -#define IND_N(ind) (static_cast(ind) * 1e-9) -#define IND_P(ind) (static_cast(ind) * 1e-12) +#define RES_R(res) (res) +#define RES_K(res) ((res) * 1e3) +#define RES_M(res) ((res) * 1e6) +#define CAP_U(cap) ((cap) * 1e-6) +#define CAP_N(cap) ((cap) * 1e-9) +#define CAP_P(cap) ((cap) * 1e-12) +#define IND_U(ind) ((ind) * 1e-6) +#define IND_N(ind) ((ind) * 1e-9) +#define IND_P(ind) ((ind) * 1e-12) #endif #endif /* NLD_TWOTERM_H_ */ diff --git a/src/lib/netlist/analog/nlid_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp index 49955c0c952..ea5687c4f80 100644 --- a/src/lib/netlist/analog/nlid_fourterm.cpp +++ b/src/lib/netlist/analog/nlid_fourterm.cpp @@ -67,16 +67,17 @@ NETLIB_UPDATE_TERMINALS(LVCCS) { const nl_fptype m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A const nl_fptype vi = m_IP.net().Q_Analog() - m_IN.net().Q_Analog(); + const auto c1(plib::constants::cast(0.2)); - if (std::abs(m_mult / m_cur_limit() * vi) > 0.5) - m_vi = m_vi + 0.2*std::tanh((vi - m_vi)/0.2); + if (std::abs(m_mult / m_cur_limit() * vi) > plib::constants::half()) + m_vi = m_vi + c1 * std::tanh((vi - m_vi) / c1); else m_vi = vi; const nl_fptype x = m_mult / m_cur_limit() * m_vi; const nl_fptype X = std::tanh(x); - const nl_fptype beta = m_mult * (1.0 - X*X); + const nl_fptype beta = m_mult * (plib::constants::one() - X*X); const nl_fptype I = m_cur_limit() * X - beta * m_vi; m_OP.set_go_gt_I(-beta, plib::constants::zero(), I); diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h index 7faaac926c1..4900b55fda6 100644 --- a/src/lib/netlist/analog/nlid_fourterm.h +++ b/src/lib/netlist/analog/nlid_fourterm.h @@ -39,15 +39,15 @@ namespace netlist { { public: NETLIB_CONSTRUCTOR(VCCS) - , m_G(*this, "G", 1.0) - , m_RI(*this, "RI", 1e9) + , m_G(*this, "G", plib::constants::one()) + , m_RI(*this, "RI", plib::constants::cast(1e9)) , m_OP(*this, "OP", &m_IP) , m_ON(*this, "ON", &m_IP) , m_IP(*this, "IP", &m_IN) // <= this should be NULL and terminal be filtered out prior to solving... , m_IN(*this, "IN", &m_IP) // <= this should be NULL and terminal be filtered out prior to solving... , m_OP1(*this, "_OP1", &m_IN) , m_ON1(*this, "_ON1", &m_IN) - , m_gfac(1.0) + , m_gfac(plib::constants::one()) { connect(m_OP, m_OP1); connect(m_ON, m_ON1); @@ -85,8 +85,8 @@ namespace netlist { { public: NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS) - , m_cur_limit(*this, "CURLIM", 1000.0) - , m_vi(0.0) + , m_cur_limit(*this, "CURLIM", plib::constants::cast(1000.0)) + , m_vi(plib::constants::zero()) { } @@ -174,7 +174,7 @@ namespace netlist { { public: NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS) - , m_RO(*this, "RO", 1.0) + , m_RO(*this, "RO", plib::constants::one()) , m_OP2(*this, "_OP2", &m_ON2) , m_ON2(*this, "_ON2", &m_OP2) { diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp index fe928782810..c9d94c98f51 100644 --- a/src/lib/netlist/analog/nlid_twoterm.cpp +++ b/src/lib/netlist/analog/nlid_twoterm.cpp @@ -64,7 +64,7 @@ NETLIB_RESET(POT) { nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0); + v = (std::exp(v) - plib::constants::one()) / (std::exp(plib::constants::one()) - plib::constants::one()); m_R1.set_R(std::max(m_R() * v, exec().gmin())); m_R2.set_R(std::max(m_R() * (plib::constants::one() - v), exec().gmin())); @@ -77,9 +77,9 @@ NETLIB_UPDATE_PARAM(POT) nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0); + v = (std::exp(v) - plib::constants::one()) / (std::exp(plib::constants::one()) - plib::constants::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants::one() - v; m_R1.set_R(std::max(m_R() * v, exec().gmin())); m_R2.set_R(std::max(m_R() * (plib::constants::one() - v), exec().gmin())); @@ -94,9 +94,9 @@ NETLIB_RESET(POT2) nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0); + v = (std::exp(v) - plib::constants::one()) / (std::exp(plib::constants::one()) - plib::constants::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants::one() - v; m_R1.set_R(std::max(m_R() * v, exec().gmin())); } @@ -108,9 +108,9 @@ NETLIB_UPDATE_PARAM(POT2) nl_fptype v = m_Dial(); if (m_DialIsLog()) - v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0); + v = (std::exp(v) - plib::constants::one()) / (std::exp(plib::constants::one()) - plib::constants::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants::one() - v; m_R1.set_R(std::max(m_R() * v, exec().gmin())); } @@ -121,7 +121,7 @@ NETLIB_UPDATE_PARAM(POT2) NETLIB_RESET(L) { m_gmin = exec().gmin(); - m_I = 0.0; + m_I = plib::constants::zero(); m_G = m_gmin; set_mat( m_G, -m_G, -m_I, -m_G, m_G, m_I); @@ -152,7 +152,7 @@ NETLIB_RESET(D) nl_fptype n = m_model.m_N; m_D.set_param(Is, n, exec().gmin(), constants::T0()); - set_G_V_I(m_D.G(), 0.0, m_D.Ieq()); + set_G_V_I(m_D.G(), plib::constants::zero(), m_D.Ieq()); } NETLIB_UPDATE_PARAM(D) diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index cb80e15a34a..72de24181e0 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -128,8 +128,8 @@ namespace analog void set_R(const nl_fptype R) { const nl_fptype G = plib::constants::one() / R; - set_mat( G, -G, 0.0, - -G, G, 0.0); + set_mat( G, -G, plib::constants::zero(), + -G, G, plib::constants::zero()); } NETLIB_RESETI(); @@ -142,7 +142,7 @@ namespace analog NETLIB_OBJECT_DERIVED(R, R_base) { NETLIB_CONSTRUCTOR_DERIVED(R, R_base) - , m_R(*this, "R", 1e9) + , m_R(*this, "R", plib::constants::cast(1e9)) { } @@ -178,7 +178,7 @@ namespace analog , m_R1(*this, "_R1") , m_R2(*this, "_R2") , m_R(*this, "R", 10000) - , m_Dial(*this, "DIAL", 0.5) + , m_Dial(*this, "DIAL", plib::constants::half()) , m_DialIsLog(*this, "DIALLOG", false) , m_Reverse(*this, "REVERSE", false) { @@ -208,8 +208,8 @@ namespace analog { NETLIB_CONSTRUCTOR(POT2) , m_R1(*this, "_R1") - , m_R(*this, "R", 10000) - , m_Dial(*this, "DIAL", 0.5) + , m_R(*this, "R", plib::constants::cast(10000.0)) + , m_Dial(*this, "DIAL", plib::constants::half()) , m_DialIsLog(*this, "DIALLOG", false) , m_Reverse(*this, "REVERSE", false) { @@ -239,7 +239,7 @@ namespace analog { public: NETLIB_CONSTRUCTOR_DERIVED(C, twoterm) - , m_C(*this, "C", 1e-6) + , m_C(*this, "C", plib::constants::cast(1e-6)) , m_cap(*this, "m_cap") { } @@ -289,10 +289,10 @@ namespace analog { public: NETLIB_CONSTRUCTOR_DERIVED(L, twoterm) - , m_L(*this, "L", 1e-6) - , m_gmin(0.0) - , m_G(0.0) - , m_I(0.0) + , m_L(*this, "L", plib::constants::cast(1e-6)) + , m_gmin(plib::constants::zero()) + , m_G(plib::constants::zero()) + , m_I(plib::constants::zero()) { //register_term("1", m_P); //register_term("2", m_N); @@ -392,12 +392,12 @@ namespace analog { public: NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm) - , m_t(*this, "m_t", 0.0) - , m_R(*this, "R", 0.1) - , m_V(*this, "V", 0.0) + , m_t(*this, "m_t", plib::constants::zero()) + , m_R(*this, "R", plib::constants::cast(0.1)) + , m_V(*this, "V", plib::constants::zero()) , m_func(*this,"FUNC", "") , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_funcparam({plib::constants::zero()}) { register_subalias("P", m_P); register_subalias("N", m_N); @@ -413,7 +413,7 @@ namespace analog m_funcparam[0] = m_t; this->set_G_V_I(plib::reciprocal(m_R()), m_compiled.evaluate(m_funcparam), - 0.0); + plib::constants::zero()); } protected: @@ -422,7 +422,7 @@ namespace analog NETLIB_RESETI() { NETLIB_NAME(twoterm)::reset(); - this->set_G_V_I(plib::reciprocal(m_R()), m_V(), 0.0); + this->set_G_V_I(plib::reciprocal(m_R()), m_V(), plib::constants::zero()); } private: @@ -442,11 +442,11 @@ namespace analog { public: NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm) - , m_t(*this, "m_t", 0.0) - , m_I(*this, "I", 1.0) + , m_t(*this, "m_t", plib::constants::zero()) + , m_I(*this, "I", plib::constants::one()) , m_func(*this,"FUNC", "") , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_funcparam({plib::constants::zero()}) { register_subalias("P", m_P); register_subalias("N", m_N); @@ -460,8 +460,9 @@ namespace analog m_t += step; m_funcparam[0] = m_t; const nl_fptype I = m_compiled.evaluate(m_funcparam); - set_mat(0.0, 0.0, -I, - 0.0, 0.0, I); + const auto zero(plib::constants::zero()); + set_mat(zero, zero, -I, + zero, zero, I); } protected: @@ -470,15 +471,17 @@ namespace analog NETLIB_RESETI() { NETLIB_NAME(twoterm)::reset(); - set_mat(0.0, 0.0, -m_I(), - 0.0, 0.0, m_I()); + const auto zero(plib::constants::zero()); + set_mat(zero, zero, -m_I(), + zero, zero, m_I()); } NETLIB_UPDATE_PARAMI() { solve_now(); - set_mat(0.0, 0.0, -m_I(), - 0.0, 0.0, m_I()); + const auto zero(plib::constants::zero()); + set_mat(zero, zero, -m_I(), + zero, zero, m_I()); } diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp index 798beffa975..ed14748975a 100644 --- a/src/lib/netlist/devices/nld_4066.cpp +++ b/src/lib/netlist/devices/nld_4066.cpp @@ -22,7 +22,7 @@ namespace netlist , m_supply(*this, "VDD", "VSS", true) , m_R(*this, "R") , m_control(*this, "CTL") - , m_base_r(*this, "BASER", 270.0) + , m_base_r(*this, "BASER", plib::constants::cast(270.0)) { } @@ -52,7 +52,7 @@ namespace netlist nl_fptype high = plib::constants::cast(0.55) * sup; nl_fptype in = m_control() - m_supply.GND(); nl_fptype rON = m_base_r() * plib::constants::cast(5.0) / sup; - nl_fptype R = -1.0; + nl_fptype R = -plib::constants::one(); if (in < low) { diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp index 26a188502a8..206dffc821d 100644 --- a/src/lib/netlist/devices/nld_4316.cpp +++ b/src/lib/netlist/devices/nld_4316.cpp @@ -20,7 +20,7 @@ namespace netlist { namespace devices { , m_R(*this, "_R") , m_S(*this, "S") , m_E(*this, "E") - , m_base_r(*this, "BASER", 45.0) + , m_base_r(*this, "BASER", plib::constants::cast(45.0)) { } diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp index 067e6ca1918..a7d654a83d2 100644 --- a/src/lib/netlist/devices/nld_74123.cpp +++ b/src/lib/netlist/devices/nld_74123.cpp @@ -31,8 +31,8 @@ namespace netlist , m_last_trig(*this, "m_last_trig", 0) , m_state(*this, "m_state", 0) , m_KP(*this, "m_KP", 0) - , m_K(*this, "K", (m_dev_type == 4538) ? 1.0 : 0.4) // CD4538 datasheet states PW=RC - , m_RI(*this, "RI", 400.0) // around 250 for HC series, 400 on LS/TTL, estimated from datasheets + , m_K(*this, "K", plib::constants::cast((m_dev_type == 4538) ? 1.0 : 0.4)) // CD4538 datasheet states PW=RC + , m_RI(*this, "RI", plib::constants::cast(400.0)) // around 250 for HC series, 400 on LS/TTL, estimated from datasheets { if ((m_dev_type != 9602) && (m_dev_type != 4538) ) m_dev_type = 74123; @@ -241,7 +241,7 @@ namespace netlist } if (m_state == 2) { - const nl_fptype vHigh = m_RP.m_R.m_P() * (1.0 - m_KP); + const nl_fptype vHigh = m_RP.m_R.m_P() * (plib::constants::one() - m_KP); if (m_CV() > vHigh) { m_RP_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF @@ -255,7 +255,7 @@ namespace netlist NETLIB_RESET(74123) { - m_KP = plib::reciprocal(1.0 + exp(m_K())); + m_KP = plib::reciprocal(plib::constants::one() + std::exp(m_K())); m_RP.reset(); m_RN.reset(); diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp index 42c9292315c..f95da603e7e 100644 --- a/src/lib/netlist/devices/nld_74ls629.cpp +++ b/src/lib/netlist/devices/nld_74ls629.cpp @@ -85,7 +85,7 @@ namespace netlist , m_ENQ(*this, "ENQ") , m_RNG(*this, "RNG") , m_FC(*this, "FC") - , m_CAP(*this, "CAP", 1e-6) + , m_CAP(*this, "CAP", plib::constants::cast(1e-6)) { register_subalias("GND", m_R_FC.m_N); @@ -98,8 +98,8 @@ namespace netlist NETLIB_RESETI() { - m_R_FC.set_R(90000.0); - m_R_RNG.set_R(90000.0); + m_R_FC.set_R( plib::constants::cast(90000.0)); + m_R_RNG.set_R(plib::constants::cast(90000.0)); m_clock.reset(); } NETLIB_UPDATEI(); @@ -179,16 +179,16 @@ namespace netlist nl_fptype v_rng = m_RNG(); /* coefficients */ - const nl_fptype k1 = 1.9904769024796283E+03; - const nl_fptype k2 = 1.2070059213983407E+03; - const nl_fptype k3 = 1.3266985579561108E+03; - const nl_fptype k4 = -1.5500979825922698E+02; - const nl_fptype k5 = 2.8184536266938172E+00; - const nl_fptype k6 = -2.3503421582744556E+02; - const nl_fptype k7 = -3.3836786704527788E+02; - const nl_fptype k8 = -1.3569136703258670E+02; - const nl_fptype k9 = 2.9914575453819188E+00; - const nl_fptype k10 = 1.6855569086173170E+00; + const nl_fptype k1 = plib::constants::cast( 1.9904769024796283E+03); + const nl_fptype k2 = plib::constants::cast( 1.2070059213983407E+03); + const nl_fptype k3 = plib::constants::cast( 1.3266985579561108E+03); + const nl_fptype k4 = plib::constants::cast(-1.5500979825922698E+02); + const nl_fptype k5 = plib::constants::cast( 2.8184536266938172E+00); + const nl_fptype k6 = plib::constants::cast(-2.3503421582744556E+02); + const nl_fptype k7 = plib::constants::cast(-3.3836786704527788E+02); + const nl_fptype k8 = plib::constants::cast(-1.3569136703258670E+02); + const nl_fptype k9 = plib::constants::cast( 2.9914575453819188E+00); + const nl_fptype k10 = plib::constants::cast( 1.6855569086173170E+00); /* scale due to input resistance */ @@ -212,7 +212,7 @@ namespace netlist // FIXME: we need a possibility to remove entries from queue ... // or an exact model ... - m_clock.m_inc = netlist_time::from_fp(0.5 / freq); + m_clock.m_inc = netlist_time::from_fp(plib::constants::half() / freq); //m_clock.update(); //NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq)); diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp index 5d32c8ff8cd..21b7e7d17ab 100644 --- a/src/lib/netlist/devices/nld_mm5837.cpp +++ b/src/lib/netlist/devices/nld_mm5837.cpp @@ -69,9 +69,11 @@ namespace netlist { //m_V0.initial(0.0); //m_RV.do_reset(); - m_RV.set_G_V_I(plib::constants::one() / R_LOW, 0.0, 0.0); + m_RV.set_G_V_I(plib::constants::one() / plib::constants::cast(R_LOW), + plib::constants::zero(), + plib::constants::zero()); m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); - if (m_FREQ() < 24000 || m_FREQ() > 56000) + if (m_FREQ() < plib::constants::cast(24000) || m_FREQ() > plib::constants::cast(56000)) log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); m_shift = 0x1ffff; @@ -81,7 +83,7 @@ namespace netlist NETLIB_UPDATE_PARAM(MM5837_dip) { m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); - if (m_FREQ() < 24000 || m_FREQ() > 56000) + if (m_FREQ() < plib::constants::cast(24000) || m_FREQ() > plib::constants::cast(56000)) log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); } @@ -102,7 +104,7 @@ namespace netlist if (state != last_state) { - const nl_fptype R = state ? R_HIGH : R_LOW; + const nl_fptype R = plib::constants::cast(state ? R_HIGH : R_LOW); const nl_fptype V = state ? m_VDD() : m_VSS(); // We only need to update the net first if this is a time stepping net diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp index 05a334c2fe4..5c28f8313c0 100644 --- a/src/lib/netlist/devices/nld_ne555.cpp +++ b/src/lib/netlist/devices/nld_ne555.cpp @@ -140,11 +140,11 @@ namespace netlist m_RDIS.reset(); /* FIXME make resistances a parameter, properly model other variants */ - m_R1.set_R(5000); - m_R2.set_R(5000); - m_R3.set_R(5000); - m_ROUT.set_R(20); - m_RDIS.set_R(R_OFF); + m_R1.set_R(plib::constants::cast(5000)); + m_R2.set_R(plib::constants::cast(5000)); + m_R3.set_R(plib::constants::cast(5000)); + m_ROUT.set_R(plib::constants::cast(20)); + m_RDIS.set_R(plib::constants::cast(R_OFF)); m_last_out = true; } @@ -161,9 +161,9 @@ namespace netlist } else { - const nl_fptype vt = clamp(m_R2.m_P(), 0.7, 1.4); + const nl_fptype vt = clamp(m_R2.m_P(), plib::constants::cast(0.7), plib::constants::cast(1.4)); const bool bthresh = (m_THRES() > vt); - const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4)); + const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), plib::constants::cast(0.7), plib::constants::cast(1.4))); if (!btrig) m_ff = true; @@ -177,14 +177,14 @@ namespace netlist { m_RDIS.update(); m_OUT.push(m_R3.m_N()); - m_RDIS.set_R(R_ON); + m_RDIS.set_R(plib::constants::cast(R_ON)); } else if (!m_last_out && out) { m_RDIS.update(); // FIXME: Should be delayed by 100ns m_OUT.push(m_R1.m_P()); - m_RDIS.set_R(R_OFF); + m_RDIS.set_R(plib::constants::cast(R_OFF)); } m_last_reset = reset; m_last_out = out; diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp index c1cc4462b7b..6d83d755791 100644 --- a/src/lib/netlist/devices/nld_r2r_dac.cpp +++ b/src/lib/netlist/devices/nld_r2r_dac.cpp @@ -16,8 +16,8 @@ namespace netlist NETLIB_OBJECT_DERIVED(r2r_dac, twoterm) { NETLIB_CONSTRUCTOR_DERIVED(r2r_dac, twoterm) - , m_VIN(*this, "VIN", 1.0) - , m_R(*this, "R", 1.0) + , m_VIN(*this, "VIN", plib::constants::one()) + , m_R(*this, "R", plib::constants::one()) , m_num(*this, "N", 1) , m_val(*this, "VAL", 1) { @@ -44,7 +44,7 @@ namespace netlist nl_fptype V = m_VIN() / static_cast(1 << m_num()) * static_cast(m_val()); - this->set_G_V_I(plib::reciprocal(m_R()), V, 0.0); + this->set_G_V_I(plib::reciprocal(m_R()), V, plib::constants::zero()); } } //namespace analog diff --git a/src/lib/netlist/devices/nld_schmitt.cpp b/src/lib/netlist/devices/nld_schmitt.cpp index 95739cfd662..fafeaa9f2a8 100644 --- a/src/lib/netlist/devices/nld_schmitt.cpp +++ b/src/lib/netlist/devices/nld_schmitt.cpp @@ -85,8 +85,8 @@ namespace netlist m_RVI.reset(); m_RVO.reset(); m_is_timestep = m_RVO.m_P.net().solver()->has_timestep_devices(); - m_RVI.set_G_V_I(plib::constants::one() / m_model.m_RI, m_model.m_VI, 0.0); - m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROL, m_model.m_VOL, 0.0); + m_RVI.set_G_V_I(plib::constants::one() / m_model.m_RI, m_model.m_VI, plib::constants::zero()); + m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROL, m_model.m_VOL, plib::constants::zero()); } NETLIB_UPDATEI() @@ -98,7 +98,7 @@ namespace netlist m_last_state = 0; if (m_is_timestep) m_RVO.update(); - m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROH, m_model.m_VOH, 0.0); + m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROH, m_model.m_VOH, plib::constants::zero()); m_RVO.solve_later(); } } @@ -109,7 +109,7 @@ namespace netlist m_last_state = 1; if (m_is_timestep) m_RVO.update(); - m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROL, m_model.m_VOL, 0.0); + m_RVO.set_G_V_I(plib::constants::one() / m_model.m_ROL, m_model.m_VOL, plib::constants::zero()); m_RVO.solve_later(); } } diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index 2b608185ff6..9f5be46a6cd 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -52,11 +52,11 @@ namespace netlist nl_assert(m_logic_family != nullptr); // FIXME: Variable supply voltage! nl_fptype supply_V = logic_family()->fixed_V(); - if (supply_V == 0.0) supply_V = 5.0; + if (supply_V == plib::constants::zero()) supply_V = plib::constants::cast(5.0); - if (m_I.Q_Analog() > logic_family()->high_thresh_V(0.0, supply_V)) + if (m_I.Q_Analog() > logic_family()->high_thresh_V(plib::constants::zero(), supply_V)) out().push(1, netlist_time::quantum()); - else if (m_I.Q_Analog() < logic_family()->low_thresh_V(0.0, supply_V)) + else if (m_I.Q_Analog() < logic_family()->low_thresh_V(plib::constants::zero(), supply_V)) out().push(0, netlist_time::quantum()); else { @@ -112,7 +112,7 @@ namespace netlist //FIXME: Use power terminals and change info to warning or error if (!f) { - if (logic_family()->fixed_V() == 0.0) + if (logic_family()->fixed_V() == plib::constants::zero()) log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); else log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); @@ -148,7 +148,9 @@ namespace netlist { // FIXME: Variable voltage nl_fptype supply_V = logic_family()->fixed_V(); - if (supply_V == 0.0) supply_V = 5.0; + // FIXME: comparison to zero + if (supply_V == plib::constants::zero()) + supply_V = plib::constants::cast(5.0); //m_Q.initial(0.0); m_last_state = -1; @@ -160,9 +162,10 @@ namespace netlist m_VCCHack->initial(supply_V); m_is_timestep = m_RN.m_P.net().solver()->has_timestep_devices(); m_RN.set_G_V_I(plib::constants::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); + logic_family()->low_offset_V(), plib::constants::zero()); m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); + plib::constants::zero(), + plib::constants::zero()); } NETLIB_UPDATE(d_to_a_proxy) @@ -178,16 +181,18 @@ namespace netlist if (state) { m_RN.set_G_V_I(G_OFF, - 0.0, 0.0); + plib::constants::zero(), + plib::constants::zero()); m_RP.set_G_V_I(plib::constants::one() / logic_family()->R_high(), - logic_family()->high_offset_V(), 0.0); + logic_family()->high_offset_V(), plib::constants::zero()); } else { m_RN.set_G_V_I(plib::constants::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); + logic_family()->low_offset_V(), plib::constants::zero()); m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); + plib::constants::zero(), + plib::constants::zero()); } m_RN.solve_later(); // RN, RP are connected ... m_last_state = state; diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h index bdf871d9f9b..30043580306 100644 --- a/src/lib/netlist/devices/nlid_proxy.h +++ b/src/lib/netlist/devices/nlid_proxy.h @@ -104,7 +104,7 @@ namespace netlist private: - static constexpr const nl_fptype G_OFF = 1e-9; + static constexpr const nl_fptype G_OFF = plib::constants::cast(1e-9); plib::unique_ptr m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd plib::unique_ptr m_VCCHack; // FIXME: Long term, we need to connect proxy gnd to device gnd diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index d57de8f4750..c92c18b56e3 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -52,9 +52,9 @@ namespace devices { NETLIB_CONSTRUCTOR(mainclock) , m_Q(*this, "Q") - , m_freq(*this, "FREQ", 7159000.0 * 5) + , m_freq(*this, "FREQ", plib::constants::cast(7159000.0 * 5)) { - m_inc = netlist_time::from_fp(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); } NETLIB_RESETI() @@ -64,7 +64,7 @@ namespace devices NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_fp(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); } NETLIB_UPDATEI() @@ -91,9 +91,9 @@ namespace devices NETLIB_CONSTRUCTOR(clock) , m_feedback(*this, "FB") , m_Q(*this, "Q") - , m_freq(*this, "FREQ", 7159000.0 * 5.0) + , m_freq(*this, "FREQ", plib::constants::cast(7159000.0 * 5.0)) { - m_inc = netlist_time::from_fp(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); connect(m_feedback, m_Q); } @@ -101,7 +101,7 @@ namespace devices NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_fp(1.0 / (m_freq() * 2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); } NETLIB_UPDATEI() @@ -128,7 +128,7 @@ namespace devices , m_Q(*this, "Q") , m_func(*this,"FUNC", "") , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_funcparam({plib::constants::zero()}) { if (m_func() != "") m_compiled.compile(std::vector({{pstring("T")}}), m_func()); @@ -160,19 +160,19 @@ namespace devices NETLIB_OBJECT(extclock) { NETLIB_CONSTRUCTOR(extclock) - , m_freq(*this, "FREQ", 7159000.0 * 5.0) + , m_freq(*this, "FREQ", plib::constants::cast(7159000.0 * 5.0)) , m_pattern(*this, "PATTERN", "1,1") - , m_offset(*this, "OFFSET", 0.0) + , m_offset(*this, "OFFSET", plib::constants::zero()) , m_feedback(*this, "FB") , m_Q(*this, "Q") , m_cnt(*this, "m_cnt", 0) , m_off(*this, "m_off", netlist_time::zero()) { - m_inc[0] = netlist_time::from_fp(1.0 / (m_freq() * 2.0)); + m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); connect(m_feedback, m_Q); - netlist_time base = netlist_time::from_fp(1.0 / (m_freq()*2.0)); + netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants::two())); std::vector pat(plib::psplit(m_pattern(),",")); m_off = netlist_time::from_fp(m_offset()); @@ -250,12 +250,12 @@ namespace devices { NETLIB_CONSTRUCTOR(analog_input) , m_Q(*this, "Q") - , m_IN(*this, "IN", 0.0) + , m_IN(*this, "IN", plib::constants::zero()) { } NETLIB_UPDATEI() { } - NETLIB_RESETI() { m_Q.initial(0.0); } + NETLIB_RESETI() { m_Q.initial(plib::constants::zero()); } NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); } private: @@ -275,7 +275,7 @@ namespace devices } NETLIB_UPDATEI() { - m_Q.push(0.0); + m_Q.push(plib::constants::zero()); } NETLIB_RESETI() { } protected: @@ -316,8 +316,8 @@ namespace devices , m_ROUT(*this, "m_ROUT", true) , m_I(*this, "_I") , m_Q(*this, "_Q") - , m_p_RIN(*this, "RIN", 1.0e6) - , m_p_ROUT(*this, "ROUT", 50.0) + , m_p_RIN(*this, "RIN", plib::constants::cast(1.0e6)) + , m_p_ROUT(*this, "ROUT", plib::constants::cast(50.0)) { register_subalias("I", m_RIN.m_P); @@ -371,7 +371,7 @@ namespace devices pstring n = plib::pfmt("A{1}")(i); m_I.push_back(pool().make_unique(*this, n)); inps.push_back(n); - m_vals.push_back(0.0); + m_vals.push_back(plib::constants::zero()); } m_compiled.compile(inps, m_func()); } @@ -402,8 +402,8 @@ namespace devices NETLIB_CONSTRUCTOR(res_sw) , m_R(*this, "_R") , m_I(*this, "I") - , m_RON(*this, "RON", 1.0) - , m_ROFF(*this, "ROFF", 1.0E20) + , m_RON(*this, "RON", plib::constants::one()) + , m_ROFF(*this, "ROFF", plib::constants::cast(1.0E20)) , m_last_state(*this, "m_last_state", 0) { register_subalias("1", m_R.m_P); diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index f0b5735ff26..02a341f5b7f 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -40,14 +40,14 @@ namespace netlist public: logic_family_ttl_t() : logic_family_desc_t() { - m_fixed_V = 5.0; - m_low_thresh_PCNT = 0.8 / 5.0; - m_high_thresh_PCNT = 2.0 / 5.0; + m_fixed_V = plib::constants::cast(5.0); + m_low_thresh_PCNT = plib::constants::cast(0.8 / 5.0); + m_high_thresh_PCNT = plib::constants::cast(2.0 / 5.0); // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_VO = 0.1; - m_high_VO = 1.0; // 4.0 - m_R_low = 1.0; - m_R_high = 130.0; + m_low_VO = plib::constants::cast(0.1); + m_high_VO = plib::constants::cast(1.0); // 4.0 + m_R_low = plib::constants::cast(1.0); + m_R_high = plib::constants::cast(130.0); } unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; @@ -67,14 +67,14 @@ namespace netlist public: logic_family_cd4xxx_t() : logic_family_desc_t() { - m_fixed_V = 0.0; - m_low_thresh_PCNT = 1.5 / 5.0; - m_high_thresh_PCNT = 3.5 / 5.0; + m_fixed_V = plib::constants::cast(0.0); + m_low_thresh_PCNT = plib::constants::cast(1.5 / 5.0); + m_high_thresh_PCNT = plib::constants::cast(3.5 / 5.0); // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_VO = 0.05; - m_high_VO = 0.05; // 4.95 - m_R_low = 10.0; - m_R_high = 10.0; + m_low_VO = plib::constants::cast(0.05); + m_high_VO = plib::constants::cast(0.05); // 4.95 + m_R_low = plib::constants::cast(10.0); + m_R_high = plib::constants::cast(10.0); } unique_pool_ptr create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; unique_pool_ptr create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override; @@ -669,7 +669,7 @@ namespace netlist auto *p = dynamic_cast(this); if (p != nullptr) - p->m_cur_Analog = 0.0; + p->m_cur_Analog = plib::constants::zero(); /* rebuild m_list and reset terminals to active or analog out state */ @@ -727,7 +727,7 @@ namespace netlist analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr) : net_t(nl, aname, mr) - , m_cur_Analog(*this, "m_cur_Analog", 0.0) + , m_cur_Analog(*this, "m_cur_Analog", plib::constants::zero()) , m_solver(nullptr) { } diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index ca1e121536c..c1d42f22cb9 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -764,12 +764,12 @@ namespace netlist void set_conductivity(const nl_fptype G) noexcept { - set_go_gt_I(-G, G, 0.0); + set_go_gt_I(-G, G, plib::constants::zero()); } void set_go_gt(const nl_fptype GO, const nl_fptype GT) noexcept { - set_go_gt_I(GO, GT, 0.0); + set_go_gt_I(GO, GT, plib::constants::zero()); } void set_go_gt_I(const nl_fptype GO, const nl_fptype GT, const nl_fptype I) noexcept diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 1633efc523b..a0cbb687fec 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -128,6 +128,7 @@ namespace netlist static inline constexpr long double TIMESTEP_MINDIV() noexcept { return 1e-60L; } static inline constexpr const char * name() noexcept { return "long double"; } + static inline constexpr const char * suffix() noexcept { return "L"; } }; /*! Specific constants for double floating point type @@ -142,6 +143,7 @@ namespace netlist static inline constexpr double TIMESTEP_MINDIV() noexcept { return 1e-60; } static inline constexpr const char * name() noexcept { return "double"; } + static inline constexpr const char * suffix() noexcept { return ""; } }; /*! Specific constants for float floating point type @@ -156,6 +158,7 @@ namespace netlist static inline constexpr float TIMESTEP_MINDIV() noexcept { return 1e-8f; } static inline constexpr const char * name() noexcept { return "float"; } + static inline constexpr const char * suffix() noexcept { return "f"; } }; } // namespace netlist diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 27165d9d1f4..44c2a02ca0d 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -413,7 +413,15 @@ void parser_t::device(const pstring &dev_type) nl_fptype parser_t::eval_param(const token_t &tok) { static std::array macs = {"", "RES_R", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"}; - static std::array facs = {1, 1, 1e3, 1e6, 1e-6, 1e-9, 1e-12}; + static std::array facs = { + plib::constants::cast(1.0), + plib::constants::cast(1.0), + plib::constants::cast(1e3), + plib::constants::cast(1e6), + plib::constants::cast(1e-6), + plib::constants::cast(1e-9), + plib::constants::cast(1e-12) + }; std::size_t f=0; nl_fptype ret(0); @@ -423,7 +431,7 @@ nl_fptype parser_t::eval_param(const token_t &tok) if (f>0) { require_token(m_tok_param_left); - ret = get_number_double(); + ret = static_cast(get_number_double()); require_token(m_tok_param_right); } else diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index a9ff47959fa..e6008595e3f 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -119,9 +119,10 @@ namespace netlist m_namespace_stack.pop(); } - void nlparse_t::register_param(const pstring ¶m, const nl_fptype value) + void nlparse_t::register_param_x(const pstring ¶m, const nl_fptype value) { - if (std::abs(value - std::floor(value)) > 1e-30 || std::abs(value) > 1e9) + if (std::abs(value - std::floor(value)) > plib::constants::cast(1e-30) + || std::abs(value) > plib::constants::cast(1e9)) register_param(param, plib::pfmt("{1:.9}").e(value)); else register_param(param, plib::pfmt("{1}")(static_cast(value))); @@ -945,15 +946,15 @@ nl_fptype models_t::value(const pstring &model, const pstring &entity) auto p = std::next(tmp.begin(), static_cast(tmp.size() - 1)); switch (*p) { - case 'M': factor = 1e6; break; + case 'M': factor = plib::constants::cast(1e6); break; case 'k': - case 'K': factor = 1e3; break; - case 'm': factor = 1e-3; break; - case 'u': factor = 1e-6; break; - case 'n': factor = 1e-9; break; - case 'p': factor = 1e-12; break; - case 'f': factor = 1e-15; break; - case 'a': factor = 1e-18; break; + case 'K': factor = plib::constants::cast(1e3); break; + case 'm': factor = plib::constants::cast(1e-3); break; + case 'u': factor = plib::constants::cast(1e-6); break; + case 'n': factor = plib::constants::cast(1e-9); break; + case 'p': factor = plib::constants::cast(1e-12); break; + case 'f': factor = plib::constants::cast(1e-15); break; + case 'a': factor = plib::constants::cast(1e-18); break; default: if (*p < '0' || *p > '9') throw nl_exception(MF_UNKNOWN_NUMBER_FACTOR_IN_1(entity)); @@ -1125,9 +1126,10 @@ void setup_t::prepare_to_run() //FIXME: check for errors ... bool err(false); auto v = plib::pstonum_ne(p->second, err); - if (err || std::abs(v - std::floor(v)) > 1e-6 ) + if (err || std::abs(v - std::floor(v)) > plib::constants::cast(1e-6) ) log().fatal(MF_HND_VAL_NOT_SUPPORTED(p->second)); - d.second->set_hint_deactivate(v == 0.0); + // FIXME comparison with zero + d.second->set_hint_deactivate(v == plib::constants::zero()); } } else diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 180b437d293..7d34f66d91a 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -244,7 +244,16 @@ namespace netlist void register_link(const pstring &sin, const pstring &sout); void register_link_arr(const pstring &terms); void register_param(const pstring ¶m, const pstring &value); - void register_param(const pstring ¶m, const nl_fptype value); + + // FIXME: quick hack + void register_param_x(const pstring ¶m, const nl_fptype value); + template + typename std::enable_if::value || std::is_integral::value>::type + register_param(const pstring ¶m, T value) + { + register_param_x(param, static_cast(value)); + } + void register_lib_entry(const pstring &name, const pstring &sourcefile); void register_frontier(const pstring &attach, const nl_fptype r_IN, const nl_fptype r_OUT); diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h index 8eb2e64d358..21890099d3f 100644 --- a/src/lib/netlist/plib/pchrono.h +++ b/src/lib/netlist/plib/pchrono.h @@ -216,8 +216,9 @@ namespace plib { type total() const noexcept { return m_time; } ctype count() const noexcept { return m_count; } - double as_seconds() const noexcept { return static_cast(total()) - / static_cast(T::per_second()); } + template + S as_seconds() const noexcept { return static_cast(total()) + / static_cast(T::per_second()); } guard_t guard() noexcept { return guard_t(*this); } private: @@ -247,7 +248,8 @@ namespace plib { constexpr type average() const noexcept { return 0; } constexpr type total() const noexcept { return 0; } constexpr ctype count() const noexcept { return 0; } - constexpr double as_seconds() const noexcept { return 0.0; } + template + S as_seconds() const noexcept { return static_cast(0.0); } constexpr static bool enabled = false; guard_t guard() { return guard_t(); } }; diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp index 3a1c2962169..48939c8236a 100644 --- a/src/lib/netlist/plib/pfunction.cpp +++ b/src/lib/netlist/plib/pfunction.cpp @@ -195,9 +195,9 @@ namespace plib { template NT pfunction::evaluate(const std::vector &values) noexcept { - std::array stack = { 0 }; + std::array stack = { plib::constants::zero() }; unsigned ptr = 0; - stack[0] = 0.0; + stack[0] = plib::constants::zero(); for (auto &rc : m_precompiled) { switch (rc.m_cmd) @@ -226,5 +226,6 @@ namespace plib { template class pfunction; template class pfunction; + template class pfunction; } // namespace plib diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h index 3f9c7ddc861..d1f4d8c3da4 100644 --- a/src/lib/netlist/plib/pfunction.h +++ b/src/lib/netlist/plib/pfunction.h @@ -10,6 +10,7 @@ #include "pstate.h" #include "pstring.h" +#include "putil.h" #include @@ -42,7 +43,7 @@ namespace plib { }; struct rpn_inst { - rpn_inst() : m_cmd(ADD), m_param(0.0) { } + rpn_inst() : m_cmd(ADD), m_param(plib::constants::zero()) { } rpn_cmd m_cmd; NT m_param; }; @@ -116,6 +117,7 @@ namespace plib { extern template class pfunction; extern template class pfunction; + extern template class pfunction; } // namespace plib diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h index c0a6cd5a34b..f6972d9f41e 100644 --- a/src/lib/netlist/plib/ptime.h +++ b/src/lib/netlist/plib/ptime.h @@ -123,7 +123,7 @@ namespace plib template static constexpr const typename std::enable_if::value, ptime>::type - from_fp(const FT t) noexcept { return ptime(static_cast(std::floor(t * static_cast(RES) + 0.5)), RES); } + from_fp(const FT t) noexcept { return ptime(static_cast(std::floor(t * static_cast(RES) + static_cast(0.5))), RES); } static constexpr const ptime from_double(const double t) noexcept { return from_fp(t); } diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index ae358b960df..1fa3971f8a6 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -221,10 +221,13 @@ namespace plib struct constants { static inline constexpr T zero() noexcept { return static_cast(0); } + static inline constexpr T half() noexcept { return static_cast(0.5); } static inline constexpr T one() noexcept { return static_cast(1); } static inline constexpr T two() noexcept { return static_cast(2); } - static inline constexpr T sqrt2() noexcept { return static_cast(1.414213562373095048801688724209); } - static inline constexpr T pi() noexcept { return static_cast(3.14159265358979323846264338327950); } + static inline constexpr T three() noexcept { return static_cast(3); } + static inline constexpr T four() noexcept { return static_cast(4); } + static inline constexpr T sqrt2() noexcept { return static_cast(1.414213562373095048801688724209L); } + static inline constexpr T pi() noexcept { return static_cast(3.14159265358979323846264338327950L); } /*! * \brief Electric constant of vacuum diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 9ca4579ae4d..ffadd002cda 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -47,7 +47,7 @@ public: opt_dir(*this, "d", "dir", "", "output directory for the generated files"), opt_grp4(*this, "Options for run command", "These options are only used by the run command."), - opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)\n\n abc def\n\n xyz"), + opt_ttr (*this, "t", "time_to_run", 1, "time to run the emulation (seconds)\n\n abc def\n\n xyz"), opt_stats(*this, "s", "statistics", "gather runtime statistics"), opt_logs(*this, "l", "log" , "define terminal to log. This option may be specified repeatedly."), opt_inp(*this, "i", "input", "", "input file to process (default is none)"), @@ -311,7 +311,7 @@ void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls struct input_t { input_t(const netlist::setup_t &setup, const pstring &line) - : m_value(0.0) + : m_value(plib::constants::zero()) { std::array buf; // NOLINT(cppcoreguidelines-pro-type-member-init) double t(0); @@ -402,7 +402,7 @@ void tool_app_t::run() } - pout("startup time ==> {1:5.3f}\n", t.as_seconds() ); + pout("startup time ==> {1:5.3f}\n", t.as_seconds() ); t.reset(); @@ -462,10 +462,10 @@ void tool_app_t::run() nt.stop(); } - nl_fptype emutime = t.as_seconds(); + auto emutime(t.as_seconds()); pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n", - (ttr - nlt).as_double(), emutime, - (ttr - nlt).as_double() / emutime * 100.0); + (ttr - nlt).as_fp(), emutime, + (ttr - nlt).as_fp() / emutime * plib::constants::cast(100.0)); } void tool_app_t::validate() diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index a1bb4f2f88e..d7b77baf1b9 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -501,7 +501,7 @@ namespace solver std::vector touched(1024, false); // FIXME! - nl_fptype weight = 0.0; + nl_fptype weight = plib::constants::zero(); auto &term = m_terms[row]; for (std::size_t i = 0; i < term.count(); i++) { @@ -560,7 +560,7 @@ namespace solver this->m_stat_calculations, static_cast(this->m_stat_calculations) / this->exec().time().as_fp(), this->m_iterative_fail, - 100.0 * static_cast(this->m_iterative_fail) + plib::constants::cast(100.0) * static_cast(this->m_iterative_fail) / static_cast(this->m_stat_calculations), static_cast(this->m_iterative_total) / static_cast(this->m_stat_calculations)); } diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 341374b1df0..3a9c8386f69 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -49,26 +49,29 @@ namespace solver struct solver_parameters_t { solver_parameters_t(device_t &parent) - : m_freq(parent, "FREQ", 48000.0) + : m_freq(parent, "FREQ", plib::constants::cast(48000.0)) /* iteration parameters */ - , m_gs_sor(parent, "SOR_FACTOR", 1.059) - , m_method(parent, "METHOD", matrix_type_e::MAT_CR) - , m_fp_type(parent, "FPTYPE", matrix_fp_type_e::DOUBLE) - , m_accuracy(parent, "ACCURACY", 1e-7) - , m_gs_loops(parent, "GS_LOOPS", 9) // Gauss-Seidel loops + , m_gs_sor(parent, "SOR_FACTOR", plib::constants::cast(1.059)) + , m_method(parent, "METHOD", matrix_type_e::MAT_CR) + , m_fp_type(parent, "FPTYPE", matrix_fp_type_e::DOUBLE) + , m_reltol(parent, "RELTOL", plib::constants::cast(1e-3)) ///< SPICE RELTOL parameter + , m_vntol(parent, "VNTOL", plib::constants::cast(1e-6)) ///< SPICE VNTOL parameter + , m_accuracy(parent, "ACCURACY", plib::constants::cast(1e-7)) ///< Iterative solver accuracy + , m_nr_loops(parent, "NR_LOOPS", 250) ///< Maximum number of Newton-Raphson loops + , m_gs_loops(parent, "GS_LOOPS", 9) ///< Maximum number of Gauss-Seidel loops /* general parameters */ - , m_gmin(parent, "GMIN", 1e-9) - , m_pivot(parent, "PIVOT", false) // use pivoting - on supported solvers - , m_nr_loops(parent, "NR_LOOPS", 250) // Newton-Raphson loops - , m_nr_recalc_delay(parent, "NR_RECALC_DELAY", netlist_time::quantum().as_fp()) // Delay to next solve attempt if nr loops exceeded + , m_gmin(parent, "GMIN", plib::constants::cast(1e-9)) + , m_pivot(parent, "PIVOT", false) ///< use pivoting on supported solvers + , m_nr_recalc_delay(parent, "NR_RECALC_DELAY", + netlist_time::quantum().as_fp()) ///< Delay to next solve attempt if nr loops exceeded , m_parallel(parent, "PARALLEL", 0) /* automatic time step */ - , m_dynamic_ts(parent, "DYNAMIC_TS", false) - , m_dynamic_lte(parent, "DYNAMIC_LTE", 1e-5) // diff/timestep - , m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_fptype timestep resolution + , m_dynamic_ts(parent, "DYNAMIC_TS", false) ///< Use dynamic time stepping + , m_dynamic_lte(parent, "DYNAMIC_LTE", plib::constants::cast(1e-5)) ///< dynamic time stepping slope + , m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", plib::constants::cast(1e-6)) ///< smallest time step allowed /* matrix sorting */ , m_sort_type(parent, "SORT_TYPE", matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT) @@ -95,11 +98,13 @@ namespace solver param_fp_t m_gs_sor; param_enum_t m_method; param_enum_t m_fp_type; + param_fp_t m_reltol; + param_fp_t m_vntol; param_fp_t m_accuracy; + param_num_t m_nr_loops; param_num_t m_gs_loops; param_fp_t m_gmin; param_logic_t m_pivot; - param_num_t m_nr_loops; param_fp_t m_nr_recalc_delay; param_int_t m_parallel; param_logic_t m_dynamic_ts; @@ -229,31 +234,6 @@ namespace solver return max_rail; } - template - void store(const T & V) - { - const std::size_t iN = this->m_terms.size(); - for (std::size_t i = 0; i < iN; i++) - this->m_terms[i].setV(V[i]); - } - - - template - auto delta(const T & V) -> typename std::decay::type - { - /* NOTE: Ideally we should also include currents (RHS) here. This would - * need a reevaluation of the right hand side after voltages have been updated - * and thus belong into a different calculation. This applies to all solvers. - */ - - const std::size_t iN = this->m_terms.size(); - using vtype = typename std::decay::type; - vtype cerr = 0; - for (std::size_t i = 0; i < iN; i++) - cerr = std::max(cerr, std::abs(V[i] - this->m_terms[i].getV())); - return cerr; - } - void set_pointers() { const std::size_t iN = this->m_terms.size(); @@ -392,6 +372,8 @@ namespace solver const solver_parameters_t *params, const std::size_t size) : matrix_solver_t(anetlist, name, nets, params) , m_dim(size) + , m_new_V(size) + , m_RHS(size) , m_mat_ptr(size, this->max_railstart() + 1) , m_last_V(size, plib::constants::zero()) , m_DD_n_m_1(size, plib::constants::zero()) @@ -413,8 +395,15 @@ namespace solver static constexpr const std::size_t SIZEABS = plib::parray::SIZEABS(); static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8; + PALIGNAS_VECTOROPT() + plib::parray m_new_V; + PALIGNAS_VECTOROPT() + plib::parray m_RHS; + PALIGNAS_VECTOROPT() plib::parray2D m_mat_ptr; + + // FIXME: below should be private /* state - variable time_stepping */ PALIGNAS_VECTOROPT() plib::parray m_last_V; @@ -423,7 +412,38 @@ namespace solver PALIGNAS_VECTOROPT() plib::parray m_h_n_m_1; - constexpr std::size_t size() const noexcept { return (SIZE > 0) ? static_cast(SIZE) : m_dim; } + constexpr std::size_t size() const noexcept + { + return (SIZE > 0) ? static_cast(SIZE) : m_dim; + } + + void store() + { + const std::size_t iN = size(); + for (std::size_t i = 0; i < iN; i++) + this->m_terms[i].setV(m_new_V[i]); + } + + bool check_err() + { + /* NOTE: Ideally we should also include currents (RHS) here. This would + * need a reevaluation of the right hand side after voltages have been updated + * and thus belong into a different calculation. This applies to all solvers. + */ + + const std::size_t iN = size(); + const auto reltol(static_cast(m_params.m_reltol)); + const auto vntol(static_cast(m_params.m_vntol)); + for (std::size_t i = 0; i < iN; i++) + { + const auto vold(this->m_terms[i].template getV()); + const auto vnew(m_new_V[i]); + const auto tol(vntol + reltol * std::max(std::abs(vnew),std::abs(vold))); + if (std::abs(vnew - vold) > tol) + return true; + } + return false; + } netlist_time compute_next_timestep(const nl_fptype cur_ts) override { @@ -431,7 +451,7 @@ namespace solver if (m_params.m_dynamic_ts) { - for (std::size_t k = 0; k < m_terms.size(); k++) + for (std::size_t k = 0; k < size(); k++) { auto &t = m_terms[k]; //const nl_fptype DD_n = (n->Q_Analog() - t->m_last_V); @@ -507,8 +527,7 @@ namespace solver } } - template - void fill_matrix(RT &RHS) + void fill_matrix_and_rhs() { const std::size_t N = size(); @@ -549,7 +568,7 @@ namespace solver RHS_t += (/*m_Idr[i]*/ (- go[i]) * *cnV[i]); } - RHS[k] = static_cast(RHS_t); + m_RHS[k] = static_cast(RHS_t); // update diagonal element ... *tcr_r[railstart] += static_cast(gtot_t); //mat.A[mat.diag[k]] += gtot_t; } diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h index dc7aea3e743..20f9fa23964 100644 --- a/src/lib/netlist/solver/nld_ms_direct.h +++ b/src/lib/netlist/solver/nld_ms_direct.h @@ -51,12 +51,8 @@ namespace solver template void LE_back_subst(T & x); - PALIGNAS_VECTOROPT() - plib::parray m_new_V; PALIGNAS_VECTOROPT() plib::parray2D m_A; - PALIGNAS_VECTOROPT() - plib::parray m_RHS; }; // ---------------------------------------------------------------------------------------- @@ -81,7 +77,7 @@ namespace solver const FT f1 = -f * m_A[j][i]; for (auto &k : nzrd) m_A[j][k] += m_A[i][k] * f1; - m_RHS[j] += m_RHS[i] * f1; + this->m_RHS[j] += this->m_RHS[i] * f1; } } } @@ -93,8 +89,8 @@ namespace solver std::size_t maxrow = i; for (std::size_t j = i + 1; j < kN; j++) { - //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i])) - if (m_A[j][i] * m_A[j][i] > m_A[maxrow][i] * m_A[maxrow][i]) + if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i])) + //if (m_A[j][i] * m_A[j][i] > m_A[maxrow][i] * m_A[maxrow][i]) maxrow = j; } @@ -104,7 +100,7 @@ namespace solver for (std::size_t k = 0; k < kN; k++) { std::swap(m_A[i][k], m_A[maxrow][k]); } - std::swap(m_RHS[i], m_RHS[maxrow]); + std::swap(this->m_RHS[i], this->m_RHS[maxrow]); } /* FIXME: Singular matrix? */ const FT f = plib::reciprocal(m_A[i][i]); @@ -123,7 +119,7 @@ namespace solver // pj[k] = pj[k] + pi[k] * f1; //for (unsigned k = i+1; k < kN; k++) //A(j,k) += A(i,k) * f1; - m_RHS[j] += m_RHS[i] * f1; + this->m_RHS[j] += this->m_RHS[i] * f1; } } } @@ -145,7 +141,7 @@ namespace solver FT tmp = 0; for (std::size_t k = j+1; k < kN; k++) tmp += m_A[j][k] * x[k]; - x[j] = (m_RHS[j] - tmp) / m_A[j][j]; + x[j] = (this->m_RHS[j] - tmp) / m_A[j][j]; } } else @@ -157,7 +153,7 @@ namespace solver const auto e = nzrd.size(); // - 1; /* exclude RHS element */ for ( std::size_t k = 0; k < e; k++) tmp += m_A[j][nzrd[k]] * x[nzrd[k]]; - x[j] = (m_RHS[j] - tmp) / m_A[j][j]; + x[j] = (this->m_RHS[j] - tmp) / m_A[j][j]; } } } @@ -166,11 +162,13 @@ namespace solver unsigned matrix_solver_direct_t::solve_non_dynamic(const bool newton_raphson) { this->LE_solve(); - this->LE_back_subst(m_new_V); + this->LE_back_subst(this->m_new_V); - const FT err = (newton_raphson ? this->delta(m_new_V) : plib::constants::zero()); - this->store(m_new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template @@ -178,7 +176,7 @@ namespace solver { /* populate matrix */ this->clear_square_mat(m_A); - this->fill_matrix(m_RHS); + this->fill_matrix_and_rhs(); this->m_stat_calculations++; return this->solve_non_dynamic(newton_raphson); @@ -191,9 +189,7 @@ namespace solver const std::size_t size) : matrix_solver_ext_t(anetlist, name, nets, params, size) , m_pitch(m_pitch_ABS ? m_pitch_ABS : (((size + 0) + 7) / 8) * 8) - , m_new_V(size) , m_A(size, m_pitch) - , m_RHS(size) { this->build_mat_ptr(m_A); } diff --git a/src/lib/netlist/solver/nld_ms_direct1.h b/src/lib/netlist/solver/nld_ms_direct1.h index fa4d50677fb..3a04107103f 100644 --- a/src/lib/netlist/solver/nld_ms_direct1.h +++ b/src/lib/netlist/solver/nld_ms_direct1.h @@ -35,19 +35,19 @@ namespace solver unsigned vsolve_non_dynamic(const bool newton_raphson) override { this->clear_square_mat(this->m_A); - this->fill_matrix(this->m_RHS); + this->fill_matrix_and_rhs(); - std::array new_V = { this->m_RHS[0] / this->m_A[0][0] }; + this->m_new_V[0] = this->m_RHS[0] / this->m_A[0][0]; - const FT err = (newton_raphson ? this->delta(new_V) : plib::constants::zero()); - this->store(new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } - }; - } // namespace solver } // namespace netlist diff --git a/src/lib/netlist/solver/nld_ms_direct2.h b/src/lib/netlist/solver/nld_ms_direct2.h index a24ceb9ef71..26123730b59 100644 --- a/src/lib/netlist/solver/nld_ms_direct2.h +++ b/src/lib/netlist/solver/nld_ms_direct2.h @@ -35,7 +35,7 @@ namespace solver unsigned vsolve_non_dynamic(const bool newton_raphson) override { this->clear_square_mat(this->m_A); - this->fill_matrix(this->m_RHS); + this->fill_matrix_and_rhs(); const float_type a = this->m_A[0][0]; const float_type b = this->m_A[0][1]; @@ -44,12 +44,15 @@ namespace solver const float_type v1 = (a * this->m_RHS[1] - c * this->m_RHS[0]) / (a * d - b * c); const float_type v0 = (this->m_RHS[0] - b * v1) / a; - std::array new_V = {v0, v1}; + this->m_new_V[0] = v0; + this->m_new_V[1] = v1; this->m_stat_calculations++; - const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants::zero()); - this->store(new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } }; diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index d7f9716a5d7..5d4730ea3b1 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -36,8 +36,6 @@ namespace solver const analog_net_t::list_t &nets, const solver_parameters_t *params, const std::size_t size) : matrix_solver_ext_t(anetlist, name, nets, params, size) - , RHS(size) - , new_V(size) , mat(static_cast(size)) , m_proc() { @@ -120,9 +118,6 @@ namespace solver pstring static_compile_name(); - plib::parray RHS; - plib::parray new_V; - mat_type mat; plib::dynproc m_proc; @@ -137,9 +132,11 @@ namespace solver void matrix_solver_GCR_t::generate_code(plib::putf8_fmt_writer &strm) { const std::size_t iN = this->size(); + pstring fptype(fp_constants::name()); + pstring fpsuffix(fp_constants::suffix()); for (std::size_t i = 0; i < mat.nz_num; i++) - strm("double m_A{1} = m_A[{2}];\n", i, i); + strm("{1} m_A{2} = m_A[{3}];\n", fptype, i, i); for (std::size_t i = 0; i < iN - 1; i++) { @@ -150,7 +147,7 @@ namespace solver std::size_t pi = mat.diag[i]; //const FT f = 1.0 / m_A[pi++]; - strm("const double f{1} = 1.0 / m_A{2};\n", i, pi); + strm("const {1} f{2} = 1.0{3} / m_A{4};\n", fptype, i, fpsuffix, pi); pi++; const std::size_t piie = mat.row_idx[i+1]; @@ -164,7 +161,7 @@ namespace solver pj++; //const FT f1 = - m_A[pj++] * f; - strm("\tconst double f{1}_{2} = -f{3} * m_A{4};\n", i, j, i, pj); + strm("\tconst {1} f{2}_{3} = -f{4} * m_A{5};\n", fptype, i, j, i, pj); pj++; // subtract row i from j */ @@ -186,7 +183,7 @@ namespace solver strm("\tV[{1}] = RHS[{2}] / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]); for (std::size_t j = iN - 1; j-- > 0;) { - strm("\tdouble tmp{1} = 0.0;\n", j); + strm("\t{1} tmp{2} = 0.0{3};\n", fptype, j, fpsuffix); const std::size_t e = mat.row_idx[j+1]; for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++) { @@ -214,8 +211,9 @@ namespace solver t.imbue(std::locale::classic()); plib::putf8_fmt_writer strm(&t); pstring name = static_compile_name(); + pstring fptype(fp_constants::name()); - strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS, double * __restrict V)\n")(name)); + strm.writeline(plib::pfmt("extern \"C\" void {1}({2} * __restrict m_A, {2} * __restrict RHS, {2} * __restrict V)\n")(name, fptype)); strm.writeline("{\n"); generate_code(strm); strm.writeline("}\n"); @@ -228,28 +226,30 @@ namespace solver { /* populate matrix */ mat.set_scalar(plib::constants::zero()); - this->fill_matrix(RHS); + this->fill_matrix_and_rhs(); /* now solve it */ if (m_proc.resolved()) { - m_proc(&mat.A[0], &RHS[0], &new_V[0]); + m_proc(&mat.A[0], &this->m_RHS[0], &this->m_new_V[0]); } else { // parallel is slow -- very slow //mat.gaussian_elimination_parallel(RHS); - mat.gaussian_elimination(RHS); + mat.gaussian_elimination(this->m_RHS); /* backward substitution */ - mat.gaussian_back_substitution(new_V, RHS); + mat.gaussian_back_substitution(this->m_new_V, this->m_RHS); } this->m_stat_calculations++; - const FT err = (newton_raphson ? this->delta(new_V) : plib::constants::zero()); - this->store(new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } } // namespace solver diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index 6d9e7929fe3..abee33bb18a 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -101,12 +101,10 @@ namespace solver { const std::size_t iN = this->size(); - plib::parray RHS(iN); - m_ops.m_mat.set_scalar(plib::constants::zero()); /* populate matrix and V for first estimate */ - this->fill_matrix(RHS); + this->fill_matrix_and_rhs(); for (std::size_t k = 0; k < iN; k++) { @@ -116,7 +114,7 @@ namespace solver const float_type accuracy = static_cast(this->m_params.m_accuracy); auto iter = std::max(plib::constants::one(), this->m_params.m_gs_loops()); - auto gsl = m_gmres.solve(m_ops, this->m_new_V, RHS, iter, accuracy); + auto gsl = m_gmres.solve(m_ops, this->m_new_V, this->m_RHS, iter, accuracy); this->m_iterative_total += gsl; this->m_stat_calculations++; @@ -127,9 +125,11 @@ namespace solver return matrix_solver_direct_t::vsolve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants::zero()); - this->store(this->m_new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h index 679819a2627..0d62911bc3d 100644 --- a/src/lib/netlist/solver/nld_ms_sm.h +++ b/src/lib/netlist/solver/nld_ms_sm.h @@ -204,8 +204,6 @@ namespace solver static constexpr const bool incremental = true; const std::size_t iN = this->size(); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - std::array new_V; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array v; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) @@ -277,11 +275,13 @@ namespace solver m_cnt++; - this->LE_compute_x(new_V); + this->LE_compute_x(this->m_new_V); - const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants::zero()); - this->store(new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template @@ -289,7 +289,7 @@ namespace solver { this->clear_square_mat(this->m_A); - this->fill_matrix(this->m_RHS); + this->fill_matrix_and_rhs(); this->m_stat_calculations++; return this->solve_non_dynamic(newton_raphson); diff --git a/src/lib/netlist/solver/nld_ms_sor.h b/src/lib/netlist/solver/nld_ms_sor.h index 08d8a358a45..f2e8352279e 100644 --- a/src/lib/netlist/solver/nld_ms_sor.h +++ b/src/lib/netlist/solver/nld_ms_sor.h @@ -36,8 +36,6 @@ namespace solver , m_lp_fact(*this, "m_lp_fact", 0) , w(size, plib::constants::zero()) , one_m_w(size, plib::constants::zero()) - , RHS(size, plib::constants::zero()) - //, new_V(size, 0.0) { } @@ -47,8 +45,6 @@ namespace solver state_var m_lp_fact; std::vector w; std::vector one_m_w; - std::vector RHS; - //std::vector new_V; }; // ---------------------------------------------------------------------------------------- @@ -74,9 +70,9 @@ namespace solver for (std::size_t k = 0; k < iN; k++) { - nl_fptype gtot_t = 0.0; - nl_fptype gabs_t = 0.0; - nl_fptype RHS_t = 0.0; + nl_fptype gtot_t = plib::constants::zero(); + nl_fptype gabs_t = plib::constants::zero(); + nl_fptype RHS_t = plib::constants::zero(); const std::size_t term_count = this->m_terms[k].count(); const nl_fptype * const gt = this->m_gtn[k]; @@ -95,7 +91,7 @@ namespace solver for (std::size_t i = this->m_terms[k].railstart(); i < term_count; i++) RHS_t = RHS_t - go[i] * *other_cur_analog[i]; - RHS[k] = static_cast(RHS_t); + this->m_RHS[k] = static_cast(RHS_t); if (this->m_params.m_use_gabs) { @@ -136,7 +132,7 @@ namespace solver for (std::size_t i = 0; i < railstart; i++) Idrive = Idrive - static_cast(go[i]) * this->m_new_V[static_cast(net_other[i])]; - const float_type new_val = this->m_new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k]; + const float_type new_val = this->m_new_V[k] * one_m_w[k] + (Idrive + this->m_RHS[k]) * w[k]; err = std::max(std::abs(new_val - this->m_new_V[k]), err); this->m_new_V[k] = new_val; @@ -158,9 +154,11 @@ namespace solver return matrix_solver_direct_t::vsolve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants::zero()); - this->store(this->m_new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } } // namespace solver diff --git a/src/lib/netlist/solver/nld_ms_sor_mat.h b/src/lib/netlist/solver/nld_ms_sor_mat.h index da862e182ec..e411b1f1e59 100644 --- a/src/lib/netlist/solver/nld_ms_sor_mat.h +++ b/src/lib/netlist/solver/nld_ms_sor_mat.h @@ -117,7 +117,7 @@ namespace solver const std::size_t iN = this->size(); this->clear_square_mat(this->m_A); - this->fill_matrix(this->m_RHS); + this->fill_matrix_and_rhs(); bool resched = false; @@ -210,10 +210,11 @@ namespace solver return matrix_solver_direct_t::solve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants::zero()); - this->store(this->m_new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; - + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } } // namespace solver diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h index b89edd70b74..b0c148bf252 100644 --- a/src/lib/netlist/solver/nld_ms_w.h +++ b/src/lib/netlist/solver/nld_ms_w.h @@ -213,8 +213,6 @@ namespace solver { const auto iN = this->size(); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - std::array new_V; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array t; // FIXME: convert to member // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) @@ -224,12 +222,12 @@ namespace solver { /* complete calculation */ this->LE_invert(); - this->LE_compute_x(new_V); + this->LE_compute_x(this->m_new_V); } else { /* Solve Ay = b for y */ - this->LE_compute_x(new_V); + this->LE_compute_x(this->m_new_V); /* determine changed rows */ @@ -261,7 +259,7 @@ namespace solver const unsigned r = rows[i]; FT tmp = plib::constants::zero(); for (unsigned k = 0; k < iN; k++) - tmp += VT(r,k) * new_V[k]; + tmp += VT(r,k) * this->m_new_V[k]; w[i] = tmp; } @@ -328,7 +326,7 @@ namespace solver const unsigned row = rows[j]; tmp += Ainv(i,row) * t[j]; } - new_V[i] -= tmp; + this->m_new_V[i] -= tmp; } } } @@ -340,22 +338,24 @@ namespace solver float_type tmp = plib::constants::zero(); for (unsigned j=0; jm_new_V[j]; } if (std::abs(tmp-RHS(i)) > static_cast(1e-6)) plib::perrlogger("{} failed on row {}: {} RHS: {}\n", this->name(), i, std::abs(tmp-RHS(i)), RHS(i)); } - const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants::zero()); - this->store(new_V); - return (err > static_cast(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template unsigned matrix_solver_w_t::vsolve_non_dynamic(const bool newton_raphson) { this->clear_square_mat(this->m_A); - this->fill_matrix(this->m_RHS); + this->fill_matrix_and_rhs(); this->m_stat_calculations++; return this->solve_non_dynamic(newton_raphson); -- cgit v1.2.3