diff options
Diffstat (limited to 'src/lib/netlist/analog/nld_mosfet.cpp')
-rw-r--r-- | src/lib/netlist/analog/nld_mosfet.cpp | 155 |
1 files changed, 79 insertions, 76 deletions
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) |