- added cstddef to includes in ppmf.h - more explicit comments in ppmf.h - Fixed more typos and improved readiability
This commit is contained in:
parent
ceafeebd49
commit
034e0d2c87
@ -5,6 +5,9 @@
|
||||
#include "nl_base.h"
|
||||
#include "nlid_twoterm.h"
|
||||
|
||||
// Names
|
||||
// spell-checker: words Ebers, Moll
|
||||
|
||||
// FIXME: Remove QBJT_switch - no more use
|
||||
|
||||
namespace netlist
|
||||
@ -174,7 +177,7 @@ namespace analog
|
||||
NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
|
||||
{
|
||||
NETLIB_CONSTRUCTOR(QBJT_switch)
|
||||
, m_modacc(m_model)
|
||||
, m_bjt_model(m_model)
|
||||
, m_RB(*this, "m_RB", NETLIB_DELEGATE(termhandler))
|
||||
, m_RC(*this, "m_RC", NETLIB_DELEGATE(termhandler))
|
||||
, m_BC(*this, "m_BC", NETLIB_DELEGATE(termhandler))
|
||||
@ -206,7 +209,7 @@ namespace analog
|
||||
NETLIB_UPDATE_TERMINALSI();
|
||||
|
||||
private:
|
||||
bjt_model_t m_modacc;
|
||||
bjt_model_t m_bjt_model;
|
||||
nld_twoterm m_RB;
|
||||
nld_twoterm m_RC;
|
||||
nld_twoterm m_BC;
|
||||
@ -227,7 +230,7 @@ namespace analog
|
||||
{
|
||||
public:
|
||||
NETLIB_CONSTRUCTOR(QBJT_EB)
|
||||
, m_modacc(m_model)
|
||||
, m_bjt_model(m_model)
|
||||
, m_gD_BC(*this, "m_D_BC")
|
||||
, m_gD_BE(*this, "m_D_BE")
|
||||
, m_D_CB(*this, "m_D_CB", NETLIB_DELEGATE(termhandler))
|
||||
@ -245,13 +248,13 @@ namespace analog
|
||||
connect(m_D_EB.N(), m_D_CB.N());
|
||||
connect(m_D_CB.P(), m_D_EC.N());
|
||||
|
||||
if (m_modacc.m_CJE > nlconst::zero())
|
||||
if (m_bjt_model.m_CJE > nlconst::zero())
|
||||
{
|
||||
create_and_register_subdevice(*this, "m_CJE", m_CJE);
|
||||
connect("B", "m_CJE.1");
|
||||
connect("E", "m_CJE.2");
|
||||
}
|
||||
if (m_modacc.m_CJC > nlconst::zero())
|
||||
if (m_bjt_model.m_CJC > nlconst::zero())
|
||||
{
|
||||
create_and_register_subdevice(*this, "m_CJC", m_CJC);
|
||||
connect("B", "m_CJC.1");
|
||||
@ -276,7 +279,7 @@ namespace analog
|
||||
NETLIB_UPDATE_TERMINALSI();
|
||||
|
||||
private:
|
||||
bjt_model_t m_modacc;
|
||||
bjt_model_t m_bjt_model;
|
||||
generic_diode<diode_e::BIPOLAR> m_gD_BC;
|
||||
generic_diode<diode_e::BIPOLAR> m_gD_BE;
|
||||
|
||||
@ -315,13 +318,13 @@ namespace analog
|
||||
|
||||
NETLIB_UPDATE_PARAM(QBJT_switch)
|
||||
{
|
||||
nl_fptype IS = m_modacc.m_IS;
|
||||
nl_fptype BF = m_modacc.m_BF;
|
||||
nl_fptype NF = m_modacc.m_NF;
|
||||
//nl_fptype VJE = m_modacc.dValue("VJE", 0.75);
|
||||
nl_fptype IS = m_bjt_model.m_IS;
|
||||
nl_fptype BF = m_bjt_model.m_BF;
|
||||
nl_fptype NF = m_bjt_model.m_NF;
|
||||
//nl_fptype VJE = m_bjt_model.dValue("VJE", 0.75);
|
||||
|
||||
// FIXME: check for PNP as well and bail out
|
||||
set_qtype(m_modacc.m_type);
|
||||
set_qtype(m_bjt_model.m_type);
|
||||
|
||||
nl_fptype alpha = BF / (nlconst::one() + BF);
|
||||
|
||||
@ -375,12 +378,12 @@ namespace analog
|
||||
if (m_CJE)
|
||||
{
|
||||
m_CJE->reset();
|
||||
m_CJE->set_cap_embedded(m_modacc.m_CJE);
|
||||
m_CJE->set_cap_embedded(m_bjt_model.m_CJE);
|
||||
}
|
||||
if (m_CJC)
|
||||
{
|
||||
m_CJC->reset();
|
||||
m_CJC->set_cap_embedded(m_modacc.m_CJC);
|
||||
m_CJC->set_cap_embedded(m_bjt_model.m_CJC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,15 +415,15 @@ namespace analog
|
||||
|
||||
NETLIB_UPDATE_PARAM(QBJT_EB)
|
||||
{
|
||||
nl_fptype IS = m_modacc.m_IS;
|
||||
nl_fptype BF = m_modacc.m_BF;
|
||||
nl_fptype NF = m_modacc.m_NF;
|
||||
nl_fptype BR = m_modacc.m_BR;
|
||||
nl_fptype NR = m_modacc.m_NR;
|
||||
//nl_fptype VJE = m_m_modacc.dValue("VJE", 0.75);
|
||||
nl_fptype IS = m_bjt_model.m_IS;
|
||||
nl_fptype BF = m_bjt_model.m_BF;
|
||||
nl_fptype NF = m_bjt_model.m_NF;
|
||||
nl_fptype BR = m_bjt_model.m_BR;
|
||||
nl_fptype NR = m_bjt_model.m_NR;
|
||||
//nl_fptype VJE = m_m_bjt_model.dValue("VJE", 0.75);
|
||||
|
||||
// FIXME: check for PNP as well and bail out
|
||||
set_qtype(m_modacc.m_type);
|
||||
set_qtype(m_bjt_model.m_type);
|
||||
|
||||
m_alpha_f = BF / (nlconst::one() + BF);
|
||||
m_alpha_r = BR / (nlconst::one() + BR);
|
||||
|
@ -161,7 +161,7 @@ namespace netlist::analog
|
||||
struct generic_capacitor_const
|
||||
{
|
||||
public:
|
||||
generic_capacitor_const( [[maybe_unused]] core_device_t &dev, [[maybe_unused]] const pstring &name)
|
||||
generic_capacitor_const([[maybe_unused]] core_device_t &dev, [[maybe_unused]] const pstring &name)
|
||||
: m_gmin(nlconst::zero())
|
||||
, m_vn(0)
|
||||
, m_in(0)
|
||||
|
@ -1,22 +1,28 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
|
||||
// Names
|
||||
// spell-checker: words Farid, Naim, Jahn, Margraf, Habchi, Raimund, Qucs
|
||||
//
|
||||
// nld_mosfet.cpp
|
||||
//
|
||||
// Formulas in here based on the following Sources:
|
||||
//
|
||||
// https://www.imperial.ac.uk/pls/portallive/docs/1/7292573.PDF
|
||||
// http://www3.imperial.ac.uk/pls/portallive/docs/1/56133736.PDF
|
||||
// https://people.rit.edu/lffeee/SPICE_MOSFET_Model_Intro.pdf
|
||||
// https://people.rit.edu/lffeee/SPICE.pdf
|
||||
// http://web.mit.edu/course/6/6.012/SPR98/www/lectures/S98_Lecture10.pdf
|
||||
// http://homepages.rpi.edu/~sawyes/Models_review.pdf
|
||||
// http://jaco.ec.t.kanazawa-u.ac.jp/edu/mix/pdf/3.pdf
|
||||
//
|
||||
// Farid N. Naim, Circuit Simulation (Wiley-IEEE Press, 2010).
|
||||
// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs Technical Papers" (2007)
|
||||
//
|
||||
// Specific technical terms
|
||||
// spell-checker: words Cgso, Cgdo, Cgbo, Cjsw, Mjsw, Ucrit, Uexp, Utra, Neff, Tnom, capval, Udsat, Utst
|
||||
|
||||
///
|
||||
/// \file nld_mosfet.cpp
|
||||
///
|
||||
/// Formulas in here based on the following Sources:
|
||||
///
|
||||
/// https:///www.imperial.ac.uk/pls/portallive/docs/1/7292573.PDF
|
||||
/// http://www3.imperial.ac.uk/pls/portallive/docs/1/56133736.PDF
|
||||
/// https://people.rit.edu/lffeee/SPICE_MOSFET_Model_Intro.pdf
|
||||
/// https://people.rit.edu/lffeee/SPICE.pdf
|
||||
/// http://web.mit.edu/course/6/6.012/SPR98/www/lectures/S98_Lecture10.pdf
|
||||
/// http://homepages.rpi.edu/~sawyes/Models_review.pdf
|
||||
/// http://jaco.ec.t.kanazawa-u.ac.jp/edu/mix/pdf/3.pdf
|
||||
///
|
||||
/// Farid N. Naim, Circuit Simulation (Wiley-IEEE Press, 2010).
|
||||
/// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs Technical Papers" (2007)
|
||||
///
|
||||
|
||||
#include "solver/nld_solver.h"
|
||||
#include "../nl_setup.h"
|
||||
@ -35,7 +41,7 @@ namespace analog
|
||||
// nld_FET - Base classes
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/// \brief Class representing the nmos/pmos model paramers.
|
||||
/// \brief Class representing the nmos/pmos model parameters.
|
||||
///
|
||||
/// This is the model representation of the nmos model.
|
||||
///
|
||||
@ -202,10 +208,10 @@ namespace analog
|
||||
, m_Cgb(nlconst::zero())
|
||||
, m_Cgs(nlconst::zero())
|
||||
, m_Cgd(nlconst::zero())
|
||||
, m_capmod(2)
|
||||
, m_capacitor_model(2)
|
||||
, m_Vgs(*this, "m_Vgs", nlconst::zero())
|
||||
, m_Vgd(*this, "m_Vgd", nlconst::zero())
|
||||
, m_modacc(m_model)
|
||||
, m_model_acc(m_model)
|
||||
{
|
||||
register_subalias("S", m_SG.P()); // Source
|
||||
register_subalias("G", m_SG.N()); // Gate
|
||||
@ -219,9 +225,9 @@ namespace analog
|
||||
set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS);
|
||||
m_polarity = (qtype() == FET_NMOS ? nlconst::one() : -nlconst::one());
|
||||
|
||||
m_capmod = m_modacc.m_CAPMOD;
|
||||
// printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_modacc.m_VTO, m_polarity);
|
||||
nl_assert_always(m_capmod == 0 || m_capmod == 2, "Error: CAPMODEL invalid value");
|
||||
m_capacitor_model = m_model_acc.m_CAPMOD;
|
||||
//# printf("capmod %d %g %g\n", m_capacitor_model, (nl_fptype)m_model_acc.m_VTO, m_polarity);
|
||||
nl_assert_always(m_capacitor_model == 0 || m_capacitor_model == 2, "Error: CAPMODEL invalid value");
|
||||
|
||||
//
|
||||
// From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm :
|
||||
@ -233,51 +239,51 @@ namespace analog
|
||||
// But couldn't find a formula for lambda anywhere
|
||||
//
|
||||
|
||||
m_lambda = m_modacc.m_LAMBDA; // FIXME: m_lambda only set once
|
||||
m_lambda = m_model_acc.m_LAMBDA; // FIXME: m_lambda only set once
|
||||
|
||||
// calculate effective channel length
|
||||
m_Leff = m_modacc.m_L - 2 * m_modacc.m_LD;
|
||||
m_Leff = m_model_acc.m_L - 2 * m_model_acc.m_LD;
|
||||
nl_assert_always(m_Leff > nlconst::zero(), "Effective Lateral diffusion would be negative for model");
|
||||
|
||||
nl_fptype Cox = (m_modacc.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_modacc.m_TOX) : nlconst::zero();
|
||||
nl_fptype Cox = (m_model_acc.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model_acc.m_TOX) : nlconst::zero();
|
||||
|
||||
// calculate DC transconductance coefficient
|
||||
if (m_modacc.m_KP > nlconst::zero())
|
||||
m_beta = m_modacc.m_KP * m_modacc.m_W / m_Leff;
|
||||
else if (Cox > nlconst::zero() && m_modacc.m_UO > nlconst::zero())
|
||||
m_beta = m_modacc.m_UO * nlconst::magic(1e-4) * Cox * m_modacc.m_W / m_Leff;
|
||||
if (m_model_acc.m_KP > nlconst::zero())
|
||||
m_beta = m_model_acc.m_KP * m_model_acc.m_W / m_Leff;
|
||||
else if (Cox > nlconst::zero() && m_model_acc.m_UO > nlconst::zero())
|
||||
m_beta = m_model_acc.m_UO * nlconst::magic(1e-4) * Cox * m_model_acc.m_W / m_Leff;
|
||||
else
|
||||
m_beta = nlconst::magic(2e-5) * m_modacc.m_W / m_Leff;
|
||||
m_beta = nlconst::magic(2e-5) * m_model_acc.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_modacc.m_PHI > nlconst::zero())
|
||||
m_phi = m_modacc.m_PHI;
|
||||
else if (m_modacc.m_NSUB > nlconst::zero())
|
||||
if (m_model_acc.m_PHI > nlconst::zero())
|
||||
m_phi = m_model_acc.m_PHI;
|
||||
else if (m_model_acc.m_NSUB > nlconst::zero())
|
||||
{
|
||||
nl_assert_always(m_modacc.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model");
|
||||
m_phi = nlconst::two() * Vt * plib::log (m_modacc.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
|
||||
nl_assert_always(m_model_acc.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model");
|
||||
m_phi = nlconst::two() * Vt * plib::log (m_model_acc.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
|
||||
}
|
||||
else
|
||||
m_phi = nlconst::magic(0.6);
|
||||
|
||||
// calculate bulk threshold if not given
|
||||
if (m_modacc.m_GAMMA > nlconst::zero())
|
||||
m_gamma = m_modacc.m_GAMMA;
|
||||
if (m_model_acc.m_GAMMA > nlconst::zero())
|
||||
m_gamma = m_model_acc.m_GAMMA;
|
||||
else
|
||||
{
|
||||
if (Cox > nlconst::zero() && m_modacc.m_NSUB > nlconst::zero())
|
||||
if (Cox > nlconst::zero() && m_model_acc.m_NSUB > nlconst::zero())
|
||||
m_gamma = plib::sqrt (nlconst::two()
|
||||
* constants::Q_e() * constants::eps_Si() * constants::eps_0()
|
||||
* m_modacc.m_NSUB * nlconst::magic(1e6)) / Cox;
|
||||
* m_model_acc.m_NSUB * nlconst::magic(1e6)) / Cox;
|
||||
else
|
||||
m_gamma = nlconst::zero();
|
||||
}
|
||||
|
||||
m_vto = m_modacc.m_VTO;
|
||||
m_vto = m_model_acc.m_VTO;
|
||||
// FIXME zero conversion
|
||||
if(m_vto == nlconst::zero())
|
||||
log().warning(MW_MOSFET_THRESHOLD_VOLTAGE(m_model.name()));
|
||||
@ -285,21 +291,21 @@ namespace analog
|
||||
// FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models
|
||||
// specify VTO so skip this here.
|
||||
|
||||
m_CoxWL = Cox * m_modacc.m_W * m_Leff;
|
||||
m_CoxWL = Cox * m_model_acc.m_W * m_Leff;
|
||||
|
||||
//printf("Cox: %g\n", m_Cox);
|
||||
//#printf("Cox: %g\n", m_Cox);
|
||||
}
|
||||
|
||||
NETLIB_IS_TIMESTEP(true || m_capmod != 0)
|
||||
NETLIB_IS_TIMESTEP(true || m_capacitor_model != 0)
|
||||
|
||||
NETLIB_TIMESTEPI()
|
||||
{
|
||||
if (m_capmod != 0)
|
||||
if (m_capacitor_model != 0)
|
||||
{
|
||||
if (ts_type == timestep_type::FORWARD)
|
||||
{
|
||||
//const nl_nl_fptype Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
//const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
|
||||
//#const nl_nl_fptype Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
//#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 = nlconst::zero(); // Bulk - Source == 0 if connected
|
||||
@ -325,9 +331,9 @@ namespace analog
|
||||
NETLIB_NAME(FET)::reset();
|
||||
// Bulk diodes
|
||||
|
||||
m_D_BD.set_param(m_modacc.m_ISD, m_modacc.m_N, exec().gmin(), constants::T0());
|
||||
m_D_BD.set_param(m_model_acc.m_ISD, m_model_acc.m_N, exec().gmin(), constants::T0());
|
||||
#if (!BODY_CONNECTED_TO_SOURCE)
|
||||
m_D_BS.set_param(m_modacc.m_ISS, m_modacc.m_N, exec().gmin(), constants::T0());
|
||||
m_D_BS.set_param(m_model_acc.m_ISS, m_model_acc.m_N, exec().gmin(), constants::T0());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -375,10 +381,10 @@ namespace analog
|
||||
nl_fptype m_Cgs;
|
||||
nl_fptype m_Cgd;
|
||||
|
||||
int m_capmod;
|
||||
int m_capacitor_model;
|
||||
state_var<nl_fptype> m_Vgs;
|
||||
state_var<nl_fptype> m_Vgd;
|
||||
fet_model_t m_modacc;
|
||||
fet_model_t m_model_acc;
|
||||
|
||||
void set_cap(generic_capacitor<capacitor_e::VARIABLE_CAPACITY> &cap,
|
||||
nl_fptype capval, nl_fptype V,
|
||||
@ -515,7 +521,7 @@ namespace analog
|
||||
gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / nlconst::two());
|
||||
}
|
||||
|
||||
// backgate transconductance
|
||||
// back gate transconductance
|
||||
const nl_fptype bgtc = (phi_m_Vbulk != nlconst::zero()) ? (m_gamma / phi_m_Vbulk / nlconst::two()) : nlconst::zero();
|
||||
gmb = gm * bgtc;
|
||||
}
|
||||
@ -570,7 +576,7 @@ namespace analog
|
||||
const nl_fptype gBS = -gbs;
|
||||
nl_fptype gBB = gbs + gbd;
|
||||
|
||||
if (m_capmod != 0)
|
||||
if (m_capacitor_model != 0)
|
||||
{
|
||||
const nl_fptype Vgb = Vgs - Vbs;
|
||||
|
||||
@ -579,9 +585,9 @@ namespace analog
|
||||
else
|
||||
calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb);
|
||||
|
||||
set_cap(m_cap_gb, m_Cgb + m_modacc.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
|
||||
set_cap(m_cap_gs, m_Cgs + m_modacc.m_CGSO * m_modacc.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
|
||||
set_cap(m_cap_gd, m_Cgd + m_modacc.m_CGDO * m_modacc.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
|
||||
set_cap(m_cap_gb, m_Cgb + m_model_acc.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
|
||||
set_cap(m_cap_gs, m_Cgs + m_model_acc.m_CGSO * m_model_acc.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
|
||||
set_cap(m_cap_gd, m_Cgd + m_model_acc.m_CGDO * m_model_acc.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
|
||||
}
|
||||
|
||||
// Source connected to body, Diode S-B shorted!
|
||||
|
@ -72,7 +72,7 @@ namespace netlist::analog
|
||||
, m_N(*this, "2", &m_P, NETLIB_DELEGATE(termhandler))
|
||||
{
|
||||
}
|
||||
//NETLIB_CONSTRUCTOR_EX(twoterm, nldelegate owner_delegate)
|
||||
//#NETLIB_CONSTRUCTOR_EX(twoterm, nldelegate owner_delegate)
|
||||
template <class C>
|
||||
NETLIB_NAME(twoterm)(C &owner, const pstring &name, nldelegate owner_delegate) \
|
||||
: base_type(owner, name)
|
||||
@ -233,7 +233,7 @@ namespace netlist::analog
|
||||
|
||||
private:
|
||||
param_fp_t m_R;
|
||||
// protect set_R ... it's a recipe to desaster when used to bypass the parameter
|
||||
// protect set_R ... it's a recipe to disaster when used to bypass the parameter
|
||||
using NETLIB_NAME(R_base)::set_R;
|
||||
using NETLIB_NAME(R_base)::set_G;
|
||||
};
|
||||
@ -444,7 +444,7 @@ namespace netlist::analog
|
||||
state_var<nl_fptype> m_last_G;
|
||||
};
|
||||
|
||||
/// \brief Class representing the diode model paramers.
|
||||
/// \brief Class representing the diode model parameters.
|
||||
///
|
||||
/// This is the model representation of the diode model. Typically, SPICE uses
|
||||
/// the following parameters. A "Y" in the first column indicates that the
|
||||
|
@ -1,33 +1,47 @@
|
||||
{
|
||||
"words" : [
|
||||
"MAME",
|
||||
"netlist",
|
||||
"netlists",
|
||||
"astable",
|
||||
"behavioural",
|
||||
"datasheet",
|
||||
"cmos",
|
||||
"opamp",
|
||||
"opamps",
|
||||
"mosfet",
|
||||
"mosfets",
|
||||
"Chebyshev",
|
||||
"Fairchild",
|
||||
"Schmitt",
|
||||
"Transconductance",
|
||||
"nmos",
|
||||
"pmos",
|
||||
"retriggerable", // not in leo
|
||||
"presettable", // not in leo
|
||||
"misformatted", // not in leo
|
||||
"monostable",
|
||||
"datasheets",
|
||||
"demultiplexer",
|
||||
"demultiplexers",
|
||||
"behavioural",
|
||||
"highpass",
|
||||
"nltool",
|
||||
"nvcc",
|
||||
"lowpass",
|
||||
"misformatted", // not in leo
|
||||
"monostable",
|
||||
"presettable", // not in leo
|
||||
"transconductance",
|
||||
"retriggerable", // not in leo
|
||||
// Names
|
||||
"Chebyshev",
|
||||
"Raphson",
|
||||
"Schmitt",
|
||||
"Schottky",
|
||||
"Zener",
|
||||
// Company names
|
||||
"Fairchild",
|
||||
"Signetics",
|
||||
"Mostek",
|
||||
// Technical terms
|
||||
"cmos",
|
||||
"kaby", // Kaby Lake
|
||||
"mosfet",
|
||||
"mosfets",
|
||||
"nmos",
|
||||
"opamp",
|
||||
"opamps",
|
||||
"pmos",
|
||||
// Specific project terms
|
||||
"MAME",
|
||||
"Couriersud",
|
||||
"plib", // FIXME: Remove everything below here again
|
||||
"ppmf"
|
||||
"netlist",
|
||||
"netlists",
|
||||
"nltool",
|
||||
"nlwav",
|
||||
"nvcc",
|
||||
// FIXME: Remove everything below here again
|
||||
"pstring"
|
||||
],
|
||||
"languageSettings": [
|
||||
// This one works with Python
|
||||
@ -53,10 +67,10 @@
|
||||
// Turn off compound words, because it is only checking strings.
|
||||
"allowCompoundWords": false,
|
||||
// Only check comments and strings
|
||||
"includeRegExpList": [
|
||||
"CStyleComment",
|
||||
"string"
|
||||
],
|
||||
//"includeRegExpList": [
|
||||
// "CStyleComment",
|
||||
// "string"
|
||||
//],
|
||||
"ignoreRegExpList": [
|
||||
"/#include.*/", // Exclude includes, because they are also strings
|
||||
"/#pragma.*/", // Exclude pragmas, they may include strings
|
||||
@ -69,7 +83,10 @@
|
||||
// Project specific exclusions start here
|
||||
"/\/\/ copyright-holders.*/",
|
||||
"/\/\/- Pinalias:/",
|
||||
"/\/\/#.*/" // commented source code
|
||||
"/\/\/#.*/", // commented source code
|
||||
"\/\/ Source:.*/", // generated code
|
||||
"/\\$[A-z0-9][^\\s]*/", // everything starting with a $
|
||||
"/[A-z][^\\s]+::[^\\s]+/" // any namespace qualifier
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -232,7 +232,7 @@ ALLFILES = $(ALLSOURCES) $(VSFILES) $(DOCS) $(OTHERFILES)
|
||||
MAKEFILE_TARGETS_WITHOUT_INCLUDE := \
|
||||
clang clang-5 clang-libc gcc9 mingw native nvcc \
|
||||
clean depend doc generated manpages maketree \
|
||||
runtests tidy
|
||||
runtests tidy fix_permissions precommit srcclean
|
||||
|
||||
BUILD_DIRS = $(OBJDIRS) man html
|
||||
|
||||
|
@ -56,25 +56,25 @@ namespace netlist
|
||||
|
||||
/// \brief constructor
|
||||
///
|
||||
/// @param dev core_devict_t object owning the terminal
|
||||
/// @param aname name of this terminal
|
||||
/// @param otherterm pointer to the sibling terminal
|
||||
terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm, nldelegate delegate);
|
||||
/// \param dev object owning the terminal
|
||||
/// \param aname name of this terminal
|
||||
/// \param other_terminal pointer to the sibling terminal
|
||||
terminal_t(core_device_t &dev, const pstring &aname, terminal_t *other_terminal, nldelegate delegate);
|
||||
|
||||
terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm,
|
||||
terminal_t(core_device_t &dev, const pstring &aname, terminal_t *other_terminal,
|
||||
const std::array<terminal_t *, 2> &splitterterms, nldelegate delegate);
|
||||
|
||||
/// \brief Returns voltage of connected net
|
||||
///
|
||||
/// @return voltage of net this terminal is connected to
|
||||
/// \return voltage of net this terminal is connected to
|
||||
nl_fptype operator ()() const noexcept
|
||||
{
|
||||
return net().Q_Analog();
|
||||
}
|
||||
|
||||
/// @brief sets conductivity value of this terminal
|
||||
/// \brief sets conductivity value of this terminal
|
||||
///
|
||||
/// @param G Conductivity
|
||||
/// \param G Conductivity
|
||||
void set_conductivity(nl_fptype G) const noexcept
|
||||
{
|
||||
set_go_gt_I(-G, G, nlconst::zero());
|
||||
|
@ -110,7 +110,7 @@ namespace netlist::detail {
|
||||
private:
|
||||
};
|
||||
|
||||
/// \brief Base class for all objects bejng owned by a netlist
|
||||
/// \brief Base class for all objects being owned by a netlist
|
||||
///
|
||||
/// The object provides adds \ref netlist_state_t and \ref netlist_t
|
||||
/// accessors.
|
||||
|
@ -33,7 +33,7 @@ class NETLIB_NAME(name) : public delegator_t<device_t>
|
||||
|
||||
/// \brief Start a derived netlist device class.
|
||||
///
|
||||
/// Used to define a derived device class based on plcass.
|
||||
/// Used to define a derived device class based on `plcass`.
|
||||
/// The simplest device without inputs or outputs would look like this:
|
||||
///
|
||||
/// NETLIB_OBJECT_DERIVED(some_object, parent_object)
|
||||
|
@ -24,7 +24,7 @@
|
||||
namespace netlist::devices
|
||||
{
|
||||
// -----------------------------------------------------------------------------
|
||||
// mainclock
|
||||
// main clock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
NETLIB_OBJECT(mainclock)
|
||||
@ -112,7 +112,7 @@ namespace netlist::devices
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// netlistparams
|
||||
// netlist parameters
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
NETLIB_OBJECT(netlistparams)
|
||||
|
@ -72,13 +72,13 @@ namespace netlist
|
||||
|
||||
// FIXME: force late type resolution
|
||||
template <typename X = devices::nld_solver>
|
||||
nl_fptype gmin([[maybe_unused]] X *solv = nullptr) const noexcept
|
||||
nl_fptype gmin([[maybe_unused]] X *solver = nullptr) const noexcept
|
||||
{
|
||||
return static_cast<X *>(m_solver)->gmin();
|
||||
}
|
||||
|
||||
netlist_state_t &nlstate() noexcept { return m_state; }
|
||||
const netlist_state_t &nlstate() const noexcept { return m_state; }
|
||||
netlist_state_t &nl_state() noexcept { return m_state; }
|
||||
const netlist_state_t &nl_state() const noexcept { return m_state; }
|
||||
|
||||
log_type & log() noexcept { return m_state.log(); }
|
||||
const log_type &log() const noexcept { return m_state.log(); }
|
||||
@ -99,7 +99,7 @@ namespace netlist
|
||||
// mostly rw
|
||||
//PALIGNAS(16)
|
||||
netlist_time_ext m_time;
|
||||
devices::nld_mainclock * m_mainclock;
|
||||
devices::nld_mainclock * m_main_clock;
|
||||
|
||||
//PALIGNAS_CACHELINE()
|
||||
//PALIGNAS(16)
|
||||
|
@ -34,30 +34,30 @@ namespace netlist
|
||||
virtual device_arena::unique_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name,
|
||||
const logic_input_t *proxied) const = 0;
|
||||
|
||||
nl_fptype low_thresh_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_low_thresh_PCNT; }
|
||||
nl_fptype high_thresh_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_high_thresh_PCNT; }
|
||||
nl_fptype low_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_low_threshold_PCNT; }
|
||||
nl_fptype high_threshold_V(nl_fptype VN, nl_fptype VP) const noexcept{ return VN + (VP - VN) * m_high_threshold_PCNT; }
|
||||
nl_fptype low_offset_V() const noexcept{ return m_low_VO; }
|
||||
nl_fptype high_offset_V() const noexcept{ return m_high_VO; }
|
||||
nl_fptype R_low() const noexcept{ return m_R_low; }
|
||||
nl_fptype R_high() const noexcept{ return m_R_high; }
|
||||
|
||||
bool is_above_high_thresh_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept
|
||||
{ return V > high_thresh_V(VN, VP); }
|
||||
bool is_above_high_threshold_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept
|
||||
{ return V > high_threshold_V(VN, VP); }
|
||||
|
||||
bool is_below_low_thresh_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept
|
||||
{ return V < low_thresh_V(VN, VP); }
|
||||
bool is_below_low_threshold_V(nl_fptype V, nl_fptype VN, nl_fptype VP) const noexcept
|
||||
{ return V < low_threshold_V(VN, VP); }
|
||||
|
||||
pstring vcc_pin() const { return pstring(m_vcc); }
|
||||
pstring gnd_pin() const { return pstring(m_gnd); }
|
||||
|
||||
nl_fptype m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled
|
||||
nl_fptype m_high_thresh_PCNT; //!< high input threshhold offset. If the input voltage is above the value times supply voltage, a "0" input is signalled
|
||||
nl_fptype m_low_VO; //!< low output voltage offset. This voltage is output if the ouput is "0"
|
||||
nl_fptype m_high_VO; //!< high output voltage offset. The supply voltage minus this offset is output if the ouput is "1"
|
||||
nl_fptype m_R_low; //!< low output resistance. Value of series resistor used for low output
|
||||
nl_fptype m_R_high; //!< high output resistance. Value of series resistor used for high output
|
||||
const char *m_vcc; //!< default power pin name for positive supply
|
||||
const char *m_gnd; //!< default power pin name for negative supply
|
||||
nl_fptype m_low_threshold_PCNT; //!< low input threshold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled
|
||||
nl_fptype m_high_threshold_PCNT; //!< high input threshold offset. If the input voltage is above the value times supply voltage, a "0" input is signalled
|
||||
nl_fptype m_low_VO; //!< low output voltage offset. This voltage is output if the ouput is "0"
|
||||
nl_fptype m_high_VO; //!< high output voltage offset. The supply voltage minus this offset is output if the ouput is "1"
|
||||
nl_fptype m_R_low; //!< low output resistance. Value of series resistor used for low output
|
||||
nl_fptype m_R_high; //!< high output resistance. Value of series resistor used for high output
|
||||
const char *m_vcc; //!< default power pin name for positive supply
|
||||
const char *m_gnd; //!< default power pin name for negative supply
|
||||
};
|
||||
|
||||
/// \brief Base class for devices, terminals, outputs and inputs which support
|
||||
|
@ -193,7 +193,7 @@ namespace netlist
|
||||
nlparse_t &parser();
|
||||
const nlparse_t &parser() const;
|
||||
|
||||
// FIXME: make a postload member and include code there
|
||||
// FIXME: make a post load member and include code there
|
||||
void rebuild_lists(); // must be called after post_load !
|
||||
|
||||
static void compile_defines(std::vector<std::pair<pstring, pstring>> &defs);
|
||||
|
@ -41,7 +41,7 @@ namespace netlist
|
||||
DELIVERED
|
||||
};
|
||||
|
||||
net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *railterminal = nullptr);
|
||||
net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *rail_terminal = nullptr);
|
||||
|
||||
PCOPYASSIGNMOVE(net_t, delete)
|
||||
|
||||
@ -136,8 +136,8 @@ namespace netlist
|
||||
constexpr const netlist_time_ext &next_scheduled_time() const noexcept { return m_next_scheduled_time; }
|
||||
void set_next_scheduled_time(netlist_time_ext ntime) noexcept { m_next_scheduled_time = ntime; }
|
||||
|
||||
bool is_rail_net() const noexcept { return !(m_railterminal == nullptr); }
|
||||
core_terminal_t & railterminal() const noexcept { return *m_railterminal; }
|
||||
bool is_rail_net() const noexcept { return !(m_rail_terminal == nullptr); }
|
||||
core_terminal_t & rail_terminal() const noexcept { return *m_rail_terminal; }
|
||||
|
||||
void add_to_active_list(core_terminal_t &term) noexcept
|
||||
{
|
||||
@ -149,7 +149,7 @@ namespace netlist
|
||||
else
|
||||
{
|
||||
m_list_active.push_front(&term);
|
||||
railterminal().device().do_inc_active();
|
||||
rail_terminal().device().do_inc_active();
|
||||
if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE)
|
||||
{
|
||||
#if (AVOID_NOOP_QUEUE_PUSHES)
|
||||
@ -187,7 +187,7 @@ namespace netlist
|
||||
m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE;
|
||||
}
|
||||
#endif
|
||||
railterminal().device().do_dec_active();
|
||||
rail_terminal().device().do_dec_active();
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ namespace netlist
|
||||
plib::linkedlist_t<core_terminal_t> m_list_active;
|
||||
state_var<netlist_time_ext> m_next_scheduled_time;
|
||||
|
||||
core_terminal_t * m_railterminal;
|
||||
core_terminal_t * m_rail_terminal;
|
||||
//std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
|
||||
|
||||
};
|
||||
@ -271,7 +271,7 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
|
||||
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr);
|
||||
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal = nullptr);
|
||||
|
||||
void reset() noexcept override;
|
||||
|
||||
@ -298,7 +298,7 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
|
||||
logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr);
|
||||
logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal = nullptr);
|
||||
|
||||
using detail::net_t::Q;
|
||||
using detail::net_t::initial;
|
||||
|
@ -161,7 +161,7 @@ namespace netlist
|
||||
return (ret != m_connected_terminals.end()) ? &ret->second : nullptr;
|
||||
}
|
||||
|
||||
// get family -> truthtable
|
||||
// get family -> truth table
|
||||
const logic_family_desc_t *family_from_model(const pstring &model);
|
||||
|
||||
param_ref_t find_param(const pstring ¶m_in) const;
|
||||
@ -243,7 +243,7 @@ namespace netlist
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Specific netlist psource_t implementations
|
||||
// Specific netlist `psource_t` implementations
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class source_netlist_t : public plib::psource_t
|
||||
|
@ -17,6 +17,7 @@ namespace netlist
|
||||
/// Use the state_var template to define a variable whose value is saved.
|
||||
/// Within a device definition use
|
||||
///
|
||||
/// ```
|
||||
/// NETLIB_OBJECT(abc)
|
||||
/// {
|
||||
/// NETLIB_CONSTRUCTOR(abc)
|
||||
@ -24,6 +25,8 @@ namespace netlist
|
||||
/// ...
|
||||
/// state_var<unsigned> m_var;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
template <typename T>
|
||||
struct state_var
|
||||
{
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "../nl_setup.h"
|
||||
|
||||
#ifdef RES_R
|
||||
#warning "Do not include rescap.h in a netlist environment"
|
||||
#warning "Do not include `rescap.h` in a netlist environment"
|
||||
#endif
|
||||
#ifndef RES_R
|
||||
#define RES_R(res) (res)
|
||||
|
@ -250,7 +250,7 @@ namespace netlist::devices {
|
||||
{
|
||||
return ((in[0]() ^ 1) | (in[1]() ^ 1)) & in[2](); // (~A1 | ~A2) & B
|
||||
}
|
||||
template<typename T> static constexpr netlist_sig_t clear( [[maybe_unused]] const T &in) { return 1; }
|
||||
template<typename T> static constexpr netlist_sig_t clear([[maybe_unused]] const T &in) { return 1; }
|
||||
};
|
||||
|
||||
struct desc_9602 : public desc_74123
|
||||
|
@ -48,7 +48,7 @@ namespace netlist::devices {
|
||||
|
||||
// FIXME: timing is not 100% accurate, Strobe and Select inputs have a
|
||||
// slightly longer timing .
|
||||
// FIXME: Truthtable candidate
|
||||
// FIXME: Truth table candidate
|
||||
|
||||
NETLIB_OBJECT(74153)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* nld_7485.cpp
|
||||
*
|
||||
* FIXME: Truthtable candidate
|
||||
* FIXME: Truth table candidate
|
||||
*
|
||||
* DM7485: 4-bit Magnitude Comparators
|
||||
*
|
||||
|
@ -151,7 +151,7 @@ namespace netlist::devices {
|
||||
~NETLIB_NAME(wav)();
|
||||
analog_input_t m_I;
|
||||
private:
|
||||
// FIXME: rewrite sound/wavwrite.h to be an object ...
|
||||
// FIXME: rewrite `sound/wavwrite.h` to be an object ...
|
||||
void *m_file;
|
||||
);
|
||||
#endif
|
||||
@ -160,7 +160,7 @@ namespace netlist::devices {
|
||||
|
||||
|
||||
// FIXME: Implement wav later, this must be clock triggered device where the input to be written
|
||||
// is on a subdevice ..
|
||||
// is on a sub device ..
|
||||
#if 0
|
||||
NETLIB_START(wav)
|
||||
{
|
||||
|
@ -93,9 +93,9 @@ namespace netlist::devices {
|
||||
const auto vn(m_tn->net().Q_Analog());
|
||||
const auto vp(m_tp->net().Q_Analog());
|
||||
|
||||
if (logic_family()->is_above_high_thresh_V(v, vn, vp))
|
||||
if (logic_family()->is_above_high_threshold_V(v, vn, vp))
|
||||
out().push(1, netlist_time::quantum());
|
||||
else if (logic_family()->is_below_low_thresh_V(v, vn, vp))
|
||||
else if (logic_family()->is_below_low_threshold_V(v, vn, vp))
|
||||
out().push(0, netlist_time::quantum());
|
||||
else
|
||||
{
|
||||
|
@ -1,16 +1,18 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nlid_proxy.h
|
||||
*
|
||||
* netlist proxy devices
|
||||
*
|
||||
* This file contains internal headers
|
||||
*/
|
||||
|
||||
#ifndef NLID_PROXY_H_
|
||||
#define NLID_PROXY_H_
|
||||
|
||||
///
|
||||
/// \file nlid_proxy.h
|
||||
///
|
||||
/// netlist proxy devices
|
||||
///
|
||||
/// This file contains internal headers
|
||||
///
|
||||
|
||||
|
||||
#include "analog/nlid_twoterm.h"
|
||||
#include "nl_base.h"
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace netlist::devices {
|
||||
#endif
|
||||
}
|
||||
for (auto &q : m_Q)
|
||||
if (q.has_net() && !exec().nlstate().core_terms(q.net()).empty())
|
||||
if (q.has_net() && !exec().nl_state().core_terms(q.net()).empty())
|
||||
active_outputs++;
|
||||
set_active_outputs(active_outputs);
|
||||
}
|
||||
@ -278,7 +278,7 @@ namespace netlist::devices {
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Truthtable parsing ....
|
||||
// Truth table parsing ....
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
using tt_bitset = pbitset<std::uint_least64_t>;
|
||||
@ -366,7 +366,7 @@ namespace netlist::devices {
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Truthtable class ....
|
||||
// Truth table class ....
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<std::size_t m_NI, std::size_t m_NO>
|
||||
@ -378,7 +378,7 @@ namespace netlist::devices {
|
||||
// checks
|
||||
nl_assert_always(io.size() == 2, "too many '|'");
|
||||
std::vector<pstring> inout(plib::psplit(io[0], ','));
|
||||
nl_assert_always(inout.size() == m_num_bits, "bitcount wrong");
|
||||
nl_assert_always(inout.size() == m_num_bits, "bit count wrong");
|
||||
std::vector<pstring> outputs(plib::psplit(io[1], ','));
|
||||
nl_assert_always(outputs.size() == m_NO, "output count wrong");
|
||||
|
||||
@ -393,18 +393,18 @@ namespace netlist::devices {
|
||||
{
|
||||
inout[i] = plib::trim(inout[i]);
|
||||
}
|
||||
if (0 < m_NI) m_I.emplace(0, *this, inout[0]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<0>, this));
|
||||
if (1 < m_NI) m_I.emplace(1, *this, inout[1]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<1>, this));
|
||||
if (2 < m_NI) m_I.emplace(2, *this, inout[2]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<2>, this));
|
||||
if (3 < m_NI) m_I.emplace(3, *this, inout[3]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<3>, this));
|
||||
if (4 < m_NI) m_I.emplace(4, *this, inout[4]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<4>, this));
|
||||
if (5 < m_NI) m_I.emplace(5, *this, inout[5]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<5>, this));
|
||||
if (6 < m_NI) m_I.emplace(6, *this, inout[6]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<6>, this));
|
||||
if (7 < m_NI) m_I.emplace(7, *this, inout[7]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<7>, this));
|
||||
if (8 < m_NI) m_I.emplace(8, *this, inout[8]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<8>, this));
|
||||
if (9 < m_NI) m_I.emplace(9, *this, inout[9]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<9>, this));
|
||||
if (10 < m_NI) m_I.emplace(10, *this, inout[10]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<10>, this));
|
||||
if (11 < m_NI) m_I.emplace(11, *this, inout[11]); //, nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<11>, this));
|
||||
if (0 < m_NI) m_I.emplace(0, *this, inout[0]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<0>, this));
|
||||
if (1 < m_NI) m_I.emplace(1, *this, inout[1]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<1>, this));
|
||||
if (2 < m_NI) m_I.emplace(2, *this, inout[2]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<2>, this));
|
||||
if (3 < m_NI) m_I.emplace(3, *this, inout[3]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<3>, this));
|
||||
if (4 < m_NI) m_I.emplace(4, *this, inout[4]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<4>, this));
|
||||
if (5 < m_NI) m_I.emplace(5, *this, inout[5]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<5>, this));
|
||||
if (6 < m_NI) m_I.emplace(6, *this, inout[6]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<6>, this));
|
||||
if (7 < m_NI) m_I.emplace(7, *this, inout[7]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<7>, this));
|
||||
if (8 < m_NI) m_I.emplace(8, *this, inout[8]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<8>, this));
|
||||
if (9 < m_NI) m_I.emplace(9, *this, inout[9]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<9>, this));
|
||||
if (10 < m_NI) m_I.emplace(10, *this, inout[10]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<10>, this));
|
||||
if (11 < m_NI) m_I.emplace(11, *this, inout[11]); //# nldelegate(&nld_truthtable_t<m_NI, m_NO>::update_N<11>, this));
|
||||
#endif
|
||||
for (std::size_t i=0; i < m_NO; i++)
|
||||
{
|
||||
@ -421,7 +421,7 @@ namespace netlist::devices {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Truthtable factory ....
|
||||
// Truth table factory ....
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<unsigned m_NI, unsigned m_NO>
|
||||
@ -512,7 +512,7 @@ namespace netlist::devices {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// parseline
|
||||
// parse line
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
|
||||
@ -553,7 +553,7 @@ namespace netlist::devices {
|
||||
{
|
||||
// cutoff previous inputs and outputs for ignore
|
||||
if (m_out_state[nstate] != m_out_state.mask() && m_out_state[nstate] != val)
|
||||
throw nl_exception(plib::pfmt("Error in truthtable: State {1:04} already set, {2} != {3}\n")
|
||||
throw nl_exception(plib::pfmt("Error in truth table: State {1:04} already set, {2} != {3}\n")
|
||||
.x(nstate.as_uint())(m_out_state[nstate])(val) );
|
||||
m_out_state.set(nstate, val);
|
||||
for (std::size_t j=0; j<m_NO; j++)
|
||||
@ -593,7 +593,7 @@ namespace netlist::devices {
|
||||
std::vector<uint_least8_t> tindex;
|
||||
|
||||
//
|
||||
// FIXME: evaluation of outputs should be done in parseline to
|
||||
// FIXME: evaluation of outputs should be done in parse_line to
|
||||
// enable the use of inputs for output values, i.e. "I1" or "~I1"
|
||||
// in addition to "0" and "1".
|
||||
|
||||
@ -649,7 +649,7 @@ namespace netlist::devices {
|
||||
for (size_t i=0; i<m_size; i++)
|
||||
{
|
||||
if (m_out_state[i] == m_out_state.mask())
|
||||
throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
|
||||
throw nl_exception(plib::pfmt("truth table: found element not set {1}\n").x(i) );
|
||||
m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO));
|
||||
}
|
||||
}
|
||||
@ -695,7 +695,7 @@ namespace netlist::factory {
|
||||
ENTRY(11, props);
|
||||
ENTRY(12, props);
|
||||
default:
|
||||
pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
|
||||
pstring msg = plib::pfmt("unable to create truth table<{1},{2}>")(desc.ni)(desc.no);
|
||||
nl_assert_always(false, putf8string(msg).c_str());
|
||||
}
|
||||
ret->m_desc = desc.desc;
|
||||
|
@ -1,9 +1,10 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nld_truthtable.h
|
||||
*
|
||||
*/
|
||||
|
||||
///
|
||||
/// \file nld_truthtable.h
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef NLID_TRUTHTABLE_H_
|
||||
#define NLID_TRUTHTABLE_H_
|
||||
|
@ -1,7 +1,7 @@
|
||||
// license:CC0
|
||||
// copyright-holders:Couriersud
|
||||
|
||||
// File programmatically created Fri May 6 11:19:43 2022
|
||||
// File programmatically created Sun May 22 09:38:02 2022
|
||||
|
||||
#include "devices/net_lib.h"
|
||||
|
||||
|
@ -52,7 +52,7 @@ NETLIST_START(ICL8038_DIP)
|
||||
|
||||
ALIAS(11, VI.ON) // GND
|
||||
ALIAS(9, V_SQR.OP) // Square out
|
||||
ALIAS(3, VO.OP) // Triag out
|
||||
ALIAS(3, VO.OP) // Triangle out
|
||||
ALIAS(8, VI.IP) // VC
|
||||
ALIAS(4, CI1.IP) // R1
|
||||
ALIAS(5, CI2.IP) // R2
|
||||
|
@ -1,5 +1,9 @@
|
||||
// license:CC0
|
||||
// copyright-holders:Couriersud
|
||||
|
||||
// Specific technical terms
|
||||
// spell-checker: words Iave, Vishay, Zdiodes, Icrating, Vceo
|
||||
|
||||
#include "devices/net_lib.h"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
@ -648,7 +648,7 @@ NETLIST_END()
|
||||
//- Package: DIP
|
||||
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
|
||||
//- FunctionTable:
|
||||
//- pdf.datasheetcatalog.com/datasheets/185/109289_DS.pdf
|
||||
//- http://pdf.datasheetcatalog.com/datasheets/185/109289_DS.pdf
|
||||
//-
|
||||
static NETLIST_START(CD4071_DIP)
|
||||
CD4071_GATE(A)
|
||||
@ -727,7 +727,7 @@ NETLIST_END()
|
||||
//- Package: DIP
|
||||
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
|
||||
//- FunctionTable:
|
||||
//- pdf.datasheetcatalog.com/datasheets/185/109289_DS.pdf
|
||||
//- http://pdf.datasheetcatalog.com/datasheets/185/109289_DS.pdf
|
||||
//-
|
||||
static NETLIST_START(CD4081_DIP)
|
||||
CD4081_GATE(A)
|
||||
|
@ -627,7 +627,7 @@ NETLIST_START(opamp_lib)
|
||||
NET_MODEL("LM747 OPAMP(TYPE=3 VLH=1.0 VLL=1.0 FPF=5 UGF=1000k SLEW=0.5M RI=2000k RO=50 DAB=0.0017)")
|
||||
NET_MODEL("LM747A OPAMP(TYPE=3 VLH=2.0 VLL=2.0 FPF=5 UGF=1000k SLEW=0.7M RI=6000k RO=50 DAB=0.0015)")
|
||||
NET_MODEL("LM748 OPAMP(TYPE=3 VLH=2.0 VLL=2.0 FPF=5 UGF=800k SLEW=0.7M RI=800k RO=60 DAB=0.001)")
|
||||
// TI and Motorola Datasheets differ - below are Motorola values, SLEW is average of LH and HL
|
||||
// TI and Motorola datasheets differ - below are Motorola values, SLEW is average of LH and HL
|
||||
NET_MODEL("LM3900 OPAMP(TYPE=3 VLH=1.0 VLL=0.03 FPF=2k UGF=4M SLEW=10M RI=10M RO=2k DAB=0.0015)")
|
||||
|
||||
NET_MODEL("AN6551 OPAMP(TYPE=3 VLH=1.0 VLL=0.03 FPF=20 UGF=2M SLEW=1M RI=10M RO=200 DAB=0.0015)")
|
||||
|
@ -939,7 +939,7 @@ NETLIST_END()
|
||||
//- Title: DM54LS73A/DM74LS73A Dual Negative-Edge-Triggered Master-Slave J-K Flip-Flops with Clear and Complementary Outputs
|
||||
//- Pinalias: CLK1,CLR1,K1,VCC,CLK2,CLR2,J2,QQ2,Q2,K2,GND,Q1,QQ1,J1
|
||||
//- Package: DIP
|
||||
//- NamingConvention: Naming conventions follow National Semicouductor datasheet
|
||||
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
|
||||
//- FunctionTable:
|
||||
//- http://pdf.datasheetcatalog.com/datasheet/nationalsemiconductor/DS006372.PDF
|
||||
//-
|
||||
@ -1686,7 +1686,7 @@ NETLIST_END()
|
||||
//- Package: DIP
|
||||
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
|
||||
//- FunctionTable:
|
||||
//- pdf.datasheetcatalog.com/datasheets/166/375388_DS.pdf
|
||||
//- http://pdf.datasheetcatalog.com/datasheets/166/375388_DS.pdf
|
||||
//-
|
||||
//- +---+-------+-------------+
|
||||
//- | E | A0 A1 | O0 O1 O2 O3 |
|
||||
|
@ -73,12 +73,12 @@ namespace netlist
|
||||
|
||||
netlist_state_t & detail::netlist_object_t::state() noexcept
|
||||
{
|
||||
return m_netlist.nlstate();
|
||||
return m_netlist.nl_state();
|
||||
}
|
||||
|
||||
const netlist_state_t & detail::netlist_object_t::state() const noexcept
|
||||
{
|
||||
return m_netlist.nlstate();
|
||||
return m_netlist.nl_state();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -89,7 +89,7 @@ namespace netlist
|
||||
: m_state(state)
|
||||
, m_solver(nullptr)
|
||||
, m_time(netlist_time_ext::zero())
|
||||
, m_mainclock(nullptr)
|
||||
, m_main_clock(nullptr)
|
||||
, m_use_stats(false)
|
||||
, m_queue(config::max_queue_size::value,
|
||||
detail::queue_t::id_delegate(&netlist_state_t :: find_net_id, &state),
|
||||
@ -276,7 +276,7 @@ namespace netlist
|
||||
void netlist_t::reset()
|
||||
{
|
||||
log().debug("Searching for main clock\n");
|
||||
m_mainclock = m_state.get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
|
||||
m_main_clock = m_state.get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
|
||||
|
||||
log().debug("Searching for solver\n");
|
||||
m_solver = m_state.get_single_device<devices::NETLIB_NAME(solver)>("solver");
|
||||
@ -284,8 +284,8 @@ namespace netlist
|
||||
// Don't reset time
|
||||
//m_time = netlist_time_ext::zero();
|
||||
m_queue.clear();
|
||||
if (m_mainclock != nullptr)
|
||||
m_mainclock->m_Q.net().set_next_scheduled_time(m_time);
|
||||
if (m_main_clock != nullptr)
|
||||
m_main_clock->m_Q.net().set_next_scheduled_time(m_time);
|
||||
//if (m_solver != nullptr)
|
||||
// m_solver->reset();
|
||||
|
||||
@ -376,8 +376,8 @@ namespace netlist
|
||||
netlist_state_t::stats_info si{m_queue, m_stat_mainloop, m_perf_out_processed};
|
||||
m_state.print_stats(si);
|
||||
}
|
||||
log().verbose("Current pool memory allocated: {1:12} kB", nlstate().pool().cur_alloc() >> 10);
|
||||
log().verbose("Maximum pool memory allocated: {1:12} kB", nlstate().pool().max_alloc() >> 10);
|
||||
log().verbose("Current pool memory allocated: {1:12} kB", nl_state().pool().cur_alloc() >> 10);
|
||||
log().verbose("Maximum pool memory allocated: {1:12} kB", nl_state().pool().max_alloc() >> 10);
|
||||
}
|
||||
|
||||
void netlist_state_t::print_stats(stats_info &si) const
|
||||
@ -602,13 +602,13 @@ namespace netlist
|
||||
// net_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *railterminal)
|
||||
detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *rail_terminal)
|
||||
: netlist_object_t(nl.exec(), aname)
|
||||
, m_new_Q(*this, "m_new_Q", netlist_sig_t(0))
|
||||
, m_cur_Q (*this, "m_cur_Q", netlist_sig_t(0))
|
||||
, m_in_queue(*this, "m_in_queue", queue_status::DELIVERED)
|
||||
, m_next_scheduled_time(*this, "m_time", netlist_time_ext::zero())
|
||||
, m_railterminal(railterminal)
|
||||
, m_rail_terminal(rail_terminal)
|
||||
{
|
||||
props::add(this, props::value_type());
|
||||
}
|
||||
@ -618,7 +618,7 @@ namespace netlist
|
||||
// rebuild m_list
|
||||
|
||||
m_list_active.clear();
|
||||
for (auto & term : exec().nlstate().core_terms(*this))
|
||||
for (auto & term : exec().nl_state().core_terms(*this))
|
||||
if (term->terminal_state() != logic_t::STATE_INP_PASSIVE)
|
||||
{
|
||||
m_list_active.push_back(term);
|
||||
@ -643,7 +643,7 @@ namespace netlist
|
||||
// rebuild m_list and reset terminals to active or analog out state
|
||||
|
||||
m_list_active.clear();
|
||||
for (core_terminal_t *ct : exec().nlstate().core_terms(*this))
|
||||
for (core_terminal_t *ct : exec().nl_state().core_terms(*this))
|
||||
{
|
||||
ct->reset();
|
||||
if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE)
|
||||
@ -656,8 +656,8 @@ namespace netlist
|
||||
// logic_net_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal)
|
||||
: net_t(nl, aname, railterminal)
|
||||
logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal)
|
||||
: net_t(nl, aname, rail_terminal)
|
||||
{
|
||||
}
|
||||
|
||||
@ -665,8 +665,8 @@ namespace netlist
|
||||
// analog_net_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal)
|
||||
: net_t(nl, aname, railterminal)
|
||||
analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *rail_terminal)
|
||||
: net_t(nl, aname, rail_terminal)
|
||||
, m_cur_Analog(*this, "m_cur_Analog", nlconst::zero())
|
||||
, m_solver(nullptr)
|
||||
{
|
||||
@ -704,20 +704,20 @@ namespace netlist
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
terminal_t::terminal_t(core_device_t &dev, const pstring &aname,
|
||||
terminal_t *otherterm, nldelegate delegate)
|
||||
: terminal_t(dev, aname, otherterm, { nullptr, nullptr }, delegate)
|
||||
terminal_t *other_terminal, nldelegate delegate)
|
||||
: terminal_t(dev, aname, other_terminal, { nullptr, nullptr }, delegate)
|
||||
{
|
||||
}
|
||||
|
||||
terminal_t::terminal_t(core_device_t &dev, const pstring &aname,
|
||||
terminal_t *otherterm, const std::array<terminal_t *, 2> &splitterterms,
|
||||
terminal_t *other_terminal, const std::array<terminal_t *, 2> &splitterterms,
|
||||
nldelegate delegate)
|
||||
: analog_t(dev, aname, STATE_BIDIR, delegate)
|
||||
, m_Idr(nullptr)
|
||||
, m_go(nullptr)
|
||||
, m_gt(nullptr)
|
||||
{
|
||||
state().setup().register_term(*this, otherterm, splitterterms);
|
||||
state().setup().register_term(*this, other_terminal, splitterterms);
|
||||
}
|
||||
|
||||
void terminal_t::set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false)
|
||||
@ -999,7 +999,7 @@ namespace netlist
|
||||
|
||||
qpush(stop, nullptr);
|
||||
|
||||
if (m_mainclock == nullptr)
|
||||
if (m_main_clock == nullptr)
|
||||
{
|
||||
m_time = m_queue.top().exec_time();
|
||||
detail::net_t *obj(m_queue.top().object());
|
||||
@ -1018,8 +1018,8 @@ namespace netlist
|
||||
}
|
||||
else
|
||||
{
|
||||
logic_net_t &mc_net(m_mainclock->m_Q.net());
|
||||
const netlist_time inc(m_mainclock->m_inc);
|
||||
logic_net_t &mc_net(m_main_clock->m_Q.net());
|
||||
const netlist_time inc(m_main_clock->m_inc);
|
||||
netlist_time_ext mc_time(mc_net.next_scheduled_time());
|
||||
|
||||
do
|
||||
|
@ -7,6 +7,9 @@
|
||||
#ifndef NLCONFIG_H_
|
||||
#define NLCONFIG_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Woodbury
|
||||
|
||||
#include "plib/pconfig.h"
|
||||
#include "plib/pexception.h"
|
||||
|
||||
|
@ -971,7 +971,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
|
||||
if (t1.has_net())
|
||||
{
|
||||
if (t1.net().is_rail_net())
|
||||
ret = connect(t2, t1.net().railterminal());
|
||||
ret = connect(t2, t1.net().rail_terminal());
|
||||
if (!ret)
|
||||
{
|
||||
for (auto & t : nlstate().core_terms(t1.net()))
|
||||
@ -986,7 +986,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
|
||||
if (!ret && t2.has_net())
|
||||
{
|
||||
if (t2.net().is_rail_net())
|
||||
ret = connect(t1, t2.net().railterminal());
|
||||
ret = connect(t1, t2.net().rail_terminal());
|
||||
if (!ret)
|
||||
{
|
||||
for (auto & t : nlstate().core_terms(t2.net()))
|
||||
@ -1491,8 +1491,8 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
|
||||
|
||||
auto ret = plib::make_unique<logic_family_std_proxy_t, host_arena>(ft);
|
||||
|
||||
ret->m_low_thresh_PCNT = modv.m_IVL();
|
||||
ret->m_high_thresh_PCNT = modv.m_IVH();
|
||||
ret->m_low_threshold_PCNT = modv.m_IVL();
|
||||
ret->m_high_threshold_PCNT = modv.m_IVH();
|
||||
ret->m_low_VO = modv.m_OVL();
|
||||
ret->m_high_VO = modv.m_OVH();
|
||||
ret->m_R_low = modv.m_ORL();
|
||||
@ -1711,14 +1711,14 @@ plib::istream_uptr source_string_t::stream([[maybe_unused]] const pstring &name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
plib::istream_uptr source_mem_t::stream( [[maybe_unused]] const pstring &name)
|
||||
plib::istream_uptr source_mem_t::stream([[maybe_unused]] const pstring &name)
|
||||
{
|
||||
plib::istream_uptr ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary), name);
|
||||
ret->imbue(std::locale::classic());
|
||||
return ret;
|
||||
}
|
||||
|
||||
plib::istream_uptr source_file_t::stream( [[maybe_unused]] const pstring &name)
|
||||
plib::istream_uptr source_file_t::stream([[maybe_unused]] const pstring &name)
|
||||
{
|
||||
auto f = std::make_unique<plib::ifstream>(plib::filesystem::u8path(m_filename));
|
||||
if (f->is_open())
|
||||
@ -1729,7 +1729,7 @@ plib::istream_uptr source_file_t::stream( [[maybe_unused]] const pstring &name)
|
||||
return plib::istream_uptr();
|
||||
}
|
||||
|
||||
plib::istream_uptr source_pattern_t::stream( [[maybe_unused]] const pstring &name)
|
||||
plib::istream_uptr source_pattern_t::stream([[maybe_unused]] const pstring &name)
|
||||
{
|
||||
pstring filename = plib::pfmt(m_pattern)(m_force_lowercase ? plib::lcase(name) : name);
|
||||
auto f = std::make_unique<plib::ifstream>(plib::filesystem::u8path(filename));
|
||||
@ -1753,7 +1753,7 @@ bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
|
||||
return false;
|
||||
}
|
||||
|
||||
plib::istream_uptr source_proc_t::stream( [[maybe_unused]] const pstring &name)
|
||||
plib::istream_uptr source_proc_t::stream([[maybe_unused]] const pstring &name)
|
||||
{
|
||||
return plib::istream_uptr();
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ namespace netlist
|
||||
// Types needed by various includes
|
||||
//============================================================
|
||||
|
||||
/// \brief Timestep type.
|
||||
/// \brief Time step type.
|
||||
///
|
||||
/// May be either FORWARD or RESTORE
|
||||
///
|
||||
|
@ -4,6 +4,10 @@
|
||||
#ifndef PLIB_GMRES_H_
|
||||
#define PLIB_GMRES_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Burkardt, Saad, Yousef
|
||||
//
|
||||
|
||||
///
|
||||
/// \file gmres.h
|
||||
///
|
||||
@ -203,7 +207,7 @@ namespace plib
|
||||
plib::pmatrix_cr<FT, SIZE> m_mat;
|
||||
};
|
||||
|
||||
// FIXME: hardcoding RESTART to 20 becomes an issue on very large
|
||||
// FIXME: hard coding RESTART to 20 becomes an issue on very large
|
||||
// systems.
|
||||
|
||||
template <typename FT, int SIZE, int RESTARTMAX = 16>
|
||||
@ -270,7 +274,7 @@ namespace plib
|
||||
// ==> rho / accuracy = sqrt(y * y)
|
||||
//
|
||||
// This approach will approximate the iterative stop condition
|
||||
// based |xnew - xold| pretty precisely. But it is slow, or expressed
|
||||
// based `|xnew - xold|` pretty precisely. But it is slow, or expressed
|
||||
// differently: The invest doesn't pay off.
|
||||
//
|
||||
|
||||
@ -506,7 +510,7 @@ namespace plib
|
||||
}
|
||||
private:
|
||||
|
||||
//typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
|
||||
//#typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
|
||||
|
||||
plib::parray<float_type, SIZE> residual;
|
||||
plib::parray<float_type, SIZE> Ax;
|
||||
|
@ -40,7 +40,7 @@ dynlib::dynlib(const pstring &libname)
|
||||
// printf("library <%s> not found: %s\n", libname.c_str(), dlerror());
|
||||
}
|
||||
|
||||
dynlib::dynlib( [[maybe_unused]] const pstring &path, const pstring &libname)
|
||||
dynlib::dynlib([[maybe_unused]] const pstring &path, const pstring &libname)
|
||||
: m_lib(nullptr)
|
||||
{
|
||||
// FIXME: implement path search
|
||||
|
@ -45,7 +45,7 @@ namespace plib {
|
||||
{
|
||||
public:
|
||||
explicit dynlib(const pstring &libname);
|
||||
dynlib(/*[[maybe_unused]]*/ const pstring &path, const pstring &libname);
|
||||
dynlib(const pstring &path, const pstring &libname);
|
||||
|
||||
~dynlib() override;
|
||||
|
||||
|
@ -13,9 +13,10 @@
|
||||
namespace plib
|
||||
{
|
||||
|
||||
//============================================================
|
||||
// penum - strongly typed enumeration
|
||||
//============================================================
|
||||
///
|
||||
/// \brief strongly typed enumeration
|
||||
///
|
||||
///
|
||||
struct penum_base
|
||||
{
|
||||
protected:
|
||||
|
@ -118,8 +118,8 @@ namespace plib {
|
||||
|
||||
/// \brief cast to void *
|
||||
///
|
||||
/// The purpose here is to help identifiy casts to void in the code.
|
||||
/// These case usuallyindicate some wizard assumptioms which should be easily
|
||||
/// The purpose here is to help identify casts to void in the code.
|
||||
/// These case usually indicate some wizard assumptions which should be easily
|
||||
/// be easy to identify.
|
||||
template <typename T>
|
||||
constexpr void * void_ptr_cast(T *ptr) noexcept { return static_cast<void *>(ptr); }
|
||||
|
@ -39,7 +39,6 @@ namespace plib {
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
//uninitialised_array_t() noexcept = default;
|
||||
uninitialised_array() noexcept = default;
|
||||
|
||||
uninitialised_array(const uninitialised_array &) = default;
|
||||
|
@ -71,11 +71,6 @@ inline std::size_t get_max_threads() noexcept
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// pdynlib: dynamic loading of libraries ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
} // namespace plib::omp
|
||||
|
||||
#endif // PSTRING_H_
|
||||
|
@ -81,6 +81,7 @@ namespace plib {
|
||||
#include "ptypes.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef> // ptrdiff_t
|
||||
#include <cstdint> // uintptr_t
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@ -162,11 +163,31 @@ namespace plib {
|
||||
// extract the generic function and adjust the object pointer
|
||||
void convert_to_generic(generic_function &func, mfp_generic_class *&object) const;
|
||||
|
||||
// actual state
|
||||
/// \brief Byte offset into the vtable
|
||||
///
|
||||
/// On x86-64, the vtable contains pointers to code, and function pointers
|
||||
/// are pointers to code. To obtain a function pointer for a virtual
|
||||
/// member function, you fetch a pointer to code from the vtable.
|
||||
///
|
||||
/// On traditional PPC64, the vtable contains pointers to function
|
||||
/// descriptors, and function pointers are pointers to function descriptors.
|
||||
/// To obtain a function pointer for a virtual member function, you
|
||||
/// fetch a pointer to a function descriptor from the vtable.
|
||||
///
|
||||
/// On IA64, the vtable contains function descriptors, and function
|
||||
/// pointers are pointers to function descriptors. To obtain a
|
||||
/// function pointer for a virtual member function, you calculate
|
||||
/// the address of the function descriptor in the vtable.
|
||||
///
|
||||
/// Simply adding the byte offset to the vtable pointer creates a
|
||||
/// function pointer on IA64 because the vtable contains function
|
||||
/// descriptors; on most other targets, the vtable contains function
|
||||
/// pointers, so you need to fetch the function pointer after
|
||||
/// calculating its address in the vtable.
|
||||
///
|
||||
uintptr_t m_function; // first item can be one of two things:
|
||||
// if even, it's a pointer to the function
|
||||
// if even, it's a function pointer
|
||||
// if odd, it's the byte offset into the vtable
|
||||
// or a byte offset into the function descriptors on IA64
|
||||
ptrdiff_t m_this_delta; // delta to apply to the 'this' pointer
|
||||
};
|
||||
|
||||
@ -184,10 +205,10 @@ namespace plib {
|
||||
void convert_to_generic(generic_function &func, mfp_generic_class *&object) const;
|
||||
|
||||
// actual state
|
||||
uintptr_t m_function; // first item can pointer to the function or a byte offset into the vtable
|
||||
uintptr_t m_function; // first item can be a function pointer or a byte offset into the vtable
|
||||
ptrdiff_t m_this_delta; // delta to apply to the 'this' pointer after right shifting by one bit
|
||||
// m_function is the byte offset into the vtable
|
||||
// On IA64 it may also be a byte offset into the function descriptors
|
||||
// if even, m_function is a fuction pointer
|
||||
// if odd, m_function is the byte offset into the vtable
|
||||
};
|
||||
|
||||
template <>
|
||||
@ -394,6 +415,7 @@ namespace plib {
|
||||
/// is virtual, the vtable may not yet be fully constructed. In these cases
|
||||
/// the following class allows to construct the delegate later.
|
||||
///
|
||||
/// ```
|
||||
/// plib::late_pmfp<plib::pmfp<void, pstring>> a(&nld_7493::printer);
|
||||
/// // Store the a object somewhere
|
||||
///
|
||||
@ -401,7 +423,7 @@ namespace plib {
|
||||
///
|
||||
/// auto delegate_obj = a(this);
|
||||
/// delegate_obj(pstring("Hello World!"));
|
||||
///
|
||||
/// ```
|
||||
template<typename T>
|
||||
class late_pmfp
|
||||
{
|
||||
@ -472,8 +494,8 @@ namespace plib {
|
||||
{
|
||||
typename traits::template specific_member_function<O> pFunc;
|
||||
static_assert(sizeof(pFunc) >= sizeof(F), "size error");
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
//*reinterpret_cast<F *>(&pFunc) = *mftp;
|
||||
//# NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
//# *reinterpret_cast<F *>(&pFunc) = *mftp;
|
||||
reinterpret_copy(*mftp, pFunc);
|
||||
raw_type mfpo(pFunc);
|
||||
generic_function_storage rfunc(nullptr);
|
||||
|
@ -88,8 +88,7 @@ namespace plib {
|
||||
};
|
||||
|
||||
///
|
||||
///
|
||||
/// putf8reader_t digests linux & dos/windows text files
|
||||
/// \brief digests linux & dos/windows text files
|
||||
///
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
||||
class putf8_reader
|
||||
@ -201,9 +200,9 @@ private:
|
||||
std::unique_ptr<std::istream> m_strm;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// putf8writer_t: writer on top of ostream
|
||||
// -----------------------------------------------------------------------------
|
||||
///
|
||||
/// \brief writer on top of ostream
|
||||
///
|
||||
|
||||
class putf8_writer
|
||||
{
|
||||
@ -265,9 +264,9 @@ public:
|
||||
private:
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// pbinary_writer_t: writer on top of ostream
|
||||
// -----------------------------------------------------------------------------
|
||||
///
|
||||
/// \brief writer on top of ostream
|
||||
///
|
||||
|
||||
class pbinary_writer
|
||||
{
|
||||
|
@ -10,13 +10,13 @@
|
||||
/// google tests compatible (hopefully) test macros. This is work in progress!
|
||||
///
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||
|
@ -60,7 +60,7 @@ namespace plib
|
||||
}
|
||||
|
||||
template <typename O, typename T = std::enable_if_t<!ptime_le<ptime<O, RES>, ptime>::value, int>>
|
||||
constexpr explicit ptime(const ptime<O, RES> &rhs,[[maybe_unused]] T dummy = 0) noexcept
|
||||
constexpr explicit ptime(const ptime<O, RES> &rhs, [[maybe_unused]] T dummy = 0) noexcept
|
||||
: m_time(static_cast<TYPE>(rhs.m_time))
|
||||
{
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace plib
|
||||
};
|
||||
|
||||
// <sys/types.h> on ubuntu system may define major and minor as macros
|
||||
// That's why we use vmajor, .. here
|
||||
// That's why we use `vmajor`, .. here
|
||||
template <std::size_t MAJOR, std::size_t MINOR>
|
||||
struct typed_version
|
||||
{
|
||||
@ -159,7 +159,7 @@ namespace plib
|
||||
using version = typed_version<__clang_major__, __clang_minor__>;
|
||||
#elif defined(__GNUC__)
|
||||
using type = std::integral_constant<ci_compiler, ci_compiler::GCC>;
|
||||
using version = typed_version< __GNUC__, __GNUC_MINOR__ >;
|
||||
using version = typed_version<__GNUC__, __GNUC_MINOR__>;
|
||||
#elif defined(_MSC_VER)
|
||||
using type = std::integral_constant<ci_compiler, ci_compiler::MSC>;
|
||||
using version = typed_version<_MSC_VER / 100, _MSC_VER % 100>;
|
||||
@ -169,10 +169,10 @@ namespace plib
|
||||
#endif
|
||||
#if defined(_LIBCPP_VERSION)
|
||||
using cpp_stdlib = std::integral_constant<ci_cpp_stdlib, ci_cpp_stdlib::LIBCPP>;
|
||||
using cpp_stdlib_version = std::integral_constant<int, ((_LIBCPP_VERSION) / 1000) * 100 + ((_LIBCPP_VERSION) / 100) % 10>;
|
||||
using cpp_stdlib_version = typed_version<(_LIBCPP_VERSION) / 1000, ((_LIBCPP_VERSION) / 100) % 10>;
|
||||
#elif defined(__GLIBCXX__)
|
||||
using cpp_stdlib = std::integral_constant<ci_cpp_stdlib, ci_cpp_stdlib::LIBSTDCXX>;
|
||||
using cpp_stdlib_version = std::integral_constant<int, (_GLIBCXX_RELEASE) * 100>;
|
||||
using cpp_stdlib_version = typed_version<(_GLIBCXX_RELEASE), 0>;
|
||||
#else
|
||||
using cpp_stdlib = std::integral_constant<ci_cpp_stdlib, ci_cpp_stdlib::UNKNOWN>;
|
||||
using cpp_stdlib_version = std::integral_constant<int, 0>;
|
||||
@ -286,7 +286,7 @@ namespace plib
|
||||
|
||||
template<typename T> struct is_floating_point : public std::is_floating_point<T> { };
|
||||
|
||||
template< class T >
|
||||
template<class T>
|
||||
struct is_arithmetic : std::integral_constant<bool,
|
||||
plib::is_integral<T>::value || plib::is_floating_point<T>::value> {};
|
||||
|
||||
@ -350,7 +350,7 @@ namespace plib
|
||||
|
||||
/// \brief mark arguments as not used for compiler
|
||||
///
|
||||
/// @tparam Ts unsused parameters
|
||||
/// \tparam Ts unused parameters
|
||||
///
|
||||
template<typename... Ts>
|
||||
inline void unused_var(Ts&&...) noexcept {} // NOLINT(readability-named-parameter) // FIXME: remove unused var completely
|
||||
@ -377,7 +377,7 @@ namespace plib
|
||||
|
||||
/// \brief Test if type R has a stream operator << defined
|
||||
///
|
||||
/// has_ostram_operator<std::ostream, int>:: value should be true
|
||||
/// has_ostream_operator<std::ostream, int>:: value should be true
|
||||
///
|
||||
/// \tparam LEFT Stream type
|
||||
/// \tparam RIGHT Type to check for operator overload
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
|
||||
opt_grp3(*this, "Options for static command", "These options apply to static command."),
|
||||
opt_dir(*this, "d", "dir", "", "output directory for the generated files."),
|
||||
opt_out(*this, "o", "output", "", "single output file for the generated code.\nEither --dir or --output can be specificied"),
|
||||
opt_out(*this, "o", "output", "", "single output file for the generated code.\nEither --dir or --output can be specified"),
|
||||
|
||||
opt_grp4(*this, "Options for run command", "These options are only used by the run command."),
|
||||
opt_ttr (*this, "t", "time_to_run", 1, "time to run the emulation (seconds)"),
|
||||
|
@ -21,7 +21,7 @@
|
||||
// is a common agreement in serious recording applications while
|
||||
// still recording the file. So a playback application can determine that the
|
||||
// given file is still being recorded. As soon as the recording application
|
||||
// finishes the ongoing recording, it writes the correct values for RIFF lenth
|
||||
// finishes the ongoing recording, it writes the correct values for RIFF length
|
||||
// and data chunk length to the file.
|
||||
//
|
||||
// http://de.wikipedia.org/wiki/RIFF_WAVE
|
||||
@ -401,7 +401,7 @@ public:
|
||||
val = outsam * m_amp;
|
||||
} while (plib::abs(val) > 1.0);
|
||||
// FIXME: log this in state and provide on verbose output
|
||||
//printf("dynamp adjusted to %f at %f\n", m_amp, time);
|
||||
//printf("dynamic amplification adjusted to %f at %f\n", m_amp, time);
|
||||
}
|
||||
m_samples[chan] = val;
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
|
||||
// Names
|
||||
// spell-checker: words Raphson, Seidel
|
||||
//
|
||||
// Specific technical terms
|
||||
// spell-checker: words vsolver
|
||||
|
||||
#include "nld_solver.h"
|
||||
#include "core/setup.h"
|
||||
#include "nl_setup.h"
|
||||
@ -12,7 +18,7 @@ namespace netlist::solver
|
||||
|
||||
terms_for_net_t::terms_for_net_t(analog_net_t * net)
|
||||
: m_net(net)
|
||||
, m_railstart(0)
|
||||
, m_rail_start(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -144,27 +150,31 @@ namespace netlist::solver
|
||||
m_dynamic_funcs.emplace_back(nldelegate_dyn(&core_device_t::update_terminals, d));
|
||||
}
|
||||
|
||||
/// \brief Sort terminals
|
||||
///
|
||||
/// @param sort Sort algorithm to use.
|
||||
///
|
||||
/// Sort in descending order by number of connected matrix voltages.
|
||||
///The idea is, that for Gauss-Seidel algorithm the first voltage computed
|
||||
/// depends on the greatest number of previous voltages thus taking into
|
||||
/// account the maximum amount of information.
|
||||
///
|
||||
/// This actually improves performance on popeye slightly. Average
|
||||
/// GS computations reduce from 2.509 to 2.370
|
||||
///
|
||||
/// Smallest to largest : 2.613
|
||||
/// Unsorted : 2.509
|
||||
/// Largest to smallest : 2.370
|
||||
//
|
||||
/// Sorting as a general matrix pre-conditioning is mentioned in
|
||||
/// literature but I have found no articles about Gauss Seidel.
|
||||
///
|
||||
/// For Gaussian Elimination however increasing order is better suited.
|
||||
/// NOTE: Even better would be to sort on elements right of the matrix diagonal.
|
||||
/// FIXME: This entry needs an update.
|
||||
///
|
||||
void matrix_solver_t::sort_terms(matrix_sort_type_e sort)
|
||||
{
|
||||
// Sort in descending order by number of connected matrix voltages.
|
||||
// The idea is, that for Gauss-Seidel algo the first voltage computed
|
||||
// depends on the greatest number of previous voltages thus taking into
|
||||
// account the maximum amout of information.
|
||||
//
|
||||
// This actually improves performance on popeye slightly. Average
|
||||
// GS computations reduce from 2.509 to 2.370
|
||||
//
|
||||
// Smallest to largest : 2.613
|
||||
// Unsorted : 2.509
|
||||
// Largest to smallest : 2.370
|
||||
//
|
||||
// Sorting as a general matrix pre-conditioning is mentioned in
|
||||
// literature but I have found no articles about Gauss Seidel.
|
||||
//
|
||||
// For Gaussian Elimination however increasing order is better suited.
|
||||
// NOTE: Even better would be to sort on elements right of the matrix diagonal.
|
||||
//
|
||||
|
||||
const std::size_t iN = m_terms.size();
|
||||
|
||||
switch (sort)
|
||||
@ -211,7 +221,7 @@ namespace netlist::solver
|
||||
for (std::size_t k = 0; k < iN - 1; k++)
|
||||
for (std::size_t i = k+1; i < iN; i++)
|
||||
{
|
||||
if ((static_cast<int>(m_terms[k].railstart()) - static_cast<int>(m_terms[i].railstart())) * sort_order < 0)
|
||||
if ((static_cast<int>(m_terms[k].rail_start()) - static_cast<int>(m_terms[i].rail_start())) * sort_order < 0)
|
||||
{
|
||||
std::swap(m_terms[i], m_terms[k]);
|
||||
}
|
||||
@ -238,7 +248,7 @@ namespace netlist::solver
|
||||
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
{
|
||||
m_terms[k].set_railstart(m_terms[k].count());
|
||||
m_terms[k].set_rail_start(m_terms[k].count());
|
||||
for (std::size_t i = 0; i < m_rails_temp[k].count(); i++)
|
||||
this->m_terms[k].add_terminal(m_rails_temp[k].terms()[i], m_rails_temp[k].m_connected_net_idx.data()[i], false);
|
||||
}
|
||||
@ -259,7 +269,7 @@ namespace netlist::solver
|
||||
|
||||
t.m_nz.clear();
|
||||
|
||||
for (std::size_t i = 0; i < t.railstart(); i++)
|
||||
for (std::size_t i = 0; i < t.rail_start(); i++)
|
||||
if (!plib::container::contains(t.m_nz, static_cast<unsigned>(other[i])))
|
||||
t.m_nz.push_back(static_cast<unsigned>(other[i]));
|
||||
|
||||
@ -293,7 +303,7 @@ namespace netlist::solver
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < t.railstart(); i++)
|
||||
for (std::size_t i = 0; i < t.rail_start(); i++)
|
||||
if (!plib::container::contains(t.m_nzrd, static_cast<unsigned>(other[i])) && other[i] >= static_cast<int>(k + 1))
|
||||
t.m_nzrd.push_back(static_cast<unsigned>(other[i]));
|
||||
|
||||
@ -334,7 +344,7 @@ namespace netlist::solver
|
||||
}
|
||||
}
|
||||
}
|
||||
log().verbose("Number of mults/adds for {1}: {2}", name(), m_ops);
|
||||
log().verbose("Number of multiplications/additions for {1}: {2}", name(), m_ops);
|
||||
|
||||
if ((false))
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
@ -368,7 +378,7 @@ namespace netlist::solver
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
{
|
||||
max_count = std::max(max_count, m_terms[k].count());
|
||||
max_rail = std::max(max_rail, m_terms[k].railstart());
|
||||
max_rail = std::max(max_rail, m_terms[k].rail_start());
|
||||
}
|
||||
|
||||
m_gtn.resize(iN, max_count);
|
||||
@ -445,7 +455,7 @@ namespace netlist::solver
|
||||
do
|
||||
{
|
||||
update_dynamic();
|
||||
// Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
|
||||
// Gauss-Seidel will revert to Gaussian elimination if steps exceeded.
|
||||
this->m_stat_calculations++;
|
||||
this->vsolve_non_dynamic();
|
||||
this_resched = this->check_err();
|
||||
@ -472,11 +482,11 @@ namespace netlist::solver
|
||||
backup();
|
||||
step(timestep_type::FORWARD, netlist_time::from_fp(m_params.m_min_ts_ts()));
|
||||
resched = solve_nr_base();
|
||||
// update timestep calculation
|
||||
// update time step calculation
|
||||
next_time_step = compute_next_timestep(m_params.m_min_ts_ts(), m_params.m_min_ts_ts(), m_params.m_max_timestep);
|
||||
delta -= netlist_time::from_fp(m_params.m_min_ts_ts());
|
||||
}
|
||||
// try remaining time using compute_next_timestep
|
||||
// try remaining time using compute_next_time step
|
||||
while (delta > netlist_time::zero())
|
||||
{
|
||||
if (next_time_step > delta)
|
||||
@ -516,7 +526,7 @@ namespace netlist::solver
|
||||
return timestep_device_count() > 0 ? netlist_time::from_fp(m_params.m_min_timestep) : netlist_time::zero();
|
||||
}
|
||||
|
||||
backup(); // save voltages for backup and timestep calculation
|
||||
backup(); // save voltages for backup and time step calculation
|
||||
// update all terminals for new time step
|
||||
m_last_step = now;
|
||||
|
||||
@ -650,7 +660,7 @@ namespace netlist::solver
|
||||
log().verbose("Solver {1}", this->name());
|
||||
log().verbose(" ==> {1} nets", this->m_terms.size());
|
||||
log().verbose(" has {1} dynamic elements", this->dynamic_device_count());
|
||||
log().verbose(" has {1} timestep elements", this->timestep_device_count());
|
||||
log().verbose(" has {1} time step elements", this->timestep_device_count());
|
||||
log().verbose(" {1:6.3} average newton raphson loops",
|
||||
static_cast<fptype>(this->m_stat_newton_raphson) / static_cast<fptype>(this->m_stat_vsolver_calls));
|
||||
log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average",
|
||||
|
@ -4,6 +4,9 @@
|
||||
#ifndef NLD_MATRIX_SOLVER_H_
|
||||
#define NLD_MATRIX_SOLVER_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Raphson, Seidel
|
||||
|
||||
///
|
||||
/// \file nld_matrix_solver.h
|
||||
///
|
||||
@ -183,7 +186,7 @@ namespace netlist::solver
|
||||
|
||||
std::size_t count() const noexcept { return m_terms.size(); }
|
||||
|
||||
std::size_t railstart() const noexcept { return m_railstart; }
|
||||
std::size_t rail_start() const noexcept { return m_rail_start; }
|
||||
|
||||
terminal_t **terms() noexcept { return m_terms.data(); }
|
||||
|
||||
@ -193,7 +196,7 @@ namespace netlist::solver
|
||||
|
||||
bool is_net(const analog_net_t * net) const noexcept { return net == m_net; }
|
||||
|
||||
void set_railstart(std::size_t val) noexcept { m_railstart = val; }
|
||||
void set_rail_start(std::size_t val) noexcept { m_rail_start = val; }
|
||||
|
||||
PALIGNAS_VECTOROPT()
|
||||
|
||||
@ -205,7 +208,7 @@ namespace netlist::solver
|
||||
private:
|
||||
analog_net_t * m_net;
|
||||
plib::aligned_vector<terminal_t *> m_terms;
|
||||
std::size_t m_railstart;
|
||||
std::size_t m_rail_start;
|
||||
};
|
||||
|
||||
class proxied_analog_output_t : public analog_output_t
|
||||
@ -256,7 +259,7 @@ namespace netlist::solver
|
||||
/// \brief Immediately solve system at current time
|
||||
///
|
||||
/// This should only be called from update and update_param events.
|
||||
/// It's purpose is to bring voltage values to the current timestep.
|
||||
/// It's purpose is to bring voltage values to the current time step.
|
||||
/// This will be called BEFORE updating object properties.
|
||||
void solve_now()
|
||||
{
|
||||
@ -316,11 +319,11 @@ namespace netlist::solver
|
||||
virtual void backup() = 0;
|
||||
virtual void restore() = 0;
|
||||
|
||||
std::size_t max_railstart() const noexcept
|
||||
std::size_t max_rail_start() const noexcept
|
||||
{
|
||||
std::size_t max_rail = 0;
|
||||
for (std::size_t k = 0; k < m_terms.size(); k++)
|
||||
max_rail = std::max(max_rail, m_terms[k].railstart());
|
||||
max_rail = std::max(max_rail, m_terms[k].rail_start());
|
||||
return max_rail;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace netlist::solver
|
||||
: matrix_solver_t(main_solver, name, nets, params)
|
||||
, m_new_V(size)
|
||||
, m_RHS(size)
|
||||
, m_mat_ptr(size, this->max_railstart() + 1)
|
||||
, m_mat_ptr(size, this->max_rail_start() + 1)
|
||||
, m_last_V(size, nlconst::zero())
|
||||
, m_DD_n_m_1(size, nlconst::zero())
|
||||
, m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here
|
||||
@ -46,16 +46,16 @@ namespace netlist::solver
|
||||
static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS();
|
||||
static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8;
|
||||
|
||||
//PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
//PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::parray<float_type, SIZE> m_new_V;
|
||||
//PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
//PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::parray<float_type, SIZE> m_RHS;
|
||||
|
||||
//PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
//PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::pmatrix2d<float_type *> m_mat_ptr;
|
||||
|
||||
template <typename T, typename M>
|
||||
void log_fill(const T &fill,[[maybe_unused]] M &mat)
|
||||
void log_fill(const T &fill, [[maybe_unused]] M &mat)
|
||||
{
|
||||
const std::size_t iN = fill.size();
|
||||
|
||||
@ -207,7 +207,7 @@ namespace netlist::solver
|
||||
{
|
||||
std::size_t cnt(0);
|
||||
// build pointers into the compressed row format matrix for each terminal
|
||||
for (std::size_t j=0; j< this->m_terms[k].railstart();j++)
|
||||
for (std::size_t j=0; j< this->m_terms[k].rail_start();j++)
|
||||
{
|
||||
int other = this->m_terms[k].m_connected_net_idx[j];
|
||||
if (other >= 0)
|
||||
@ -216,8 +216,8 @@ namespace netlist::solver
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
nl_assert_always(cnt == this->m_terms[k].railstart(), "Count and railstart mismatch");
|
||||
m_mat_ptr[k][this->m_terms[k].railstart()] = &(mat[k][k]);
|
||||
nl_assert_always(cnt == this->m_terms[k].rail_start(), "Count and rail start mismatch");
|
||||
m_mat_ptr[k][this->m_terms[k].rail_start()] = &(mat[k][k]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,25 +245,25 @@ namespace netlist::solver
|
||||
|
||||
using source_type = typename decltype(m_gtn)::value_type;
|
||||
const std::size_t term_count = net.count();
|
||||
const std::size_t railstart = net.railstart();
|
||||
const std::size_t rail_start = net.rail_start();
|
||||
const auto &go = m_gonn[k];
|
||||
const auto > = m_gtn[k];
|
||||
const auto &Idr = m_Idrn[k];
|
||||
const auto &cnV = m_connected_net_Vn[k];
|
||||
|
||||
// FIXME: gonn, gtn and Idr - which float types should they have?
|
||||
//# FIXME: gonn, gtn and Idr - which float types should they have?
|
||||
|
||||
auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<source_type>::zero());
|
||||
|
||||
// update diagonal element ...
|
||||
*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
|
||||
*tcr_r[rail_start] = static_cast<FT>(gtot_t); //# mat.A[mat.diag[k]] += gtot_t;
|
||||
|
||||
for (std::size_t i = 0; i < railstart; i++)
|
||||
for (std::size_t i = 0; i < rail_start; i++)
|
||||
*tcr_r[i] += static_cast<FT>(go[i]);
|
||||
|
||||
auto RHS_t = std::accumulate(Idr, Idr + term_count, plib::constants<source_type>::zero());
|
||||
|
||||
for (std::size_t i = railstart; i < term_count; i++)
|
||||
for (std::size_t i = rail_start; i < term_count; i++)
|
||||
RHS_t += (- go[i]) * *cnV[i];
|
||||
|
||||
m_RHS[k] = static_cast<FT>(RHS_t);
|
||||
@ -272,9 +272,9 @@ namespace netlist::solver
|
||||
|
||||
private:
|
||||
// state - variable time_stepping
|
||||
//PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
//PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::parray<fptype, SIZE> m_last_V;
|
||||
// PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
//PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::parray<fptype, SIZE> m_DD_n_m_1;
|
||||
// PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
plib::parray<fptype, SIZE> m_h_n_m_1;
|
||||
|
@ -49,7 +49,7 @@ namespace netlist::solver
|
||||
template <typename T>
|
||||
void LE_back_subst(T & x);
|
||||
|
||||
// PALIGNAS_VECTOROPT() parrays define alignment already
|
||||
// PALIGNAS_VECTOROPT() `parray` defines alignment already
|
||||
plib::parray2D<FT, SIZE, m_pitch_ABS> m_A;
|
||||
};
|
||||
|
||||
@ -86,25 +86,25 @@ namespace netlist::solver
|
||||
for (std::size_t i = 0; i < kN; i++)
|
||||
{
|
||||
// Find the row with the largest first value
|
||||
std::size_t maxrow = i;
|
||||
std::size_t max_row = i;
|
||||
for (std::size_t j = i + 1; j < kN; j++)
|
||||
{
|
||||
if (plib::abs(m_A[j][i]) > plib::abs(m_A[maxrow][i]))
|
||||
//if (m_A[j][i] * m_A[j][i] > m_A[maxrow][i] * m_A[maxrow][i])
|
||||
maxrow = j;
|
||||
if (plib::abs(m_A[j][i]) > plib::abs(m_A[max_row][i]))
|
||||
//#if (m_A[j][i] * m_A[j][i] > m_A[max_row][i] * m_A[max_row][i])
|
||||
max_row = j;
|
||||
}
|
||||
|
||||
if (maxrow != i)
|
||||
if (max_row != i)
|
||||
{
|
||||
#if 0
|
||||
// Swap the maxrow and ith row
|
||||
// Swap the max_row and ith row
|
||||
for (std::size_t k = 0; k < kN; k++) {
|
||||
std::swap(m_A[i][k], m_A[maxrow][k]);
|
||||
std::swap(m_A[i][k], m_A[max_row][k]);
|
||||
}
|
||||
#else
|
||||
std::swap(m_A[i], m_A[maxrow]);
|
||||
std::swap(m_A[i], m_A[max_row]);
|
||||
#endif
|
||||
std::swap(this->m_RHS[i], this->m_RHS[maxrow]);
|
||||
std::swap(this->m_RHS[i], this->m_RHS[max_row]);
|
||||
}
|
||||
// FIXME: Singular matrix?
|
||||
const auto &Ai = m_A[i];
|
||||
|
@ -1,13 +1,18 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nld_ms_direct.h
|
||||
*
|
||||
*/
|
||||
|
||||
///
|
||||
/// \file nld_ms_direct.h
|
||||
///
|
||||
///
|
||||
#if 0
|
||||
#ifndef NLD_MS_DIRECT_H_
|
||||
#define NLD_MS_DIRECT_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Seidel,Crout
|
||||
|
||||
|
||||
#include "solver/nld_solver.h"
|
||||
#include "solver/nld_matrix_solver.h"
|
||||
|
||||
@ -199,21 +204,21 @@ nl_double matrix_solver_direct_t<m_N, storage_N>::compute_next_timestep()
|
||||
if (new_solver_timestep > m_params.m_max_timestep)
|
||||
new_solver_timestep = m_params.m_max_timestep;
|
||||
}
|
||||
//if (new_solver_timestep > 10.0 * hn)
|
||||
// new_solver_timestep = 10.0 * hn;
|
||||
//#if (new_solver_timestep > 10.0 * hn)
|
||||
//# new_solver_timestep = 10.0 * hn;
|
||||
return new_solver_timestep;
|
||||
}
|
||||
|
||||
template <unsigned m_N, unsigned storage_N>
|
||||
void matrix_solver_direct_t<m_N, storage_N>::add_term(int k, terminal_t *term)
|
||||
{
|
||||
if (term->m_otherterm->net().isRailNet())
|
||||
if (term->m_other_terminal->net().isRailNet())
|
||||
{
|
||||
m_rails_temp[k].add(term, -1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
int ot = get_net_idx(&term->m_otherterm->net());
|
||||
int ot = get_net_idx(&term->m_other_terminal->net());
|
||||
if (ot>=0)
|
||||
{
|
||||
m_terms[k]->add(term, ot, true);
|
||||
@ -222,7 +227,7 @@ void matrix_solver_direct_t<m_N, storage_N>::add_term(int k, terminal_t *term)
|
||||
else // if (ot<0)
|
||||
{
|
||||
m_rails_temp[k].add(term, ot, true);
|
||||
netlist().error("found term with missing othernet {1}\n", term->name());
|
||||
netlist().error("found term with missing other net {1}\n", term->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,7 +249,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
|
||||
|
||||
for (unsigned k = 0; k < N(); k++)
|
||||
{
|
||||
m_terms[k]->m_railstart = m_terms[k]->count();
|
||||
m_terms[k]->m_rail_start = m_terms[k]->count();
|
||||
for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
|
||||
this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].connected_net_idx()[i], false);
|
||||
|
||||
@ -257,7 +262,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
|
||||
/* Sort in descending order by number of connected matrix voltages.
|
||||
* The idea is, that for Gauss-Seidel algo the first voltage computed
|
||||
* depends on the greatest number of previous voltages thus taking into
|
||||
* account the maximum amout of information.
|
||||
* account the maximum amount of information.
|
||||
*
|
||||
* This actually improves performance on popeye slightly. Average
|
||||
* GS computations reduce from 2.509 to 2.370
|
||||
@ -279,7 +284,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
|
||||
for (unsigned k = 0; k < N() / 2; k++)
|
||||
for (unsigned i = 0; i < N() - 1; i++)
|
||||
{
|
||||
if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0)
|
||||
if ((m_terms[i]->m_rail_start - m_terms[i+1]->m_rail_start) * sort_order < 0)
|
||||
{
|
||||
std::swap(m_terms[i],m_terms[i+1]);
|
||||
std::swap(m_nets[i], m_nets[i+1]);
|
||||
@ -291,7 +296,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
|
||||
int *other = m_terms[k]->connected_net_idx();
|
||||
for (unsigned i = 0; i < m_terms[k]->count(); i++)
|
||||
if (other[i] != -1)
|
||||
other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net());
|
||||
other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_other_terminal->net());
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -325,7 +330,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
|
||||
|
||||
for (unsigned j = 0; j < N(); j++)
|
||||
{
|
||||
for (unsigned i = 0; i < t->m_railstart; i++)
|
||||
for (unsigned i = 0; i < t->m_rail_start; i++)
|
||||
{
|
||||
if (!t->m_nzrd.contains(other[i]) && other[i] >= (int) (k + 1))
|
||||
t->m_nzrd.add(other[i]);
|
||||
@ -378,7 +383,7 @@ void matrix_solver_direct_t<m_N, storage_N>::build_LE_A()
|
||||
|
||||
nl_double akk = 0.0;
|
||||
const unsigned terms_count = m_terms[k]->count();
|
||||
const unsigned railstart = m_terms[k]->m_railstart;
|
||||
const unsigned rail_start = m_terms[k]->m_rail_start;
|
||||
const nl_double * RESTRICT gt = m_terms[k]->gt();
|
||||
const nl_double * RESTRICT go = m_terms[k]->go();
|
||||
const int * RESTRICT net_other = m_terms[k]->connected_net_idx();
|
||||
@ -388,7 +393,7 @@ void matrix_solver_direct_t<m_N, storage_N>::build_LE_A()
|
||||
|
||||
A(k,k) += akk;
|
||||
|
||||
for (unsigned i = 0; i < railstart; i++)
|
||||
for (unsigned i = 0; i < rail_start; i++)
|
||||
A(k, net_other[i]) -= go[i];
|
||||
}
|
||||
}
|
||||
@ -410,8 +415,8 @@ void matrix_solver_direct_t<m_N, storage_N>::build_LE_RHS(nl_double * RESTRICT r
|
||||
for (int i = 0; i < terms_count; i++)
|
||||
rhsk_a = rhsk_a + Idr[i];
|
||||
|
||||
for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
|
||||
//rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
|
||||
for (int i = m_terms[k]->m_rail_start; i < terms_count; i++)
|
||||
//#rhsk = rhsk + go[i] * terms[i]->m_other_terminal->net().as_analog().Q_Analog();
|
||||
rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
|
||||
|
||||
rhs[k] = rhsk_a + rhsk_b;
|
||||
@ -438,7 +443,7 @@ void matrix_solver_direct_t<m_N, storage_N>::LE_solve()
|
||||
for (j=0;j<kN;j++)
|
||||
if ((temp=fabs(m_A[i][j])) > big)
|
||||
big=temp;
|
||||
//if (big == 0.0) nrerror("Singular matrix in routine LUDCMP");
|
||||
//#if (big == 0.0) nrerror("Singular matrix in routine LUDCMP");
|
||||
vv[i]=1.0/big;
|
||||
}
|
||||
#endif
|
||||
|
@ -67,7 +67,7 @@ namespace netlist::solver
|
||||
{
|
||||
std::size_t cnt(0);
|
||||
// build pointers into the compressed row format matrix for each terminal
|
||||
for (std::size_t j=0; j< this->m_terms[k].railstart();j++)
|
||||
for (std::size_t j=0; j< this->m_terms[k].rail_start();j++)
|
||||
{
|
||||
int other = this->m_terms[k].m_connected_net_idx[j];
|
||||
for (auto i = mat.row_idx[k]; i < mat.row_idx[k+1]; i++)
|
||||
@ -78,8 +78,8 @@ namespace netlist::solver
|
||||
break;
|
||||
}
|
||||
}
|
||||
nl_assert(cnt == this->m_terms[k].railstart());
|
||||
this->m_mat_ptr[k][this->m_terms[k].railstart()] = &mat.A[mat.diag[k]];
|
||||
nl_assert(cnt == this->m_terms[k].rail_start());
|
||||
this->m_mat_ptr[k][this->m_terms[k].rail_start()] = &mat.A[mat.diag[k]];
|
||||
}
|
||||
|
||||
this->state().log().verbose("maximum fill: {1}", gr.first);
|
||||
@ -144,11 +144,11 @@ namespace netlist::solver
|
||||
{
|
||||
auto &net = this->m_terms[k];
|
||||
|
||||
// FIXME: gonn, gtn and Idr - which float types should they have?
|
||||
//# FIXME: gonn, gtn and Idr - which float types should they have?
|
||||
|
||||
//auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<FT>::zero());
|
||||
//*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
|
||||
auto pd = this->m_mat_ptr[k][net.railstart()] - &this->mat.A[0];
|
||||
//*tcr_r[rail_start] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
|
||||
auto pd = this->m_mat_ptr[k][net.rail_start()] - &this->mat.A[0];
|
||||
#if 0
|
||||
pstring terms = plib::pfmt("m_A{1} = gt[{2}]")(pd, this->m_gtn.didx(k,0));
|
||||
for (std::size_t i=1; i < net.count(); i++)
|
||||
@ -159,10 +159,10 @@ namespace netlist::solver
|
||||
for (std::size_t i=0; i < net.count(); i++)
|
||||
strm("\tm_A{1} += gt[{2}];\n", pd, this->m_gtn.didx(k,i));
|
||||
#endif
|
||||
//for (std::size_t i = 0; i < railstart; i++)
|
||||
//for (std::size_t i = 0; i < rail_start; i++)
|
||||
// *tcr_r[i] += static_cast<FT>(go[i]);
|
||||
|
||||
for (std::size_t i = 0; i < net.railstart(); i++)
|
||||
for (std::size_t i = 0; i < net.rail_start(); i++)
|
||||
{
|
||||
auto p = this->m_mat_ptr[k][i] - &this->mat.A[0];
|
||||
strm("\tm_A{1} += go[{2}];\n", p, this->m_gonn.didx(k,i));
|
||||
@ -173,10 +173,10 @@ namespace netlist::solver
|
||||
terms = plib::pfmt("{1} RHS{2} = Idr[{3}]")(fptype, k, this->m_Idrn.didx(k,0));
|
||||
for (std::size_t i=1; i < net.count(); i++)
|
||||
terms += plib::pfmt(" + Idr[{1}]")(this->m_Idrn.didx(k,i));
|
||||
//for (std::size_t i = railstart; i < term_count; i++)
|
||||
//for (std::size_t i = rail_start; i < term_count; i++)
|
||||
// RHS_t += (- go[i]) * *cnV[i];
|
||||
|
||||
for (std::size_t i = net.railstart(); i < net.count(); i++)
|
||||
for (std::size_t i = net.rail_start(); i < net.count(); i++)
|
||||
terms += plib::pfmt(" - go[{1}] * *cnV[{2}]")(this->m_gonn.didx(k,i), this->m_connected_net_Vn.didx(k,i));
|
||||
|
||||
strm("\t{1};\n", terms);
|
||||
@ -185,10 +185,10 @@ namespace netlist::solver
|
||||
strm("\t{1} RHS{2} = Idr[{3}];\n", fptype, k, this->m_Idrn.didx(k,0));
|
||||
for (std::size_t i=1; i < net.count(); i++)
|
||||
strm("\tRHS{1} += Idr[{2}];\n", k, this->m_Idrn.didx(k,i));
|
||||
//for (std::size_t i = railstart; i < term_count; i++)
|
||||
//for (std::size_t i = rail_start; i < term_count; i++)
|
||||
// RHS_t += (- go[i]) * *cnV[i];
|
||||
|
||||
for (std::size_t i = net.railstart(); i < net.count(); i++)
|
||||
for (std::size_t i = net.rail_start(); i < net.count(); i++)
|
||||
strm("\tRHS{1} -= go[{2}] * *cnV[{3}];\n", k, this->m_gonn.didx(k,i), this->m_connected_net_Vn.didx(k,i));
|
||||
|
||||
#endif
|
||||
@ -196,7 +196,7 @@ namespace netlist::solver
|
||||
|
||||
for (std::size_t i = 0; i < iN - 1; i++)
|
||||
{
|
||||
//const auto &nzbd = this->m_terms[i].m_nzbd;
|
||||
//#const auto &nzbd = this->m_terms[i].m_nzbd;
|
||||
const auto *nzbd = mat.nzbd(i);
|
||||
const auto nzbd_count = mat.nzbd_count(i);
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace netlist::solver
|
||||
for (std::size_t k=0; k<iN; k++)
|
||||
{
|
||||
std::size_t cnt = 0;
|
||||
for (std::size_t j=0; j< this->m_terms[k].railstart();j++)
|
||||
for (std::size_t j=0; j< this->m_terms[k].rail_start();j++)
|
||||
{
|
||||
for (std::size_t i = m_ops.m_mat.row_idx[k]; i<m_ops.m_mat.row_idx[k+1]; i++)
|
||||
if (this->m_terms[k].m_connected_net_idx[j] == static_cast<int>(m_ops.m_mat.col_idx[i]))
|
||||
@ -72,8 +72,8 @@ namespace netlist::solver
|
||||
break;
|
||||
}
|
||||
}
|
||||
nl_assert(cnt == this->m_terms[k].railstart());
|
||||
this->m_mat_ptr[k][this->m_terms[k].railstart()] = &m_ops.m_mat.A[m_ops.m_mat.diag[k]];
|
||||
nl_assert(cnt == this->m_terms[k].rail_start());
|
||||
this->m_mat_ptr[k][this->m_terms[k].rail_start()] = &m_ops.m_mat.A[m_ops.m_mat.diag[k]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
///
|
||||
/// The approach is iterative and applied for each row changed.
|
||||
///
|
||||
/// The performance for a typical circuit like kidniki compared to Gaussian
|
||||
/// The performance for a typical circuit like `kidniki` compared to Gaussian
|
||||
/// elimination is poor:
|
||||
///
|
||||
/// a) The code needs to be run for each row change.
|
||||
@ -239,7 +239,7 @@ namespace netlist::solver
|
||||
auto lamba(plib::constants<FT>::zero());
|
||||
std::array<float_type, m_pitch> w = {0};
|
||||
|
||||
// compute w and lamba
|
||||
// compute w and lambda
|
||||
for (std::size_t i = 0; i < iN; i++)
|
||||
z[i] = Ainv(i, row); // u is row'th column
|
||||
|
||||
@ -251,7 +251,7 @@ namespace netlist::solver
|
||||
std::size_t col = cols[j];
|
||||
float_type f = v[col];
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
w[k] += Ainv(col,k) * f; // Transpose(Ainv) * v
|
||||
w[k] += Ainv(col,k) * f; //# Transpose(Ainv) * v
|
||||
}
|
||||
|
||||
lamba = -plib::reciprocal(plib::constants<float_type>::one() + lamba);
|
||||
|
@ -4,6 +4,9 @@
|
||||
#ifndef NLD_MS_SOR_H_
|
||||
#define NLD_MS_SOR_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Seidel
|
||||
|
||||
///
|
||||
/// \file nld_ms_sor.h
|
||||
///
|
||||
@ -45,10 +48,10 @@ namespace netlist::solver
|
||||
std::vector<float_type> one_m_w;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// matrix_solver - Gauss - Seidel
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Gauss - Seidel matrix_solver
|
||||
///
|
||||
///
|
||||
template <typename FT, int SIZE>
|
||||
void matrix_solver_SOR_t<FT, SIZE>::vsolve_non_dynamic()
|
||||
{
|
||||
@ -89,7 +92,7 @@ namespace netlist::solver
|
||||
RHS_t = RHS_t + Idr[i];
|
||||
}
|
||||
|
||||
for (std::size_t i = this->m_terms[k].railstart(); i < term_count; i++)
|
||||
for (std::size_t i = this->m_terms[k].rail_start(); i < term_count; i++)
|
||||
RHS_t = RHS_t - go[i] * *other_cur_analog[i];
|
||||
|
||||
this->m_RHS[k] = static_cast<float_type>(RHS_t);
|
||||
@ -126,11 +129,11 @@ namespace netlist::solver
|
||||
for (std::size_t k = 0; k < iN; k++)
|
||||
{
|
||||
const int * net_other = this->m_terms[k].m_connected_net_idx.data();
|
||||
const std::size_t railstart = this->m_terms[k].railstart();
|
||||
const std::size_t rail_start = this->m_terms[k].rail_start();
|
||||
const auto * go = this->m_gonn[k];
|
||||
|
||||
float_type Idrive = plib::constants<float_type>::zero();
|
||||
for (std::size_t i = 0; i < railstart; i++)
|
||||
for (std::size_t i = 0; i < rail_start; 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 + this->m_RHS[k]) * w[k];
|
||||
|
@ -4,6 +4,10 @@
|
||||
#ifndef NLD_MS_SOR_MAT_H_
|
||||
#define NLD_MS_SOR_MAT_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Seidel,
|
||||
//
|
||||
|
||||
///
|
||||
/// \file nld_ms_sor.h
|
||||
///
|
||||
|
@ -4,6 +4,13 @@
|
||||
#ifndef NLD_MS_W_H_
|
||||
#define NLD_MS_W_H_
|
||||
|
||||
// Names
|
||||
// spell-checker: words Woodbury, Raphson,
|
||||
//
|
||||
// Specific technical terms
|
||||
// spell-checker: words Cgso, Cgdo, Cgbo, Cjsw, Mjsw, Ucrit, Uexp, Utra, Neff, Tnom, capval, Udsat, Utst
|
||||
|
||||
|
||||
///
|
||||
/// \file nld_ms_direct.h
|
||||
///
|
||||
@ -34,8 +41,8 @@
|
||||
/// for uk being unit vectors for full rank (max(k) == n) is identical to the
|
||||
/// inverse of A.
|
||||
///
|
||||
/// The approach performs relatively well for matrices up to n ~ 40 (kidniki using frontiers).
|
||||
/// Kidniki without frontiers has n==88. Here, the average number of Newton-Raphson
|
||||
/// The approach performs relatively well for matrices up to n ~ 40 (`kidniki` using frontiers).
|
||||
/// `Kidniki` without frontiers has n==88. Here, the average number of Newton-Raphson
|
||||
/// loops increase to 20. It looks like that the approach for larger matrices
|
||||
/// introduces numerical instability.
|
||||
///
|
||||
@ -82,7 +89,7 @@ namespace netlist::solver
|
||||
template <typename T1, typename T2>
|
||||
float_ext_type &W(const T1 &r, const T2 &c) { return m_W[r][c]; }
|
||||
|
||||
// access to Ainv for fixed columns over row, there store transposed
|
||||
// access to the inverted matrix for fixed columns over row, values stored transposed
|
||||
template <typename T1, typename T2>
|
||||
float_ext_type &Ainv(const T1 &r, const T2 &c) { return m_Ainv[c][r]; }
|
||||
template <typename T1>
|
||||
@ -109,7 +116,7 @@ namespace netlist::solver
|
||||
array2D<float_ext_type, storage_N, m_pitch> H;
|
||||
std::array<unsigned, storage_N> rows;
|
||||
array2D<unsigned, storage_N, m_pitch> cols;
|
||||
std::array<unsigned, storage_N> colcount;
|
||||
std::array<unsigned, storage_N> col_count;
|
||||
|
||||
unsigned m_cnt;
|
||||
};
|
||||
@ -225,7 +232,7 @@ namespace netlist::solver
|
||||
|
||||
// determine changed rows
|
||||
|
||||
unsigned rowcount=0;
|
||||
unsigned row_count=0;
|
||||
#define VT(r,c) (A(r,c) - lA(r,c))
|
||||
|
||||
for (unsigned row = 0; row < iN; row ++)
|
||||
@ -235,20 +242,20 @@ namespace netlist::solver
|
||||
for (auto & col : nz)
|
||||
{
|
||||
if (A(row,col) != lA(row,col))
|
||||
cols[rowcount][cc++] = col;
|
||||
cols[row_count][cc++] = col;
|
||||
}
|
||||
if (cc > 0)
|
||||
{
|
||||
colcount[rowcount] = cc;
|
||||
rows[rowcount++] = row;
|
||||
col_count[row_count] = cc;
|
||||
rows[row_count++] = row;
|
||||
}
|
||||
}
|
||||
if (rowcount > 0)
|
||||
if (row_count > 0)
|
||||
{
|
||||
// construct w = transform(V) * y
|
||||
// dim: rowcount x iN
|
||||
// dim: row_count x iN
|
||||
//
|
||||
for (unsigned i = 0; i < rowcount; i++)
|
||||
for (unsigned i = 0; i < row_count; i++)
|
||||
{
|
||||
const unsigned r = rows[i];
|
||||
FT tmp = plib::constants<FT>::zero();
|
||||
@ -257,32 +264,32 @@ namespace netlist::solver
|
||||
w[i] = tmp;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < rowcount; i++)
|
||||
for (unsigned k=0; k< rowcount; k++)
|
||||
for (unsigned i = 0; i < row_count; i++)
|
||||
for (unsigned k=0; k< row_count; k++)
|
||||
H[i][k] = plib::constants<FT>::zero();
|
||||
|
||||
for (unsigned i = 0; i < rowcount; i++)
|
||||
for (unsigned i = 0; i < row_count; i++)
|
||||
H[i][i] = plib::constants<FT>::one();
|
||||
// Construct H = (I + VT*Z)
|
||||
for (unsigned i = 0; i < rowcount; i++)
|
||||
for (unsigned k=0; k< colcount[i]; k++)
|
||||
for (unsigned i = 0; i < row_count; i++)
|
||||
for (unsigned k=0; k< col_count[i]; k++)
|
||||
{
|
||||
const unsigned col = cols[i][k];
|
||||
float_type f = VT(rows[i],col);
|
||||
// FIXME: comparison to zero
|
||||
if (f != plib::constants<float_type>::zero())
|
||||
for (unsigned j= 0; j < rowcount; j++)
|
||||
for (unsigned j= 0; j < row_count; j++)
|
||||
H[i][j] += f * Ainv(col,rows[j]);
|
||||
}
|
||||
|
||||
// Gaussian elimination of H
|
||||
for (unsigned i = 0; i < rowcount; i++)
|
||||
for (unsigned i = 0; i < row_count; i++)
|
||||
{
|
||||
// FIXME: comparison to zero
|
||||
if (H[i][i] == plib::constants<float_type>::zero())
|
||||
plib::perrlogger("{} H singular\n", this->name());
|
||||
const float_type f = plib::reciprocal(H[i][i]);
|
||||
for (unsigned j = i+1; j < rowcount; j++)
|
||||
for (unsigned j = i+1; j < row_count; j++)
|
||||
{
|
||||
const float_type f1 = - f * H[j][i];
|
||||
|
||||
@ -291,7 +298,7 @@ namespace netlist::solver
|
||||
{
|
||||
float_type *pj = &H[j][i+1];
|
||||
const float_type *pi = &H[i][i+1];
|
||||
for (unsigned k = 0; k < rowcount-i-1; k++)
|
||||
for (unsigned k = 0; k < row_count-i-1; k++)
|
||||
pj[k] += f1 * pi[k];
|
||||
//H[j][k] += f1 * H[i][k];
|
||||
w[j] += f1 * w[i];
|
||||
@ -300,12 +307,12 @@ namespace netlist::solver
|
||||
}
|
||||
// Back substitution
|
||||
//inv(H) w = t w = H t
|
||||
for (unsigned j = rowcount; j-- > 0; )
|
||||
for (unsigned j = row_count; j-- > 0; )
|
||||
{
|
||||
float_type tmp = 0;
|
||||
const float_type *pj = &H[j][j+1];
|
||||
const float_type *tj = &t[j+1];
|
||||
for (unsigned k = 0; k < rowcount-j-1; k++)
|
||||
for (unsigned k = 0; k < row_count-j-1; k++)
|
||||
tmp += pj[k] * tj[k];
|
||||
//tmp += H[j][k] * t[k];
|
||||
t[j] = (w[j] - tmp) / H[j][j];
|
||||
@ -315,7 +322,7 @@ namespace netlist::solver
|
||||
for (unsigned i=0; i<iN; i++)
|
||||
{
|
||||
float_type tmp = plib::constants<FT>::zero();
|
||||
for (unsigned j=0; j<rowcount;j++)
|
||||
for (unsigned j=0; j<row_count;j++)
|
||||
{
|
||||
const unsigned row = rows[j];
|
||||
tmp += Ainv(i,row) * t[j];
|
||||
|
@ -1,6 +1,8 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Couriersud
|
||||
|
||||
// Names
|
||||
// spell-checker: words Woodbury,
|
||||
|
||||
#include "nl_factory.h"
|
||||
#include "core/setup.h"
|
||||
@ -413,9 +415,9 @@ namespace netlist::devices
|
||||
}
|
||||
else
|
||||
{
|
||||
auto *otherterm = dynamic_cast<terminal_t *>(t);
|
||||
if (otherterm != nullptr)
|
||||
if (state().setup().get_connected_terminal(*otherterm)->net().is_rail_net())
|
||||
auto *other_terminal = dynamic_cast<terminal_t *>(t);
|
||||
if (other_terminal != nullptr)
|
||||
if (state().setup().get_connected_terminal(*other_terminal)->net().is_rail_net())
|
||||
railterms++;
|
||||
}
|
||||
}
|
||||
@ -465,7 +467,7 @@ namespace netlist::devices
|
||||
log().verbose("Solver {1}", ms->name());
|
||||
log().verbose(" ==> {1} nets", grp.size());
|
||||
log().verbose(" has {1} dynamic elements", ms->dynamic_device_count());
|
||||
log().verbose(" has {1} timestep elements", ms->timestep_device_count());
|
||||
log().verbose(" has {1} time step elements", ms->timestep_device_count());
|
||||
for (auto &n : grp)
|
||||
{
|
||||
log().verbose("Net {1}", n->name());
|
||||
|
@ -4,7 +4,7 @@
|
||||
///
|
||||
/// \file test_pfunction.cpp
|
||||
///
|
||||
/// tests for pfunction
|
||||
/// tests for `pfunction` class
|
||||
///
|
||||
|
||||
#include "plib/ptests.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
///
|
||||
/// \file test_pmfp.cpp
|
||||
///
|
||||
/// tests for plib::pmfp
|
||||
/// tests for `plib::pmfp` class
|
||||
///
|
||||
|
||||
#include "plib/ptests.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
///
|
||||
/// \file test_pmfp_multibase.cpp
|
||||
///
|
||||
/// tests for plib::pmfp
|
||||
/// tests for `plib::pmfp`
|
||||
///
|
||||
|
||||
#include "plib/ptypes.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
///
|
||||
/// \file test_pmfp.cpp
|
||||
///
|
||||
/// tests for plib::pmfp
|
||||
/// tests for `plib::pmfp`
|
||||
///
|
||||
|
||||
#include "plib/pconfig.h"
|
||||
|
@ -340,7 +340,7 @@ void nl_convert_spice_t::convert_block(const str_list &contents)
|
||||
void nl_convert_spice_t::convert(const pstring &contents)
|
||||
{
|
||||
std::vector<pstring> spnl(plib::psplit(contents, '\n'));
|
||||
std::vector<pstring> after_linecontinuation;
|
||||
std::vector<pstring> after_line_continuation;
|
||||
|
||||
// Add gnd net
|
||||
|
||||
@ -358,24 +358,24 @@ void nl_convert_spice_t::convert(const pstring &contents)
|
||||
line += inl.substr(1);
|
||||
else
|
||||
{
|
||||
after_linecontinuation.push_back(line);
|
||||
after_line_continuation.push_back(line);
|
||||
line = inl;
|
||||
}
|
||||
}
|
||||
after_linecontinuation.push_back(line);
|
||||
after_line_continuation.push_back(line);
|
||||
spnl.clear(); // no longer needed
|
||||
|
||||
// Process sub circuits
|
||||
|
||||
std::vector<std::vector<pstring>> subckts;
|
||||
std::vector<pstring> nl;
|
||||
auto inp = after_linecontinuation.begin();
|
||||
while (inp != after_linecontinuation.end())
|
||||
auto inp = after_line_continuation.begin();
|
||||
while (inp != after_line_continuation.end())
|
||||
{
|
||||
if (plib::startsWith(*inp, ".SUBCKT"))
|
||||
{
|
||||
std::vector<pstring> sub;
|
||||
while (inp != after_linecontinuation.end())
|
||||
while (inp != after_line_continuation.end())
|
||||
{
|
||||
auto s(*inp);
|
||||
sub.push_back(s);
|
||||
|
Loading…
Reference in New Issue
Block a user