From e4ff0d3322b1da0c747fd98d3100e4bea840bada Mon Sep 17 00:00:00 2001 From: couriersud Date: Fri, 29 Mar 2019 19:40:39 +0100 Subject: netlist: Improved MOS transistor model. [Couriersud] This is a significant improvement to the MOS transistor model. It adds modelling of the Meyer capacitance model. This is a somewhat academic addition since the effects occur on a nanosecond time scale and have a huge impact on performance. I plan to make the capacitance model selectable. Both on a model level as well as by introducing a global solver parameter. The model delivers comparable results to LTSpice. --- nl_examples/nmos_fet.cpp | 10 +- src/lib/netlist/analog/nld_mosfet.cpp | 282 ++++++++++++++++++--------- src/lib/netlist/analog/nlid_twoterm.h | 76 ++++++-- src/lib/netlist/build/makefile | 3 + src/lib/netlist/devices/nlid_proxy.cpp | 4 +- src/lib/netlist/macro/nlm_base.cpp | 4 +- src/lib/netlist/nl_base.h | 2 +- src/lib/netlist/nl_config.h | 1 + src/lib/netlist/nl_setup.cpp | 1 + src/lib/netlist/solver/nld_matrix_solver.cpp | 2 +- src/lib/netlist/solver/nld_solver.h | 2 +- 11 files changed, 266 insertions(+), 121 deletions(-) diff --git a/nl_examples/nmos_fet.cpp b/nl_examples/nmos_fet.cpp index ffa67c1bf00..8a096af59ac 100644 --- a/nl_examples/nmos_fet.cpp +++ b/nl_examples/nmos_fet.cpp @@ -9,13 +9,15 @@ #include "netlist/devices/net_lib.h" #include "netlist/analog/nld_twoterm.h" -NETLIST_START(bjt) +NETLIST_START(nmos) /* Standard stuff */ CLOCK(clk, 100) // 100 Hz SOLVER(Solver, 48000) - PARAM(Solver.ACCURACY, 1e-7) - PARAM(Solver.NR_LOOPS, 5000) + PARAM(Solver.ACCURACY, 1e-9) + PARAM(Solver.NR_LOOPS, 50000) + PARAM(Solver.DYNAMIC_TS, 1) + PARAM(Solver.DYNAMIC_MIN_TIMESTEP, 1e-9) ANALOG_INPUT(V5, 5) ANALOG_INPUT(V3, 3.5) @@ -40,7 +42,7 @@ NETLIST_START(bjt) NET_C(RCE.1, M.D) NET_C(RCE.2, GND) - // capacitance over D - S + // capacitance over G - S CAP(C, CAP_N(1)) NET_C(M.D, C.1) diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index ea717fdefee..f941d06076a 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -57,9 +57,9 @@ namespace analog * | Y |Is | Bulk junction saturation current |A|0.00000000000001|1E-015| * | Y |N | Bulk diode emission coefficient |-|1|* * | |Pb | Bulk junction potential |V|0.8|0.87|8| - * | |Cgso | Gate-source overlap capacitance per meter channel width |F/m|0|0.00000000004| - * | |Cgdo | Gate-drain overlap capacitance per meter channel width |F/m|0|0.00000000004|* - * | |Cgbo | Gate-bulk overlap capacitance per meter channel width |F/m|0|0.0000000002|* + * | Y |Cgso | Gate-source overlap capacitance per meter channel width |F/m|0|0.00000000004| + * | Y |Cgdo | Gate-drain overlap capacitance per meter channel width |F/m|0|0.00000000004|* + * | Y |Cgbo | Gate-bulk overlap capacitance per meter channel width |F/m|0|0.0000000002|* * | |Rsh | Drain and source diffusion sheet resistance |W|0|10|* * | |Cj | Zero-bias bulk junction bottom capacitance per square meter of junction area|F/m²|0|0.0002|* * | |Mj | Bulk junction bottom grading coefficient |-|0.5|0.5|* @@ -87,8 +87,8 @@ namespace analog * | |Eta | Static feedback (level 3 only) |-|0|1| * | |Kappa | Saturation field (level 3 only) |0.2|0.5| * | |Tnom | Parameter measurement temperature |ºC|27|50|| - * | Y |L | Length scaling |-|1.0|| - * | Y |W | Width scaling |-|1.0|| + * | Y |L | Length scaling |-|100e-6|| + * | Y |W | Width scaling |-|100e-6|| * */ class fet_model_t : public param_model_t @@ -112,24 +112,30 @@ namespace analog , m_LAMBDA(*this, "LAMBDA") , m_RD(*this, "RD") , m_RS(*this, "RS") + , m_CGSO(*this, "CGSO") + , m_CGDO(*this, "CGDO") + , m_CGBO(*this, "CGBO") {} - value_t m_VTO; //!< Threshold voltage [V] - value_t m_N; //!< Bulk diode emission coefficient - value_t m_ISS; //!< Body diode saturation current - value_t m_ISD; //!< Body diode saturation current - value_t m_LD; //!< Lateral diffusion [m] - value_t m_L; //!< Length scaling - value_t m_W; //!< Width scaling - value_t m_TOX; //!< Oxide thickness - value_t m_KP; //!< Transconductance parameter [A/V²] - value_t m_UO; //!< Surface mobility [cm²/V/s] - value_t m_PHI; //!< Surface inversion potential [V] - value_t m_NSUB;//!< Substrate doping [1/cm³] - value_t m_GAMMA; //!< Bulk threshold parameter [V^½] - value_t m_LAMBDA; //!< Channel-length modulation [1/V] - value_t m_RD; //!< Drain ohmic resistance - value_t m_RS; //!< Source ohmic resistance + value_t m_VTO; //!< Threshold voltage [V] + value_t m_N; //!< Bulk diode emission coefficient + value_t m_ISS; //!< Body diode saturation current + value_t m_ISD; //!< Body diode saturation current + value_t m_LD; //!< Lateral diffusion [m] + value_t m_L; //!< Length scaling + value_t m_W; //!< Width scaling + value_t m_TOX; //!< Oxide thickness + value_t m_KP; //!< Transconductance parameter [A/V²] + value_t m_UO; //!< Surface mobility [cm²/V/s] + value_t m_PHI; //!< Surface inversion potential [V] + value_t m_NSUB; //!< Substrate doping [1/cm³] + value_t m_GAMMA; //!< Bulk threshold parameter [V^½] + value_t m_LAMBDA; //!< Channel-length modulation [1/V] + value_t m_RD; //!< Drain ohmic resistance + value_t m_RS; //!< Source ohmic resistance + value_t m_CGSO; //!< Gate-source overlap capacitance per meter channel width + value_t m_CGDO; //!< Gate-drain overlap capacitance per meter channel width + value_t m_CGBO; //!< Gate-bulk overlap capacitance per meter channel width }; // Have a common start for mosfets @@ -167,7 +173,6 @@ namespace analog // nld_QBJT_EB // ----------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(MOSFET, FET) { public: @@ -179,13 +184,21 @@ namespace analog #if (!BODY_CONNECTED_TO_SOURCE) , m_D_BS(*this, "m_D_BS") #endif + , 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_Cox(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) + { register_subalias("S", m_SG.m_P); // Source register_subalias("G", m_SG.m_N); // Gate @@ -212,6 +225,20 @@ namespace analog #endif } + NETLIB_IS_TIMESTEP(true) + + NETLIB_TIMESTEPI() + { + const nl_double Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain + const nl_double Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source + const nl_double Ubs = 0.0; // Bulk - Source == 0 if connected + const nl_double Ugb = Ugs - Ubs; + + m_cap_gb.timestep(m_Cgb, Ugb, step); + m_cap_gs.timestep(m_Cgs, Ugs, step); + m_cap_gd.timestep(m_Cgd, Ugd, step); + } + protected: NETLIB_RESETI(); @@ -230,6 +257,11 @@ namespace analog generic_diode m_D_BS; #endif + generic_capacitor m_cap_gb; + generic_capacitor m_cap_gs; + generic_capacitor m_cap_gd; + + nl_double m_phi; nl_double m_gamma; nl_double m_vto; @@ -238,19 +270,80 @@ namespace analog /* used in capacitance calculation */ nl_double m_Leff; - nl_double m_Cox; + nl_double m_CoxWL; + nl_double m_polarity; - //NETLIB_SUBXX(analog, C) m_CJE; - //NETLIB_SUBXX(analog, C) m_CJC; - }; + /* capacitance values */ + nl_double m_Cgb; + nl_double m_Cgs; + nl_double m_Cgd; + void set_cap(generic_capacitor cap, + nl_double capval, nl_double V, + nl_double &g11, nl_double &g12, nl_double &g21, nl_double &g22, + nl_double &I1, nl_double &I2) + { + const nl_double I = cap.Ieq(capval, V) * m_polarity; + const nl_double G = cap.G(capval); + g11 += G; g12 -= G; g21 -= G; g22 += G; + I1 -= I; I2 += I; + //printf("Cap: %g\n", capval); + } + + void calculate_caps(nl_double Vgs, nl_double Vgd, nl_double Vth, + nl_double &Cgs, nl_double &Cgd, nl_double &Cgb) + { + nl_double Vctrl = Vgs - Vth * m_polarity; + // Cut off - now further differentiated into 3 different formulas + // Accumulation + if (Vctrl <= -m_phi) + { + Cgb = m_CoxWL; + Cgs = 0.0; + Cgd = 0.0; + } + else if (Vctrl <= -m_phi / 2.0) + { + Cgb = -Vctrl * m_CoxWL / m_phi; + Cgs = 0.0; + Cgd = 0.0; + } + // 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; + } + else + { + const nl_double Vdsat = Vctrl; + const nl_double Vds = Vgs - Vgd; + // saturation + if (Vdsat <= Vds) + { + Cgb = 0; + Cgs = (2.0 / 3.0) * m_CoxWL; + Cgd = 0; + } + else + { + // linear + const nl_double Sqr1 = std::pow(Vdsat - Vds, 2); + const nl_double Sqr2 = std::pow(2.0 * 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); + } + } + } + }; // ---------------------------------------------------------------------------------------- // nld_Q - Ebers Moll // ---------------------------------------------------------------------------------------- - NETLIB_UPDATE(MOSFET) { if (!m_SG.m_P.net().isRailNet()) @@ -264,46 +357,34 @@ namespace analog NETLIB_RESET(MOSFET) { NETLIB_NAME(FET)::reset(); -#if 0 - if (m_CJE) - { - m_CJE->reset(); - m_CJE->m_C.setTo(m_model.m_CJE); - } - if (m_CJC) - { - m_CJC->reset(); - m_CJC->m_C.setTo(m_model.m_CJC); - } -#endif } NETLIB_UPDATE_TERMINALS(MOSFET) { - const nl_double polarity = (qtype() == FET_NMOS ? 1.0 : -1.0); - - const nl_double Ugd = -m_DG.deltaV() * polarity; // Gate - Drain - const nl_double Ugs = -m_SG.deltaV() * polarity; // Gate - Source - const nl_double Ubs = 0.0; // Bulk - Source == 0 if connected - const nl_double Ubd = m_SD.deltaV() * polarity; // Bulk - Drain = Source - Drain - const nl_double Uds = Ugs - Ugd; + const nl_double Vgd = -m_DG.deltaV() * m_polarity; // Gate - Drain + const nl_double Vgs = -m_SG.deltaV() * m_polarity; // Gate - Source + const nl_double Vbs = 0.0; // Bulk - Source == 0 if connected + const nl_double Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain + const nl_double Vds = Vgs - Vgd; #if (!BODY_CONNECTED_TO_SOURCE) - m_D_BS.update_diode(Ubs); + m_D_BS.update_diode(Vbs); #endif - m_D_BD.update_diode(Ubd); + m_D_BD.update_diode(Vbd); // Are we in forward mode ? - const bool is_forward = Uds >= 0; + // in backward mode, just swap source and drain + const bool is_forward = Vds >= 0; // calculate Vth - const nl_double Vbulk = is_forward ? Ubs : Ubd; + const nl_double Vbulk = is_forward ? Vbs : Vbd; const nl_double phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : 0.0; - const nl_double Vth = m_vto * polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi)); + const nl_double Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi)); - const nl_double Vctrl = (is_forward ? Ugs : Ugd) - Vth; + const nl_double Vctrl = (is_forward ? Vgs : Vgd) - Vth; nl_double Ids, gm, gds, gmb; + const nl_double absVds = std::abs(Vds); if (Vctrl <= 0.0) { @@ -315,21 +396,20 @@ namespace analog } else { - const nl_double Vds = std::abs(Uds); - const nl_double b = m_beta * (1.0 + m_lambda * Vds); - if (Vctrl <= Vds) + const nl_double beta = m_beta * (1.0 + m_lambda * absVds); + if (Vctrl <= absVds) { // saturation region - Ids = b * Vctrl * Vctrl / 2.0; - gm = b * Vctrl; + Ids = beta * Vctrl * Vctrl / 2.0; + gm = beta * Vctrl; gds = m_lambda * m_beta * Vctrl * Vctrl / 2.0; } else { // linear region - Ids = b * Vds * (Vctrl - Vds / 2); - gm = b * Vds; - gds = b * (Vctrl - Vds) + m_lambda * m_beta * Vds * (Vctrl - Vds / 2.0); + Ids = beta * absVds * (Vctrl - absVds / 2); + gm = beta * absVds; + gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / 2.0); } // backgate transconductance @@ -345,7 +425,7 @@ namespace analog const nl_double IeqBD = m_D_BD.Ieq(); const nl_double gbd = m_D_BD.G(); -#if 0 +#if (!BODY_CONNECTED_TO_SOURCE) const nl_double IeqBS = m_D_BS.Ieq(); const nl_double gbs = m_D_BS.G(); #else @@ -357,34 +437,45 @@ namespace analog const nl_double gdrain = is_forward ? 0.0 : (gm + gmb); const nl_double IeqDS = (is_forward) ? - Ids - gm * Ugs - gmb * Ubs - gds * Uds - : -Ids - gm * Ugd - gmb * Ubd - gds * Uds; + Ids - gm * Vgs - gmb * Vbs - gds * Vds + : -Ids - gm * Vgd - gmb * Vbd - gds * Vds; // IG = 0 - const nl_double IG = 0.0; - const nl_double ID = (+IeqBD - IeqDS) * polarity; - const nl_double IS = (+IeqBS + IeqDS) * polarity; - const nl_double IB = (-IeqBD - IeqBS) * polarity; - - const nl_double gGG = 0.0; // ok - const nl_double gGD = 0.0; // ok - const nl_double gGS = 0.0; // ok - const nl_double gGB = 0.0; // ok - - const nl_double gDG = gm; // ok - const nl_double gDD = gds + gbd - gdrain; // ok - const nl_double gDS = -gds - gsource; // ok - const nl_double gDB = gmb - gbd; // ok - - const nl_double gSG = -gm; // ok - const nl_double gSD = -gds + gdrain; // ok - const nl_double gSS = gbs + gds + gsource; // ok + nl_double IG = 0.0; + nl_double ID = (+IeqBD - IeqDS) * m_polarity; + nl_double IS = (+IeqBS + IeqDS) * m_polarity; + nl_double IB = (-IeqBD - IeqBS) * m_polarity; + + nl_double gGG = 0.0; + nl_double gGD = 0.0; + nl_double gGS = 0.0; + nl_double gGB = 0.0; + + nl_double gDG = gm; + nl_double gDD = gds + gbd - gdrain; + const nl_double gDS = -gds - gsource; + const nl_double gDB = gmb - gbd; + + nl_double gSG = -gm; + const nl_double gSD = -gds + gdrain; + nl_double gSS = gbs + gds + gsource; const nl_double gSB = -gbs - gmb; - const nl_double gBG = 0.0; // ok - const nl_double gBD = -gbd; // ok + nl_double gBG = 0.0; + const nl_double gBD = -gbd; const nl_double gBS = -gbs; - const nl_double gBB = gbs + gbd; // ok + nl_double gBB = gbs + gbd; + + const nl_double Vgb = Vgs - Vbs; + + if (is_forward) + calculate_caps(Vgs, Vgd, Vth, m_Cgs, m_Cgd, m_Cgb); + else + calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb); + + set_cap(m_cap_gb, m_Cgb + m_model.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB); + set_cap(m_cap_gs, m_Cgs + m_model.m_CGSO * m_model.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS); + set_cap(m_cap_gd, m_Cgd + m_model.m_CGDO * m_model.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID); // Source connected to body, Diode S-B shorted! const nl_double gSSBB = gSS + gBB + gBS + gSB; @@ -398,13 +489,12 @@ namespace analog // S D m_SD.set_mat( 0.0, gSD + gBD, 0.0, // S gDS + gDB, 0.0, 0.0); // D - } - NETLIB_UPDATE_PARAM(MOSFET) { set_qtype((m_model.model_type() == "NMOS") ? FET_NMOS : FET_PMOS); + m_polarity = qtype() == FET_NMOS ? 1.0 : -1.0; /* * From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm : @@ -422,16 +512,14 @@ 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()); - if (m_model.m_TOX > 0.0) - m_Cox = (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX); - else - m_Cox = 0.0; + + nl_double Cox = (m_model.m_TOX > 0.0) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : 0.0; // calculate DC transconductance coefficient if (m_model.m_KP > 0) m_beta = m_model.m_KP * m_model.m_W / m_Leff; - else if (m_Cox > 0 && m_model.m_UO > 0) - m_beta = m_model.m_UO * 1e-4 * m_Cox * 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 m_beta = 2e-5 * m_model.m_W / m_Leff; @@ -462,8 +550,8 @@ namespace analog m_gamma = m_model.m_GAMMA; else { - if (m_Cox > 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) / m_Cox; + 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; else m_gamma = 0.0; } @@ -475,7 +563,9 @@ namespace analog * specify VTO so skip this here. */ - m_Cox = m_Cox * m_model.m_W * m_Leff; + m_CoxWL = Cox * m_model.m_W * m_Leff; + + //printf("Cox: %g\n", m_Cox); } diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index 470fb35c96e..aaf35fe9e28 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -87,7 +87,7 @@ public: void solve_now(); - void solve_later(netlist_time delay = netlist_time::from_nsec(1)); + void solve_later(netlist_time delay = netlist_time::quantum()); void set_G_V_I(const nl_double G, const nl_double V, const nl_double I) { @@ -226,7 +226,7 @@ private: enum class capacitor_e { - CHARGE_CONSERVING, + VARIABLE_CAPACITY, CONSTANT_CAPACITY }; @@ -235,19 +235,63 @@ class generic_capacitor { }; +#if 1 +template <> +class generic_capacitor +{ +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) + { + } + + capacitor_e type() const { return capacitor_e::VARIABLE_CAPACITY; } + nl_double G(nl_double cap) const + { + //return m_h * (2.0 * cap - m_c) + m_gmin; + return m_h * 0.5 * (cap + m_c) + m_gmin; + } + + nl_double Ieq(nl_double cap, nl_double v) const + { + plib::unused_var(v); +// return m_h * (cap * v - m_charge) - G(cap) * v; + return -m_h * 0.5 * (cap + m_c) * m_v; + } + + void timestep(nl_double cap, nl_double v, nl_double step) + { + m_h = 1.0 / step; + m_c = cap; + m_v = v; + } + + void setparams(nl_double gmin) { m_gmin = gmin; } + +private: + state_var m_h; + state_var m_c; + state_var m_v; + nl_double m_gmin; +}; +#else template <> -class generic_capacitor +class generic_capacitor { public: generic_capacitor(device_t &dev, const pstring &name) : m_h(dev, name + ".m_h", 0.0) , m_charge(dev, name + ".m_charge", 0.0) + , m_v(dev, name + ".m_v", 0.0) , m_gmin(0.0) { } - constexpr capacitor_e type() const { return capacitor_e::CHARGE_CONSERVING; } + constexpr capacitor_e type() const { return capacitor_e::VARIABLE_CAPACITY; } constexpr nl_double G(nl_double cap) const { @@ -256,13 +300,16 @@ public: constexpr nl_double Ieq(nl_double cap, nl_double v) const { - return m_h * (cap * v - m_charge) - G(cap) * v; +// return m_h * (cap * v - m_charge) - G(cap) * v; +// return m_h * (cap * (v - m_v)) - G(cap) * v; + return -m_h * cap * m_v; } void timestep(nl_double cap, nl_double v, nl_double step) { m_h = 1.0 / step; - m_charge = cap * v; + m_charge = m_charge + cap * (v - m_v); + m_v = v; } void setparams(nl_double gmin) { m_gmin = gmin; } @@ -270,9 +317,10 @@ public: private: state_var m_h; state_var m_charge; + state_var m_v; nl_double m_gmin; }; - +#endif template <> class generic_capacitor { @@ -283,9 +331,9 @@ public: { } - constexpr capacitor_e type() const { return capacitor_e::CONSTANT_CAPACITY; } - constexpr nl_double G(nl_double cap) const { return cap * m_h + m_gmin; } - constexpr nl_double Ieq(nl_double cap, nl_double v) const { return - G(cap) * v; } + capacitor_e type() const { return capacitor_e::CONSTANT_CAPACITY; } + nl_double G(nl_double cap) const { return cap * m_h + m_gmin; } + nl_double Ieq(nl_double cap, nl_double v) const { return - G(cap) * v; } void timestep(nl_double cap, nl_double v, nl_double step) { @@ -324,7 +372,7 @@ public: } } - NETLIB_IS_DYNAMIC(m_cap.type() == capacitor_e::CHARGE_CONSERVING) + NETLIB_IS_DYNAMIC(m_cap.type() == capacitor_e::VARIABLE_CAPACITY) NETLIB_UPDATE_TERMINALSI() { const nl_double I = m_cap.Ieq(m_C(), deltaV()); @@ -344,8 +392,8 @@ protected: NETLIB_UPDATE_PARAMI() { } private: - generic_capacitor m_cap; - //generic_capacitor m_cap; + //generic_capacitor m_cap; + generic_capacitor m_cap; }; // ----------------------------------------------------------------------------- @@ -429,7 +477,7 @@ public: else if (TYPE == diode_e::MOS || nVd < m_Vcrit) { m_Vd = nVd; - const double IseVDVt = std::exp(std::min(700.0, m_logIs + m_Vd * m_VtInv)); + const double IseVDVt = std::exp(std::min(300.0, m_logIs + m_Vd * m_VtInv)); m_Id = IseVDVt - m_Is; m_G = IseVDVt * m_VtInv + m_gmin; } diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 647c7df6f12..6179a0e5932 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -230,6 +230,9 @@ maketree: $(sort $(OBJDIRS)) native: $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra " +gcc5: + $(MAKE) CC=g++-5 LD=g++-5 CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra " + clang: $(MAKE) CC=clang++-9 LD=clang++-9 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index a2fd18e85a7..e40d3506cff 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -58,9 +58,9 @@ namespace netlist if (supply_V == 0.0) supply_V = 5.0; if (m_I.Q_Analog() > logic_family()->high_thresh_V(0.0, supply_V)) - out().push(1, NLTIME_FROM_NS(1)); + out().push(1, netlist_time::quantum()); else if (m_I.Q_Analog() < logic_family()->low_thresh_V(0.0, supply_V)) - out().push(0, NLTIME_FROM_NS(1)); + out().push(0, netlist_time::quantum()); else { // do nothing diff --git a/src/lib/netlist/macro/nlm_base.cpp b/src/lib/netlist/macro/nlm_base.cpp index 86f2450d301..2e4542de4b6 100644 --- a/src/lib/netlist/macro/nlm_base.cpp +++ b/src/lib/netlist/macro/nlm_base.cpp @@ -34,8 +34,8 @@ NETLIST_END() static NETLIST_START(mosfet_models) //NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") //NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") - NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") - NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") + NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)") + NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)") NETLIST_END() static NETLIST_START(bjt_models) diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 9d0eed869e0..c1f07a55af2 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -1710,7 +1710,7 @@ namespace netlist if (newQ != m_my_net.Q_Analog()) { m_my_net.set_Q_Analog(newQ); - m_my_net.toggle_and_push_to_queue(NLTIME_FROM_NS(1)); + m_my_net.toggle_and_push_to_queue(netlist_time::quantum()); } } diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index faa5008ff56..98ca0e27370 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -89,6 +89,7 @@ // Use nano-second resolution - Sufficient for now static constexpr const auto NETLIST_INTERNAL_RES = 1000000000; +//static constexpr const auto NETLIST_INTERNAL_RES = 1000000000000; static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES; //#define NETLIST_INTERNAL_RES (UINT64_C(1000000000)) diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index b9300f5ad9c..3ae73b50f6f 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -737,6 +737,7 @@ void setup_t::resolve_inputs() detail::core_terminal_t *t1 = find_terminal(t1s); detail::core_terminal_t *t2 = find_terminal(t2s); + //printf("%s %s\n", t1s.c_str(), t2s.c_str()); if (connect(*t1, *t2)) li = m_links.erase(li); else diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 1fe14b0f5e1..0a7bf5ef3c3 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -19,7 +19,7 @@ namespace devices : m_railstart(0) , m_last_V(0.0) , m_DD_n_m_1(0.0) - , m_h_n_m_1(1e-9) + , m_h_n_m_1(1e-12) { } diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index c9ec967a72a..3580ca94996 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -48,7 +48,7 @@ namespace devices , m_gmin(*this, "GMIN", 1e-9) , m_pivot(*this, "PIVOT", false) // use pivoting - on supported solvers , m_nr_loops(*this, "NR_LOOPS", 250) // Newton-Raphson loops - , m_nr_recalc_delay(*this, "NR_RECALC_DELAY", NLTIME_FROM_NS(10).as_double()) // Delay to next solve attempt if nr loops exceeded + , m_nr_recalc_delay(*this, "NR_RECALC_DELAY", netlist_time::quantum().as_double()) // Delay to next solve attempt if nr loops exceeded , m_parallel(*this, "PARALLEL", 0) /* automatic time step */ -- cgit v1.2.3