diff options
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<nl_fptype>::cast(1e-15)) + , m_VT(plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1e-9)) + , m_gC(plib::constants<nl_fptype>::cast(1e-9)) + , m_V(plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::one() + BF); + m_alpha_r = BR / (plib::constants<nl_fptype>::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<nl_fptype>::zero()) + , m_c(dev, name + ".m_c", plib::constants<nl_fptype>::zero()) + , m_v(dev, name + ".m_v", plib::constants<nl_fptype>::zero()) + , m_gmin(plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) + , m_v(dev, name + ".m_v", plib::constants<nl_fptype>::zero()) + , m_gmin(plib::constants<nl_fptype>::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<nl_fptype>::cast(0.7)) + , m_Id(dev, name + ".m_Id", plib::constants<nl_fptype>::zero()) + , m_G(dev, name + ".m_G", plib::constants<nl_fptype>::cast(1e-15)) + , m_Vt(plib::constants<nl_fptype>::zero()) + , m_Vmin(plib::constants<nl_fptype>::zero()) // not used in MOS model + , m_Is(plib::constants<nl_fptype>::zero()) + , m_logIs(plib::constants<nl_fptype>::zero()) + , m_n(plib::constants<nl_fptype>::zero()) + , m_gmin(plib::constants<nl_fptype>::cast(1e-15)) + , m_VtInv(plib::constants<nl_fptype>::zero()) + , m_Vcrit(plib::constants<nl_fptype>::zero()) , m_name(name) { - set_param(1e-15, 1, 1e-15, 300.0); + set_param( + plib::constants<nl_fptype>::cast(1e-15) + , plib::constants<nl_fptype>::cast(1) + , plib::constants<nl_fptype>::cast(1e-15) + , plib::constants<nl_fptype>::cast(300.0)); } void update_diode(const nl_fptype nVd) { - nl_fptype IseVDVt(0.0); + nl_fptype IseVDVt(plib::constants<nl_fptype>::zero()); if (TYPE == diode_e::BIPOLAR) { @@ -160,7 +164,7 @@ namespace analog { const nl_fptype d = std::min(+fp_constants<nl_fptype>::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<nl_fptype>::cast(d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt; } else m_Vd = std::max(-fp_constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) + , m_gamma(plib::constants<nl_fptype>::zero()) + , m_vto(plib::constants<nl_fptype>::zero()) + , m_beta(plib::constants<nl_fptype>::zero()) + , m_lambda(plib::constants<nl_fptype>::zero()) + , m_Leff(plib::constants<nl_fptype>::zero()) + , m_CoxWL(plib::constants<nl_fptype>::zero()) + , m_polarity(plib::constants<nl_fptype>::cast(qtype() == FET_NMOS ? 1.0 : -1.0)) + , m_Cgb(plib::constants<nl_fptype>::zero()) + , m_Cgs(plib::constants<nl_fptype>::zero()) + , m_Cgd(plib::constants<nl_fptype>::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<nl_fptype>::zero()) + , m_Vgd(*this, "m_Vgd", plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : plib::constants<nl_fptype>::zero(); // calculate DC transconductance coefficient - if (m_model.m_KP > 0) + if (m_model.m_KP > plib::constants<nl_fptype>::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<nl_fptype>::zero() && m_model.m_UO > plib::constants<nl_fptype>::zero()) + m_beta = m_model.m_UO * plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) m_phi = m_model.m_PHI; - else if (m_model.m_NSUB > 0.0) + else if (m_model.m_NSUB > plib::constants<nl_fptype>::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<nl_fptype>::cast(1e6) >= constants::NiSi(), "Error calculating phi for model " + m_model.name()); + m_phi = plib::constants<nl_fptype>::two() * Vt * std::log (m_model.m_NSUB * plib::constants<nl_fptype>::cast(1e6) / constants::NiSi()); } else - m_phi = 0.6; + m_phi = plib::constants<nl_fptype>::cast(0.6); // calculate bulk threshold if not given - if (m_model.m_GAMMA > 0.0) + if (m_model.m_GAMMA > plib::constants<nl_fptype>::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<nl_fptype>::zero() && m_model.m_NSUB > plib::constants<nl_fptype>::zero()) + m_gamma = std::sqrt (plib::constants<nl_fptype>::two() + * constants::Q_e() * constants::eps_Si() * constants::eps_0() + * m_model.m_NSUB * plib::constants<nl_fptype>::cast(1e6)) / Cox; else - m_gamma = 0.0; + m_gamma = plib::constants<nl_fptype>::zero(); } m_vto = m_model.m_VTO; - if(m_vto != 0.0) + // FIXME zero conversion + if(m_vto != plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero(); + Cgd = plib::constants<nl_fptype>::zero(); } - else if (Vctrl <= -m_phi / 2.0) + else if (Vctrl <= -m_phi / plib::constants<nl_fptype>::two()) { Cgb = -Vctrl * m_CoxWL / m_phi; - Cgs = 0.0; - Cgd = 0.0; + Cgs = plib::constants<nl_fptype>::zero(); + Cgd = plib::constants<nl_fptype>::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<nl_fptype>::cast(4.0 / 3.0) / m_phi + plib::constants<nl_fptype>::cast(2.0 / 3.0) * m_CoxWL; + Cgd = plib::constants<nl_fptype>::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<nl_fptype>::zero(); + Cgs = plib::constants<nl_fptype>::cast(2.0 / 3.0) * m_CoxWL; + Cgd = plib::constants<nl_fptype>::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<nl_fptype>(std::pow(Vdsat - Vds, 2)); + const nl_fptype Sqr2 = static_cast<nl_fptype>(std::pow(plib::constants<nl_fptype>::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<nl_fptype>::one() - Sqr1 / Sqr2) * plib::constants<nl_fptype>::cast(2.0 / 3.0); + Cgd = m_CoxWL * (plib::constants<nl_fptype>::one() - Vdsat * Vdsat / Sqr2) * plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) { // cutoff region - Ids = 0.0; - gm = 0.0; - gds = 0.0; - gmb = 0.0; + Ids = plib::constants<nl_fptype>::zero(); + gm = plib::constants<nl_fptype>::zero(); + gds = plib::constants<nl_fptype>::zero(); + gmb = plib::constants<nl_fptype>::zero(); } else { - const nl_fptype beta = m_beta * (1.0 + m_lambda * absVds); + const nl_fptype beta = m_beta * (plib::constants<nl_fptype>::one() + m_lambda * absVds); if (Vctrl <= absVds) { // saturation region - Ids = beta * Vctrl * Vctrl / 2.0; + Ids = beta * Vctrl * Vctrl / plib::constants<nl_fptype>::two(); gm = beta * Vctrl; - gds = m_lambda * m_beta * Vctrl * Vctrl / 2.0; + gds = m_lambda * m_beta * Vctrl * Vctrl / plib::constants<nl_fptype>::two(); } else { // linear region - Ids = beta * absVds * (Vctrl - absVds / 2); + Ids = beta * absVds * (Vctrl - absVds / plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) ? (m_gamma / phi_m_Vbulk / plib::constants<nl_fptype>::two()) : plib::constants<nl_fptype>::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<nl_fptype>::zero(); + const nl_fptype gbs = plib::constants<nl_fptype>::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<nl_fptype>::zero(); + const nl_fptype gdrain = is_forward ? plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero(); + nl_fptype gGD = plib::constants<nl_fptype>::zero(); + nl_fptype gGS = plib::constants<nl_fptype>::zero(); + nl_fptype gGB = plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1e-15) + plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::four() * constants::pi() * plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>(res)) -#define RES_K(res) (static_cast<nl_fptype>(res) * 1e3) -#define RES_M(res) (static_cast<nl_fptype>(res) * 1e6) -#define CAP_U(cap) (static_cast<nl_fptype>(cap) * 1e-6) -#define CAP_N(cap) (static_cast<nl_fptype>(cap) * 1e-9) -#define CAP_P(cap) (static_cast<nl_fptype>(cap) * 1e-12) -#define IND_U(ind) (static_cast<nl_fptype>(ind) * 1e-6) -#define IND_N(ind) (static_cast<nl_fptype>(ind) * 1e-9) -#define IND_P(ind) (static_cast<nl_fptype>(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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::one() - X*X); const nl_fptype I = m_cur_limit() * X - beta * m_vi; m_OP.set_go_gt_I(-beta, plib::constants<nl_fptype>::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<nl_fptype>::one()) + , m_RI(*this, "RI", plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1000.0)) + , m_vi(plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one()); m_R1.set_R(std::max(m_R() * v, exec().gmin())); m_R2.set_R(std::max(m_R() * (plib::constants<nl_fptype>::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<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants<nl_fptype>::one() - v; m_R1.set_R(std::max(m_R() * v, exec().gmin())); m_R2.set_R(std::max(m_R() * (plib::constants<nl_fptype>::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<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants<nl_fptype>::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<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one()); if (m_Reverse()) - v = 1.0 - v; + v = plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::one() / R; - set_mat( G, -G, 0.0, - -G, G, 0.0); + set_mat( G, -G, plib::constants<nl_fptype>::zero(), + -G, G, plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(10000.0)) + , m_Dial(*this, "DIAL", plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1e-6)) + , m_gmin(plib::constants<nl_fptype>::zero()) + , m_G(plib::constants<nl_fptype>::zero()) + , m_I(plib::constants<nl_fptype>::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<nl_fptype>::zero()) + , m_R(*this, "R", plib::constants<nl_fptype>::cast(0.1)) + , m_V(*this, "V", plib::constants<nl_fptype>::zero()) , m_func(*this,"FUNC", "") , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_funcparam({plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) + , m_I(*this, "I", plib::constants<nl_fptype>::one()) , m_func(*this,"FUNC", "") , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_funcparam({plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(270.0)) { } @@ -52,7 +52,7 @@ namespace netlist nl_fptype high = plib::constants<nl_fptype>::cast(0.55) * sup; nl_fptype in = m_control() - m_supply.GND(); nl_fptype rON = m_base_r() * plib::constants<nl_fptype>::cast(5.0) / sup; - nl_fptype R = -1.0; + nl_fptype R = -plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast((m_dev_type == 4538) ? 1.0 : 0.4)) // CD4538 datasheet states PW=RC + , m_RI(*this, "RI", plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(90000.0)); + m_R_RNG.set_R(plib::constants<nl_fptype>::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<nl_fptype>::cast( 1.9904769024796283E+03); + const nl_fptype k2 = plib::constants<nl_fptype>::cast( 1.2070059213983407E+03); + const nl_fptype k3 = plib::constants<nl_fptype>::cast( 1.3266985579561108E+03); + const nl_fptype k4 = plib::constants<nl_fptype>::cast(-1.5500979825922698E+02); + const nl_fptype k5 = plib::constants<nl_fptype>::cast( 2.8184536266938172E+00); + const nl_fptype k6 = plib::constants<nl_fptype>::cast(-2.3503421582744556E+02); + const nl_fptype k7 = plib::constants<nl_fptype>::cast(-3.3836786704527788E+02); + const nl_fptype k8 = plib::constants<nl_fptype>::cast(-1.3569136703258670E+02); + const nl_fptype k9 = plib::constants<nl_fptype>::cast( 2.9914575453819188E+00); + const nl_fptype k10 = plib::constants<nl_fptype>::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<nl_fptype>(0.5 / freq); + m_clock.m_inc = netlist_time::from_fp(plib::constants<nl_fptype>::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<nl_fptype>::one() / R_LOW, 0.0, 0.0); + m_RV.set_G_V_I(plib::constants<nl_fptype>::one() / plib::constants<nl_fptype>::cast(R_LOW), + plib::constants<nl_fptype>::zero(), + plib::constants<nl_fptype>::zero()); m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); - if (m_FREQ() < 24000 || m_FREQ() > 56000) + if (m_FREQ() < plib::constants<nl_fptype>::cast(24000) || m_FREQ() > plib::constants<nl_fptype>::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<nl_fptype>::cast(24000) || m_FREQ() > plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(5000)); + m_R2.set_R(plib::constants<nl_fptype>::cast(5000)); + m_R3.set_R(plib::constants<nl_fptype>::cast(5000)); + m_ROUT.set_R(plib::constants<nl_fptype>::cast(20)); + m_RDIS.set_R(plib::constants<nl_fptype>::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<nl_fptype>::cast(0.7), plib::constants<nl_fptype>::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<nl_fptype>::cast(0.7), plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::one()) + , m_R(*this, "R", plib::constants<nl_fptype>::one()) , m_num(*this, "N", 1) , m_val(*this, "VAL", 1) { @@ -44,7 +44,7 @@ namespace netlist nl_fptype V = m_VIN() / static_cast<nl_fptype>(1 << m_num()) * static_cast<nl_fptype>(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<nl_fptype>::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<nl_fptype>::one() / m_model.m_RI, m_model.m_VI, 0.0); - m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, 0.0); + m_RVI.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_RI, m_model.m_VI, plib::constants<nl_fptype>::zero()); + m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, plib::constants<nl_fptype>::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<nl_fptype>::one() / m_model.m_ROH, m_model.m_VOH, 0.0); + m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROH, m_model.m_VOH, plib::constants<nl_fptype>::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<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, 0.0); + m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, plib::constants<nl_fptype>::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<nl_fptype>::zero()) supply_V = plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::zero()) + supply_V = plib::constants<nl_fptype>::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<nl_fptype>::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); + logic_family()->low_offset_V(), plib::constants<nl_fptype>::zero()); m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); + plib::constants<nl_fptype>::zero(), + plib::constants<nl_fptype>::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<nl_fptype>::zero(), + plib::constants<nl_fptype>::zero()); m_RP.set_G_V_I(plib::constants<nl_fptype>::one() / logic_family()->R_high(), - logic_family()->high_offset_V(), 0.0); + logic_family()->high_offset_V(), plib::constants<nl_fptype>::zero()); } else { m_RN.set_G_V_I(plib::constants<nl_fptype>::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); + logic_family()->low_offset_V(), plib::constants<nl_fptype>::zero()); m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); + plib::constants<nl_fptype>::zero(), + plib::constants<nl_fptype>::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<nl_fptype>::cast(1e-9); plib::unique_ptr<analog_output_t> m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd plib::unique_ptr<analog_output_t> 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<nl_fptype>::cast(7159000.0 * 5)) { - m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two())); } NETLIB_RESETI() @@ -64,7 +64,7 @@ namespace devices NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::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<nl_fptype>::cast(7159000.0 * 5.0)) { - m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two())); connect(m_feedback, m_Q); } @@ -101,7 +101,7 @@ namespace devices NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq() * 2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::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<nl_fptype>::zero()}) { if (m_func() != "") m_compiled.compile(std::vector<pstring>({{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<nl_fptype>::cast(7159000.0 * 5.0)) , m_pattern(*this, "PATTERN", "1,1") - , m_offset(*this, "OFFSET", 0.0) + , m_offset(*this, "OFFSET", plib::constants<nl_fptype>::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<decltype(m_freq())>(1.0 / (m_freq() * 2.0)); + m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two())); connect(m_feedback, m_Q); - netlist_time base = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0)); + netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two())); std::vector<pstring> 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<nl_fptype>::zero()) { } NETLIB_UPDATEI() { } - NETLIB_RESETI() { m_Q.initial(0.0); } + NETLIB_RESETI() { m_Q.initial(plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1.0e6)) + , m_p_ROUT(*this, "ROUT", plib::constants<nl_fptype>::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<analog_input_t>(*this, n)); inps.push_back(n); - m_vals.push_back(0.0); + m_vals.push_back(plib::constants<nl_fptype>::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<nl_fptype>::one()) + , m_ROFF(*this, "ROFF", plib::constants<nl_fptype>::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<nl_fptype>::cast(5.0); + m_low_thresh_PCNT = plib::constants<nl_fptype>::cast(0.8 / 5.0); + m_high_thresh_PCNT = plib::constants<nl_fptype>::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<nl_fptype>::cast(0.1); + m_high_VO = plib::constants<nl_fptype>::cast(1.0); // 4.0 + m_R_low = plib::constants<nl_fptype>::cast(1.0); + m_R_high = plib::constants<nl_fptype>::cast(130.0); } unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; unique_pool_ptr<devices::nld_base_a_to_d_proxy> 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<nl_fptype>::cast(0.0); + m_low_thresh_PCNT = plib::constants<nl_fptype>::cast(1.5 / 5.0); + m_high_thresh_PCNT = plib::constants<nl_fptype>::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<nl_fptype>::cast(0.05); + m_high_VO = plib::constants<nl_fptype>::cast(0.05); // 4.95 + m_R_low = plib::constants<nl_fptype>::cast(10.0); + m_R_high = plib::constants<nl_fptype>::cast(10.0); } unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override; unique_pool_ptr<devices::nld_base_a_to_d_proxy> 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<analog_net_t *>(this); if (p != nullptr) - p->m_cur_Analog = 0.0; + p->m_cur_Analog = plib::constants<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::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<pstring, 7> macs = {"", "RES_R", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"}; - static std::array<nl_fptype, 7> facs = {1, 1, 1e3, 1e6, 1e-6, 1e-9, 1e-12}; + static std::array<nl_fptype, 7> facs = { + plib::constants<nl_fptype>::cast(1.0), + plib::constants<nl_fptype>::cast(1.0), + plib::constants<nl_fptype>::cast(1e3), + plib::constants<nl_fptype>::cast(1e6), + plib::constants<nl_fptype>::cast(1e-6), + plib::constants<nl_fptype>::cast(1e-9), + plib::constants<nl_fptype>::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<nl_fptype>(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<nl_fptype>::cast(1e-30) + || std::abs(value) > plib::constants<nl_fptype>::cast(1e9)) register_param(param, plib::pfmt("{1:.9}").e(value)); else register_param(param, plib::pfmt("{1}")(static_cast<long>(value))); @@ -945,15 +946,15 @@ nl_fptype models_t::value(const pstring &model, const pstring &entity) auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1)); switch (*p) { - case 'M': factor = 1e6; break; + case 'M': factor = plib::constants<nl_fptype>::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<nl_fptype>::cast(1e3); break; + case 'm': factor = plib::constants<nl_fptype>::cast(1e-3); break; + case 'u': factor = plib::constants<nl_fptype>::cast(1e-6); break; + case 'n': factor = plib::constants<nl_fptype>::cast(1e-9); break; + case 'p': factor = plib::constants<nl_fptype>::cast(1e-12); break; + case 'f': factor = plib::constants<nl_fptype>::cast(1e-15); break; + case 'a': factor = plib::constants<nl_fptype>::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<nl_fptype>(p->second, err); - if (err || std::abs(v - std::floor(v)) > 1e-6 ) + if (err || std::abs(v - std::floor(v)) > plib::constants<nl_fptype>::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<nl_fptype>::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 T> + typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value>::type + register_param(const pstring ¶m, T value) + { + register_param_x(param, static_cast<nl_fptype>(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<double>(total()) - / static_cast<double>(T::per_second()); } + template <typename S> + S as_seconds() const noexcept { return static_cast<S>(total()) + / static_cast<S>(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 <typename S> + S as_seconds() const noexcept { return static_cast<S>(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 <typename NT> NT pfunction<NT>::evaluate(const std::vector<NT> &values) noexcept { - std::array<NT, 20> stack = { 0 }; + std::array<NT, 20> stack = { plib::constants<NT>::zero() }; unsigned ptr = 0; - stack[0] = 0.0; + stack[0] = plib::constants<NT>::zero(); for (auto &rc : m_precompiled) { switch (rc.m_cmd) @@ -226,5 +226,6 @@ namespace plib { template class pfunction<float>; template class pfunction<double>; + template class pfunction<long double>; } // 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 <vector> @@ -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<NT>::zero()) { } rpn_cmd m_cmd; NT m_param; }; @@ -116,6 +117,7 @@ namespace plib { extern template class pfunction<float>; extern template class pfunction<double>; + extern template class pfunction<long double>; } // 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 <typename FT> static constexpr const typename std::enable_if<std::is_floating_point<FT>::value, ptime>::type - from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(std::floor(t * static_cast<FT>(RES) + 0.5)), RES); } + from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(std::floor(t * static_cast<FT>(RES) + static_cast<FT>(0.5))), RES); } static constexpr const ptime from_double(const double t) noexcept { return from_fp<double>(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<T>(0); } + static inline constexpr T half() noexcept { return static_cast<T>(0.5); } static inline constexpr T one() noexcept { return static_cast<T>(1); } static inline constexpr T two() noexcept { return static_cast<T>(2); } - static inline constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209); } - static inline constexpr T pi() noexcept { return static_cast<T>(3.14159265358979323846264338327950); } + static inline constexpr T three() noexcept { return static_cast<T>(3); } + static inline constexpr T four() noexcept { return static_cast<T>(4); } + static inline constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209L); } + static inline constexpr T pi() noexcept { return static_cast<T>(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<nl_fptype>::zero()) { std::array<char, 400> 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<nl_fptype>() ); t.reset(); @@ -462,10 +462,10 @@ void tool_app_t::run() nt.stop(); } - nl_fptype emutime = t.as_seconds(); + auto emutime(t.as_seconds<nl_fptype>()); 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<nl_fptype>(), emutime, + (ttr - nlt).as_fp<nl_fptype>() / emutime * plib::constants<nl_fptype>::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<bool> touched(1024, false); // FIXME! - nl_fptype weight = 0.0; + nl_fptype weight = plib::constants<nl_fptype>::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<nl_fptype>(this->m_stat_calculations) / this->exec().time().as_fp<nl_fptype>(), this->m_iterative_fail, - 100.0 * static_cast<nl_fptype>(this->m_iterative_fail) + plib::constants<nl_fptype>::cast(100.0) * static_cast<nl_fptype>(this->m_iterative_fail) / static_cast<nl_fptype>(this->m_stat_calculations), static_cast<nl_fptype>(this->m_iterative_total) / static_cast<nl_fptype>(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<nl_fptype>::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<nl_fptype>::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<nl_fptype>::cast(1e-3)) ///< SPICE RELTOL parameter + , m_vntol(parent, "VNTOL", plib::constants<nl_fptype>::cast(1e-6)) ///< SPICE VNTOL parameter + , m_accuracy(parent, "ACCURACY", plib::constants<nl_fptype>::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<nl_fptype>()) // Delay to next solve attempt if nr loops exceeded + , m_gmin(parent, "GMIN", plib::constants<nl_fptype>::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<nl_fptype>()) ///< 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<nl_fptype>::cast(1e-5)) ///< dynamic time stepping slope + , m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", plib::constants<nl_fptype>::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<matrix_type_e> m_method; param_enum_t<matrix_fp_type_e> m_fp_type; + param_fp_t m_reltol; + param_fp_t m_vntol; param_fp_t m_accuracy; + param_num_t<std::size_t> m_nr_loops; param_num_t<std::size_t> m_gs_loops; param_fp_t m_gmin; param_logic_t m_pivot; - param_num_t<std::size_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 <typename T> - 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 <typename T> - auto delta(const T & V) -> typename std::decay<decltype(V[0])>::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<decltype(V[0])>::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<vtype>())); - 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<nl_fptype>::zero()) , m_DD_n_m_1(size, plib::constants<nl_fptype>::zero()) @@ -414,7 +396,14 @@ namespace solver static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8; PALIGNAS_VECTOROPT() + plib::parray<FT, SIZE> m_new_V; + PALIGNAS_VECTOROPT() + plib::parray<FT, SIZE> m_RHS; + + PALIGNAS_VECTOROPT() plib::parray2D<float_type *, SIZE, 0> m_mat_ptr; + + // FIXME: below should be private /* state - variable time_stepping */ PALIGNAS_VECTOROPT() plib::parray<nl_fptype, SIZE> m_last_V; @@ -423,7 +412,38 @@ namespace solver PALIGNAS_VECTOROPT() plib::parray<nl_fptype, SIZE> m_h_n_m_1; - constexpr std::size_t size() const noexcept { return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; } + constexpr std::size_t size() const noexcept + { + return (SIZE > 0) ? static_cast<std::size_t>(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<FT>(m_params.m_reltol)); + const auto vntol(static_cast<FT>(m_params.m_vntol)); + for (std::size_t i = 0; i < iN; i++) + { + const auto vold(this->m_terms[i].template getV<FT>()); + 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 <typename RT> - 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<FT>(RHS_t); + m_RHS[k] = static_cast<FT>(RHS_t); // update diagonal element ... *tcr_r[railstart] += static_cast<FT>(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 @@ -52,11 +52,7 @@ namespace solver void LE_back_subst(T & x); PALIGNAS_VECTOROPT() - plib::parray<FT, SIZE> m_new_V; - PALIGNAS_VECTOROPT() plib::parray2D<FT, SIZE, m_pitch_ABS> m_A; - PALIGNAS_VECTOROPT() - plib::parray<FT, SIZE> 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<FT, SIZE>::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<FT>::zero()); - this->store(m_new_V); - return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template <typename FT, int SIZE> @@ -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<FT, SIZE>(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<FT, 1> 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<FT>::zero()); - this->store(new_V); - return (err > static_cast<FT>(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<float_type, 2> 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<FT>::zero()); - this->store(new_V); - return (err > static_cast<float_type>(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<FT, SIZE>(anetlist, name, nets, params, size) - , RHS(size) - , new_V(size) , mat(static_cast<typename mat_type::index_type>(size)) , m_proc() { @@ -120,9 +118,6 @@ namespace solver pstring static_compile_name(); - plib::parray<FT, SIZE> RHS; - plib::parray<FT, SIZE> new_V; - mat_type mat; plib::dynproc<void, FT * , FT * , FT * > m_proc; @@ -137,9 +132,11 @@ namespace solver void matrix_solver_GCR_t<FT, SIZE>::generate_code(plib::putf8_fmt_writer &strm) { const std::size_t iN = this->size(); + pstring fptype(fp_constants<FT>::name()); + pstring fpsuffix(fp_constants<FT>::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<FT>::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<FT>::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<FT>::zero()); - this->store(new_V); - return (err > static_cast<FT>(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<FT, SIZE> RHS(iN); - m_ops.m_mat.set_scalar(plib::constants<FT>::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<float_type>(this->m_params.m_accuracy); auto iter = std::max(plib::constants<std::size_t>::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<FT, SIZE>::vsolve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero()); - this->store(this->m_new_V); - return (err > static_cast<float_type>(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 @@ -205,8 +205,6 @@ namespace solver const std::size_t iN = this->size(); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - std::array<float_type, storage_N> new_V; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array<float_type, m_pitch> v; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array<std::size_t, m_pitch> cols; @@ -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<FT>::zero()); - this->store(new_V); - return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template <typename FT, int SIZE> @@ -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<FT>::zero()) , one_m_w(size, plib::constants<FT>::zero()) - , RHS(size, plib::constants<FT>::zero()) - //, new_V(size, 0.0) { } @@ -47,8 +45,6 @@ namespace solver state_var<float_type> m_lp_fact; std::vector<float_type> w; std::vector<float_type> one_m_w; - std::vector<float_type> RHS; - //std::vector<float_type> 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<nl_fptype>::zero(); + nl_fptype gabs_t = plib::constants<nl_fptype>::zero(); + nl_fptype RHS_t = plib::constants<nl_fptype>::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<float_type>(RHS_t); + this->m_RHS[k] = static_cast<float_type>(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<float_type>(go[i]) * this->m_new_V[static_cast<std::size_t>(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<FT, SIZE>::vsolve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero()); - this->store(this->m_new_V); - return (err > static_cast<float_type>(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<FT, SIZE>::solve_non_dynamic(newton_raphson); } - const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero()); - this->store(this->m_new_V); - return (err > static_cast<float_type>(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 @@ -214,8 +214,6 @@ namespace solver const auto iN = this->size(); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - std::array<float_type, storage_N> new_V; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array<float_type, storage_N> t; // FIXME: convert to member // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) std::array<float_type, storage_N> w; @@ -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<FT>::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<FT>::zero(); for (unsigned j=0; j<iN; j++) { - tmp += A(i,j) * new_V[j]; + tmp += A(i,j) * this->m_new_V[j]; } if (std::abs(tmp-RHS(i)) > static_cast<float_type>(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<FT>::zero()); - this->store(new_V); - return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1; + bool err(false); + if (newton_raphson) + err = this->check_err(); + this->store(); + return (err) ? 2 : 1; } template <typename FT, int SIZE> unsigned matrix_solver_w_t<FT, SIZE>::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); |