summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist')
-rw-r--r--src/lib/netlist/analog/nld_bjt.cpp632
-rw-r--r--src/lib/netlist/analog/nld_bjt.h2
-rw-r--r--src/lib/netlist/analog/nld_fourterm.h2
-rw-r--r--src/lib/netlist/analog/nld_mosfet.cpp488
-rw-r--r--src/lib/netlist/analog/nld_mosfet.h21
-rw-r--r--src/lib/netlist/analog/nld_opamps.cpp30
-rw-r--r--src/lib/netlist/analog/nld_opamps.h2
-rw-r--r--src/lib/netlist/analog/nld_switches.cpp49
-rw-r--r--src/lib/netlist/analog/nld_switches.h2
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h2
-rw-r--r--src/lib/netlist/analog/nlid_fourterm.cpp52
-rw-r--r--src/lib/netlist/analog/nlid_fourterm.h60
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.cpp233
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.h338
-rw-r--r--src/lib/netlist/build/makefile75
-rw-r--r--src/lib/netlist/devices/net_lib.cpp281
-rw-r--r--src/lib/netlist/devices/net_lib.h46
-rw-r--r--src/lib/netlist/devices/nld_2102A.cpp8
-rw-r--r--src/lib/netlist/devices/nld_2102A.h2
-rw-r--r--src/lib/netlist/devices/nld_2716.cpp6
-rw-r--r--src/lib/netlist/devices/nld_2716.h2
-rw-r--r--src/lib/netlist/devices/nld_4020.cpp7
-rw-r--r--src/lib/netlist/devices/nld_4020.h2
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp37
-rw-r--r--src/lib/netlist/devices/nld_4066.h2
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp18
-rw-r--r--src/lib/netlist/devices/nld_4316.h2
-rw-r--r--src/lib/netlist/devices/nld_74107.cpp20
-rw-r--r--src/lib/netlist/devices/nld_74107.h2
-rw-r--r--src/lib/netlist/devices/nld_74123.cpp26
-rw-r--r--src/lib/netlist/devices/nld_74123.h2
-rw-r--r--src/lib/netlist/devices/nld_74153.cpp12
-rw-r--r--src/lib/netlist/devices/nld_74153.h2
-rw-r--r--src/lib/netlist/devices/nld_74161.cpp8
-rw-r--r--src/lib/netlist/devices/nld_74161.h2
-rw-r--r--src/lib/netlist/devices/nld_74164.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74164.h2
-rw-r--r--src/lib/netlist/devices/nld_74165.cpp7
-rw-r--r--src/lib/netlist/devices/nld_74165.h2
-rw-r--r--src/lib/netlist/devices/nld_74166.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74166.h2
-rw-r--r--src/lib/netlist/devices/nld_74174.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74174.h2
-rw-r--r--src/lib/netlist/devices/nld_74175.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74175.h2
-rw-r--r--src/lib/netlist/devices/nld_74192.cpp8
-rw-r--r--src/lib/netlist/devices/nld_74192.h2
-rw-r--r--src/lib/netlist/devices/nld_74193.cpp8
-rw-r--r--src/lib/netlist/devices/nld_74193.h2
-rw-r--r--src/lib/netlist/devices/nld_74194.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74194.h2
-rw-r--r--src/lib/netlist/devices/nld_74365.cpp14
-rw-r--r--src/lib/netlist/devices/nld_74365.h2
-rw-r--r--src/lib/netlist/devices/nld_7448.cpp24
-rw-r--r--src/lib/netlist/devices/nld_7448.h2
-rw-r--r--src/lib/netlist/devices/nld_7450.cpp18
-rw-r--r--src/lib/netlist/devices/nld_7450.h2
-rw-r--r--src/lib/netlist/devices/nld_7473.cpp10
-rw-r--r--src/lib/netlist/devices/nld_7473.h2
-rw-r--r--src/lib/netlist/devices/nld_7474.cpp132
-rw-r--r--src/lib/netlist/devices/nld_7474.h2
-rw-r--r--src/lib/netlist/devices/nld_7475.cpp12
-rw-r--r--src/lib/netlist/devices/nld_7475.h2
-rw-r--r--src/lib/netlist/devices/nld_7483.cpp47
-rw-r--r--src/lib/netlist/devices/nld_7483.h2
-rw-r--r--src/lib/netlist/devices/nld_7485.cpp6
-rw-r--r--src/lib/netlist/devices/nld_7485.h2
-rw-r--r--src/lib/netlist/devices/nld_7490.cpp35
-rw-r--r--src/lib/netlist/devices/nld_7490.h2
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp87
-rw-r--r--src/lib/netlist/devices/nld_7493.h2
-rw-r--r--src/lib/netlist/devices/nld_7497.cpp174
-rw-r--r--src/lib/netlist/devices/nld_7497.h57
-rw-r--r--src/lib/netlist/devices/nld_74ls629.cpp19
-rw-r--r--src/lib/netlist/devices/nld_74ls629.h2
-rw-r--r--src/lib/netlist/devices/nld_82S115.cpp6
-rw-r--r--src/lib/netlist/devices/nld_82S115.h2
-rw-r--r--src/lib/netlist/devices/nld_82S123.cpp6
-rw-r--r--src/lib/netlist/devices/nld_82S123.h2
-rw-r--r--src/lib/netlist/devices/nld_82S126.cpp6
-rw-r--r--src/lib/netlist/devices/nld_82S126.h2
-rw-r--r--src/lib/netlist/devices/nld_82S16.cpp73
-rw-r--r--src/lib/netlist/devices/nld_82S16.h2
-rw-r--r--src/lib/netlist/devices/nld_9310.cpp42
-rw-r--r--src/lib/netlist/devices/nld_9310.h2
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp138
-rw-r--r--src/lib/netlist/devices/nld_9316.h2
-rw-r--r--src/lib/netlist/devices/nld_9322.cpp14
-rw-r--r--src/lib/netlist/devices/nld_9322.h2
-rw-r--r--src/lib/netlist/devices/nld_am2847.cpp10
-rw-r--r--src/lib/netlist/devices/nld_am2847.h2
-rw-r--r--src/lib/netlist/devices/nld_dm9314.cpp6
-rw-r--r--src/lib/netlist/devices/nld_dm9314.h2
-rw-r--r--src/lib/netlist/devices/nld_dm9334.cpp6
-rw-r--r--src/lib/netlist/devices/nld_dm9334.h2
-rw-r--r--src/lib/netlist/devices/nld_legacy.cpp10
-rw-r--r--src/lib/netlist/devices/nld_legacy.h2
-rw-r--r--src/lib/netlist/devices/nld_log.cpp18
-rw-r--r--src/lib/netlist/devices/nld_log.h4
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp16
-rw-r--r--src/lib/netlist/devices/nld_mm5837.h2
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp101
-rw-r--r--src/lib/netlist/devices/nld_ne555.h8
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.cpp14
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.h2
-rw-r--r--src/lib/netlist/devices/nld_schmitt.cpp30
-rw-r--r--src/lib/netlist/devices/nld_schmitt.h2
-rw-r--r--src/lib/netlist/devices/nld_system.cpp95
-rw-r--r--src/lib/netlist/devices/nld_system.h2
-rw-r--r--src/lib/netlist/devices/nld_tms4800.cpp10
-rw-r--r--src/lib/netlist/devices/nld_tms4800.h2
-rw-r--r--src/lib/netlist/devices/nld_tristate.cpp6
-rw-r--r--src/lib/netlist/devices/nld_tristate.h2
-rw-r--r--src/lib/netlist/devices/nlid_cmos.h4
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp54
-rw-r--r--src/lib/netlist/devices/nlid_proxy.h24
-rw-r--r--src/lib/netlist/devices/nlid_system.h92
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp141
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.h175
-rw-r--r--src/lib/netlist/macro/nlm_base.cpp39
-rw-r--r--src/lib/netlist/macro/nlm_base.h2
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.cpp8
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.h2
-rw-r--r--src/lib/netlist/macro/nlm_opamp.cpp2
-rw-r--r--src/lib/netlist/macro/nlm_opamp.h2
-rw-r--r--src/lib/netlist/macro/nlm_other.cpp2
-rw-r--r--src/lib/netlist/macro/nlm_other.h2
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.cpp9
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.h2
-rw-r--r--src/lib/netlist/netlist_types.h54
-rw-r--r--src/lib/netlist/nl_base.cpp765
-rw-r--r--src/lib/netlist/nl_base.h1307
-rw-r--r--src/lib/netlist/nl_config.h46
-rw-r--r--src/lib/netlist/nl_dice_compat.h17
-rw-r--r--src/lib/netlist/nl_errstr.h3
-rw-r--r--src/lib/netlist/nl_factory.cpp140
-rw-r--r--src/lib/netlist/nl_factory.h87
-rw-r--r--src/lib/netlist/nl_lists.h163
-rw-r--r--src/lib/netlist/nl_parser.cpp43
-rw-r--r--src/lib/netlist/nl_parser.h18
-rw-r--r--src/lib/netlist/nl_setup.cpp838
-rw-r--r--src/lib/netlist/nl_setup.h309
-rw-r--r--src/lib/netlist/nl_time.h145
-rw-r--r--src/lib/netlist/nltypes.h147
-rw-r--r--src/lib/netlist/plib/gmres.h450
-rw-r--r--src/lib/netlist/plib/mat_cr.h530
-rw-r--r--src/lib/netlist/plib/palloc.cpp105
-rw-r--r--src/lib/netlist/plib/palloc.h513
-rw-r--r--src/lib/netlist/plib/parray.h126
-rw-r--r--src/lib/netlist/plib/pchrono.cpp4
-rw-r--r--src/lib/netlist/plib/pchrono.h52
-rw-r--r--src/lib/netlist/plib/pconfig.h51
-rw-r--r--src/lib/netlist/plib/pdynlib.cpp18
-rw-r--r--src/lib/netlist/plib/pdynlib.h15
-rw-r--r--src/lib/netlist/plib/pexception.cpp215
-rw-r--r--src/lib/netlist/plib/pexception.h214
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp121
-rw-r--r--src/lib/netlist/plib/pfmtlog.h50
-rw-r--r--src/lib/netlist/plib/pfunction.cpp32
-rw-r--r--src/lib/netlist/plib/pfunction.h4
-rw-r--r--src/lib/netlist/plib/plists.h122
-rw-r--r--src/lib/netlist/plib/pmain.cpp13
-rw-r--r--src/lib/netlist/plib/pmain.h20
-rw-r--r--src/lib/netlist/plib/pmatrix2d.h85
-rw-r--r--src/lib/netlist/plib/pmempool.h187
-rw-r--r--src/lib/netlist/plib/pomp.h28
-rw-r--r--src/lib/netlist/plib/poptions.cpp154
-rw-r--r--src/lib/netlist/plib/poptions.h161
-rw-r--r--src/lib/netlist/plib/pparser.cpp278
-rw-r--r--src/lib/netlist/plib/pparser.h107
-rw-r--r--src/lib/netlist/plib/ppmf.h28
-rw-r--r--src/lib/netlist/plib/pstate.cpp35
-rw-r--r--src/lib/netlist/plib/pstate.h67
-rw-r--r--src/lib/netlist/plib/pstream.cpp131
-rw-r--r--src/lib/netlist/plib/pstream.h408
-rw-r--r--src/lib/netlist/plib/pstring.cpp131
-rw-r--r--src/lib/netlist/plib/pstring.h457
-rw-r--r--src/lib/netlist/plib/ptime.h136
-rw-r--r--src/lib/netlist/plib/ptypes.h124
-rw-r--r--src/lib/netlist/plib/putil.cpp75
-rw-r--r--src/lib/netlist/plib/putil.h103
-rw-r--r--src/lib/netlist/plib/vector_ops.h151
-rw-r--r--src/lib/netlist/prg/nltool.cpp374
-rw-r--r--src/lib/netlist/prg/nlwav.cpp591
-rw-r--r--src/lib/netlist/solver/mat_cr.h175
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp937
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h471
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h386
-rw-r--r--src/lib/netlist/solver/nld_ms_direct1.h50
-rw-r--r--src/lib/netlist/solver/nld_ms_direct2.h59
-rw-r--r--src/lib/netlist/solver/nld_ms_direct_lu.h26
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h562
-rw-r--r--src/lib/netlist/solver/nld_ms_gmres.h412
-rw-r--r--src/lib/netlist/solver/nld_ms_sm.h416
-rw-r--r--src/lib/netlist/solver/nld_ms_sor.h112
-rw-r--r--src/lib/netlist/solver/nld_ms_sor_mat.h338
-rw-r--r--src/lib/netlist/solver/nld_ms_w.h165
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp641
-rw-r--r--src/lib/netlist/solver/nld_solver.h178
-rw-r--r--src/lib/netlist/solver/vector_base.h144
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp117
-rw-r--r--src/lib/netlist/tools/nl_convert.h69
202 files changed, 8552 insertions, 11668 deletions
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index aef920635fe..6f4a2db86bf 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -5,49 +5,47 @@
*
*/
-#include "netlist/solver/nld_solver.h"
-#include "netlist/nl_setup.h"
+#include "../solver/nld_solver.h"
#include "nlid_twoterm.h"
-
+#include "../nl_setup.h"
#include <cmath>
namespace netlist
{
-namespace analog
-{
- using constants = plib::constants<nl_double>;
+ namespace analog
+ {
- class diode
+class diode
+{
+public:
+ diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {}
+ diode(const nl_double Is, const nl_double n)
{
- public:
- diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {}
- diode(const nl_double Is, const nl_double n)
- {
- m_Is = Is;
- m_VT = 0.0258 * n;
- m_VT_inv = 1.0 / m_VT;
- }
- void set(const nl_double Is, const nl_double n)
- {
- m_Is = Is;
- m_VT = 0.0258 * n;
- m_VT_inv = 1.0 / m_VT;
- }
- nl_double I(const nl_double V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
- nl_double g(const nl_double V) const { return m_Is * m_VT_inv * std::exp(V * m_VT_inv); }
- nl_double V(const nl_double I) const { return std::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
- nl_double gI(const nl_double I) const { return m_VT_inv * (I + m_Is); }
-
- private:
- nl_double m_Is;
- nl_double m_VT;
- nl_double m_VT_inv;
- };
+ m_Is = Is;
+ m_VT = 0.0258 * n;
+ m_VT_inv = 1.0 / m_VT;
+ }
+ void set(const nl_double Is, const nl_double n)
+ {
+ m_Is = Is;
+ m_VT = 0.0258 * n;
+ m_VT_inv = 1.0 / m_VT;
+ }
+ nl_double I(const nl_double V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
+ nl_double g(const nl_double V) const { return m_Is * m_VT_inv * std::exp(V * m_VT_inv); }
+ nl_double V(const nl_double I) const { return std::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
+ nl_double gI(const nl_double I) const { return m_VT_inv * (I + m_Is); }
- // -----------------------------------------------------------------------------
- // nld_Q - Base classes
- // -----------------------------------------------------------------------------
+private:
+ nl_double m_Is;
+ nl_double m_VT;
+ nl_double m_VT_inv;
+};
+
+// -----------------------------------------------------------------------------
+// nld_Q - Base classes
+// -----------------------------------------------------------------------------
/*! Class representing the bjt model paramers.
*
@@ -75,7 +73,7 @@ namespace analog
* | | RBM | minimum base resistance at high currents | | RB | 10 | * |
* | | RE | emitter resistance | | 0 | 1 | * |
* | | RC | collector resistance | | 0 | 10 | * |
- * | Y | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
* | | VJE | B-E built-in potential | V | 0.75 | 0.6 | |
* | | MJE | B-E junction exponential factor | - | 0.33 | 0.33 | |
* | | TF | ideal forward transit time | sec | 0 | 0.1ns | |
@@ -83,7 +81,7 @@ namespace analog
* | | VTF | voltage describing VBC dependence of TF | V | infinite | | |
* | | ITF | high-current parameter for effect on TF | A | 0 | | * |
* | | PTF | excess phase at freq=1.0/(TF*2PI) Hz | deg | 0 | | |
- * | Y | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
* | | VJC | B-C built-in potential | V | 0.75 | 0.5 | |
* | | MJC | B-C junction exponential factor | - | 0.33 | 0.5 | |
* | | XCJC | fraction of B-C depletion capacitance connected to internal base node | - | 1 | | |
@@ -97,369 +95,343 @@ namespace analog
* | | KF | flicker-noise coefficient | - | 0 | | |
* | | AF | flicker-noise exponent | - | 1 | | |
* | | FC | coefficient for forward-bias depletion capacitance formula | - | 0.5 | | |
- * | | TNOM | Parameter measurement temperature | C | 27 | 50 | |
- * */
+ * | | TNOM | Parameter measurement temperature | C | 27 | 50 | | */
class bjt_model_t : public param_model_t
{
public:
bjt_model_t(device_t &device, const pstring &name, const pstring &val)
: param_model_t(device, name, val)
- , m_IS (*this, "IS")
- , m_BF (*this, "BF")
- , m_NF (*this, "NF")
- , m_BR (*this, "BR")
- , m_NR (*this, "NR")
- , m_CJE(*this, "CJE")
- , m_CJC(*this, "CJC")
+ , m_IS(*this, "IS")
+ , m_BF(*this, "BF")
+ , m_NF(*this, "NF")
+ , m_BR(*this, "BR")
+ , m_NR(*this, "NR")
{}
- value_t m_IS; //!< transport saturation current
- value_t m_BF; //!< ideal maximum forward beta
- value_t m_NF; //!< forward current emission coefficient
- value_t m_BR; //!< ideal maximum reverse beta
- value_t m_NR; //!< reverse current emission coefficient
- value_t m_CJE; //!< B-E zero-bias depletion capacitance
- value_t m_CJC; //!< B-C zero-bias depletion capacitance
-
+ value_t m_IS; //!< transport saturation current
+ value_t m_BF; //!< ideal maximum forward beta
+ value_t m_NF; //!< forward current emission coefficient
+ value_t m_BR; //!< ideal maximum reverse beta
+ value_t m_NR; //!< reverse current emission coefficient
};
// Have a common start for transistors
- NETLIB_OBJECT(Q)
- {
- public:
- enum q_type {
- BJT_NPN,
- BJT_PNP
- };
-
- NETLIB_CONSTRUCTOR(Q)
- , m_model(*this, "MODEL", "NPN")
- , m_qtype(BJT_NPN)
- {
- }
-
- NETLIB_IS_DYNAMIC(true)
-
- //NETLIB_RESETI();
- NETLIB_UPDATEI();
-
- q_type qtype() const { return m_qtype; }
- bool is_qtype(q_type atype) const { return m_qtype == atype; }
- void set_qtype(q_type atype) { m_qtype = atype; }
- protected:
-
- bjt_model_t m_model;
- private:
- q_type m_qtype;
+NETLIB_OBJECT(Q)
+{
+public:
+ enum q_type {
+ BJT_NPN,
+ BJT_PNP
};
- NETLIB_OBJECT_DERIVED(QBJT, Q)
+ NETLIB_CONSTRUCTOR(Q)
+ , m_model(*this, "MODEL", "NPN")
+ , m_qtype(BJT_NPN)
{
- public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
- { }
+ }
- protected:
+ NETLIB_IS_DYNAMIC(true)
- private:
- };
+ //NETLIB_RESETI();
+ NETLIB_UPDATEI();
+
+ inline q_type qtype() const { return m_qtype; }
+ inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
+ inline void set_qtype(q_type atype) { m_qtype = atype; }
+protected:
+ bjt_model_t m_model;
+private:
+ q_type m_qtype;
+};
+NETLIB_OBJECT_DERIVED(QBJT, Q)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
+ { }
+protected:
- // -----------------------------------------------------------------------------
- // nld_QBJT_switch
- // -----------------------------------------------------------------------------
+private:
+};
- /*
- * + - C
- * B ----VVV----+ |
- * | |
- * Rb Rc
- * Rb Rc
- * Rb Rc
- * | |
- * +----+----+
- * |
- * E
- */
- NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
- {
- NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
- , m_RB(*this, "m_RB", true)
- , m_RC(*this, "m_RC", true)
- , m_BC_dummy(*this, "m_BC", true)
- , m_gB(1e-9)
- , m_gC(1e-9)
- , m_V(0.0)
- , m_state_on(*this, "m_state_on", 0)
- {
- register_subalias("B", m_RB.m_P);
- register_subalias("E", m_RB.m_N);
- register_subalias("C", m_RC.m_P);
- //register_term("_E1", m_RC.m_N);
-
- //register_term("_B1", m_BC_dummy.m_P);
- //register_term("_C1", m_BC_dummy.m_N);
-
- connect(m_RB.m_N, m_RC.m_N);
-
- connect(m_RB.m_P, m_BC_dummy.m_P);
- connect(m_RC.m_P, m_BC_dummy.m_N);
- }
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- private:
- nld_twoterm m_RB;
- nld_twoterm m_RC;
-
- // FIXME: this is needed so we have all terminals belong to one net list
-
- nld_twoterm m_BC_dummy;
-
- nl_double m_gB; // base conductance / switch on
- nl_double m_gC; // collector conductance / switch on
- nl_double m_V; // internal voltage source
- state_var<unsigned> m_state_on;
-
- private:
- };
- // -----------------------------------------------------------------------------
- // nld_QBJT_EB
- // -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+// nld_QBJT_switch
+// -----------------------------------------------------------------------------
- NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
+/*
+ * + - C
+ * B ----VVV----+ |
+ * | |
+ * Rb Rc
+ * Rb Rc
+ * Rb Rc
+ * | |
+ * +----+----+
+ * |
+ * E
+ */
+
+NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
+{
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
+ , m_RB(*this, "m_RB", true)
+ , m_RC(*this, "m_RC", true)
+ , m_BC_dummy(*this, "m_BC", true)
+ , m_gB(NETLIST_GMIN_DEFAULT)
+ , m_gC(NETLIST_GMIN_DEFAULT)
+ , m_V(0.0)
+ , m_state_on(*this, "m_state_on", 0)
{
- public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
- , m_gD_BC(*this, "m_D_BC")
- , m_gD_BE(*this, "m_D_BE")
- , m_D_CB(*this, "m_D_CB", true)
- , m_D_EB(*this, "m_D_EB", true)
- , m_D_EC(*this, "m_D_EC", true)
- , m_alpha_f(0)
- , m_alpha_r(0)
- {
- register_subalias("E", m_D_EB.m_P); // Cathode
- register_subalias("B", m_D_EB.m_N); // Anode
-
- register_subalias("C", m_D_CB.m_P); // Cathode
-
- connect(m_D_EB.m_P, m_D_EC.m_P);
- connect(m_D_EB.m_N, m_D_CB.m_N);
- connect(m_D_CB.m_P, m_D_EC.m_N);
-
- if (m_model.m_CJE > 0.0)
- {
- create_and_register_subdevice("m_CJE", m_CJE);
- connect("B", "m_CJE.1");
- connect("E", "m_CJE.2");
- }
- if (m_model.m_CJC > 0.0)
- {
- create_and_register_subdevice("m_CJC", m_CJC);
- connect("B", "m_CJC.1");
- connect("C", "m_CJC.2");
- }
- }
-
- protected:
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- private:
- generic_diode<diode_e::BIPOLAR> m_gD_BC;
- generic_diode<diode_e::BIPOLAR> m_gD_BE;
-
- nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
- nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
- nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
-
- nl_double m_alpha_f;
- nl_double m_alpha_r;
-
- NETLIB_SUBXX(analog, C) m_CJE;
- NETLIB_SUBXX(analog, C) m_CJC;
- };
+ register_subalias("B", m_RB.m_P);
+ register_subalias("E", m_RB.m_N);
+ register_subalias("C", m_RC.m_P);
+ //register_term("_E1", m_RC.m_N);
+ //register_term("_B1", m_BC_dummy.m_P);
+ //register_term("_C1", m_BC_dummy.m_N);
- // ----------------------------------------------------------------------------------------
- // nld_Q
- // ----------------------------------------------------------------------------------------
+ connect(m_RB.m_N, m_RC.m_N);
- NETLIB_UPDATE(Q)
- {
- // netlist().solver()->schedule1();
+ connect(m_RB.m_P, m_BC_dummy.m_P);
+ connect(m_RC.m_P, m_BC_dummy.m_N);
}
- // ----------------------------------------------------------------------------------------
- // nld_QBJT_switch
- // ----------------------------------------------------------------------------------------
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATE_TERMINALSI();
+ nld_twoterm m_RB;
+ nld_twoterm m_RC;
- NETLIB_RESET(QBJT_switch)
- {
- NETLIB_NAME(Q)::reset();
+ // FIXME: this is needed so we have all terminals belong to one net list
- m_state_on = 0;
+ nld_twoterm m_BC_dummy;
- m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
- m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
+protected:
- m_BC_dummy.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
- }
+ nl_double m_gB; // base conductance / switch on
+ nl_double m_gC; // collector conductance / switch on
+ nl_double m_V; // internal voltage source
+ state_var<unsigned> m_state_on;
+
+private:
+};
+
+// -----------------------------------------------------------------------------
+// nld_QBJT_EB
+// -----------------------------------------------------------------------------
- NETLIB_UPDATE(QBJT_switch)
+
+NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
+ , m_gD_BC(*this, "m_D_BC")
+ , m_gD_BE(*this, "m_D_BE")
+ , m_D_CB(*this, "m_D_CB", true)
+ , m_D_EB(*this, "m_D_EB", true)
+ , m_D_EC(*this, "m_D_EC", true)
+ , m_alpha_f(0)
+ , m_alpha_r(0)
{
- if (!m_RB.m_P.net().isRailNet())
- m_RB.m_P.solve_now(); // Basis
- else if (!m_RB.m_N.net().isRailNet())
- m_RB.m_N.solve_now(); // Emitter
- else if (!m_RC.m_P.net().isRailNet())
- m_RC.m_P.solve_now(); // Collector
+ register_subalias("E", m_D_EB.m_P); // Cathode
+ register_subalias("B", m_D_EB.m_N); // Anode
+
+ register_subalias("C", m_D_CB.m_P); // Cathode
+ //register_term("_B1", m_D_CB.m_N); // Anode
+
+ //register_term("_E1", m_D_EC.m_P);
+ //register_term("_C1", m_D_EC.m_N);
+
+ connect(m_D_EB.m_P, m_D_EC.m_P);
+ connect(m_D_EB.m_N, m_D_CB.m_N);
+ connect(m_D_CB.m_P, m_D_EC.m_N);
}
+protected:
- NETLIB_UPDATE_PARAM(QBJT_switch)
- {
- nl_double IS = m_model.m_IS;
- nl_double BF = m_model.m_BF;
- nl_double NF = m_model.m_NF;
- //nl_double VJE = m_model.dValue("VJE", 0.75);
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATE_TERMINALSI();
- set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ generic_diode m_gD_BC;
+ generic_diode m_gD_BE;
- nl_double alpha = BF / (1.0 + BF);
+private:
+ nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
+ nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
+ nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
- diode d(IS, NF);
+ nl_double m_alpha_f;
+ nl_double m_alpha_r;
- // Assume 5mA Collector current for switch operation
+};
- m_V = d.V(0.005 / alpha);
- /* Base current is 0.005 / beta
- * as a rough estimate, we just scale the conductance down */
+// ----------------------------------------------------------------------------------------
+// nld_Q
+// ----------------------------------------------------------------------------------------
- m_gB = 1.0 / (m_V/(0.005 / BF));
+NETLIB_UPDATE(Q)
+{
+// netlist().solver()->schedule1();
+}
- //m_gB = d.gI(0.005 / alpha);
+// ----------------------------------------------------------------------------------------
+// nld_QBJT_switch
+// ----------------------------------------------------------------------------------------
- if (m_gB < exec().gmin())
- m_gB = exec().gmin();
- m_gC = d.gI(0.005); // very rough estimate
- }
- NETLIB_UPDATE_TERMINALS(QBJT_switch)
- {
- const nl_double m = (is_qtype( BJT_NPN) ? 1 : -1);
-
- const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
- if (m_state_on ^ new_state)
- {
- const nl_double gb = new_state ? m_gB : exec().gmin();
- const nl_double gc = new_state ? m_gC : exec().gmin();
- const nl_double v = new_state ? m_V * m : 0;
-
- m_RB.set_G_V_I(gb, v, 0.0);
- m_RC.set_G_V_I(gc, 0.0, 0.0);
- m_state_on = new_state;
- }
- }
+NETLIB_RESET(QBJT_switch)
+{
+ NETLIB_NAME(Q)::reset();
+ m_state_on = 0;
- // ----------------------------------------------------------------------------------------
- // nld_Q - Ebers Moll
- // ----------------------------------------------------------------------------------------
+ m_RB.set(netlist().gmin(), 0.0, 0.0);
+ m_RC.set(netlist().gmin(), 0.0, 0.0);
+ m_BC_dummy.set(netlist().gmin() / 10.0, 0.0, 0.0);
- NETLIB_UPDATE(QBJT_EB)
- {
- if (!m_D_EB.m_P.net().isRailNet())
- m_D_EB.m_P.solve_now(); // Basis
- else if (!m_D_EB.m_N.net().isRailNet())
- m_D_EB.m_N.solve_now(); // Emitter
- else
- m_D_CB.m_N.solve_now(); // Collector
- }
+}
- NETLIB_RESET(QBJT_EB)
- {
- NETLIB_NAME(Q)::reset();
- if (m_CJE)
- {
- m_CJE->reset();
- m_CJE->m_C.setTo(m_model.m_CJE);
- }
- if (m_CJC)
- {
- m_CJC->reset();
- m_CJC->m_C.setTo(m_model.m_CJC);
- }
+NETLIB_UPDATE(QBJT_switch)
+{
+ if (!m_RB.m_P.net().isRailNet())
+ m_RB.m_P.solve_now(); // Basis
+ else if (!m_RB.m_N.net().isRailNet())
+ m_RB.m_N.solve_now(); // Emitter
+ else if (!m_RC.m_P.net().isRailNet())
+ m_RC.m_P.solve_now(); // Collector
+}
- }
- NETLIB_UPDATE_TERMINALS(QBJT_EB)
+NETLIB_UPDATE_PARAM(QBJT_switch)
+{
+ nl_double IS = m_model.m_IS;
+ nl_double BF = m_model.m_BF;
+ nl_double NF = m_model.m_NF;
+ //nl_double VJE = m_model.dValue("VJE", 0.75);
+
+ set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+
+ nl_double alpha = BF / (1.0 + BF);
+
+ diode d(IS, NF);
+
+ // Assume 5mA Collector current for switch operation
+
+ m_V = d.V(0.005 / alpha);
+
+ /* Base current is 0.005 / beta
+ * as a rough estimate, we just scale the conductance down */
+
+ m_gB = 1.0 / (m_V/(0.005 / BF));
+
+ //m_gB = d.gI(0.005 / alpha);
+
+ if (m_gB < netlist().gmin())
+ m_gB = netlist().gmin();
+ m_gC = d.gI(0.005); // very rough estimate
+}
+
+NETLIB_UPDATE_TERMINALS(QBJT_switch)
+{
+ const nl_double m = (is_qtype( BJT_NPN) ? 1 : -1);
+
+ const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
+ if (m_state_on ^ new_state)
{
- const nl_double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
-
- m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
- m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
-
- const nl_double gee = m_gD_BE.G();
- const nl_double gcc = m_gD_BC.G();
- const nl_double gec = m_alpha_r * gcc;
- const nl_double gce = m_alpha_f * gee;
- const nl_double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I();
- const nl_double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I();
- const nl_double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity;
- const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
-
- m_D_EB.set_mat( gee, gec - gee, -Ie,
- gce - gee, gee - gec, Ie);
- m_D_CB.set_mat( gcc, gce - gcc, -Ic,
- gec - gcc, gcc - gce, Ic);
- m_D_EC.set_mat( 0, -gec, 0,
- -gce, 0, 0);
+ const nl_double gb = new_state ? m_gB : netlist().gmin();
+ const nl_double gc = new_state ? m_gC : netlist().gmin();
+ const nl_double v = new_state ? m_V * m : 0;
+
+ m_RB.set(gb, v, 0.0);
+ m_RC.set(gc, 0.0, 0.0);
+ m_state_on = new_state;
}
+}
- NETLIB_UPDATE_PARAM(QBJT_EB)
- {
- nl_double IS = m_model.m_IS;
- nl_double BF = m_model.m_BF;
- nl_double NF = m_model.m_NF;
- nl_double BR = m_model.m_BR;
- nl_double NR = m_model.m_NR;
- //nl_double VJE = m_model.dValue("VJE", 0.75);
+// ----------------------------------------------------------------------------------------
+// nld_Q - Ebers Moll
+// ----------------------------------------------------------------------------------------
- set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
- m_alpha_f = BF / (1.0 + BF);
- m_alpha_r = BR / (1.0 + BR);
+NETLIB_UPDATE(QBJT_EB)
+{
+ if (!m_D_EB.m_P.net().isRailNet())
+ m_D_EB.m_P.solve_now(); // Basis
+ else if (!m_D_EB.m_N.net().isRailNet())
+ m_D_EB.m_N.solve_now(); // Emitter
+ else
+ m_D_CB.m_N.solve_now(); // Collector
+}
+
+NETLIB_RESET(QBJT_EB)
+{
+ NETLIB_NAME(Q)::reset();
+}
- m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin(), constants::T0());
- m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin(), constants::T0());
- }
+NETLIB_UPDATE_TERMINALS(QBJT_EB)
+{
+ const nl_double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
+
+ m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
+ m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
+
+ const nl_double gee = m_gD_BE.G();
+ const nl_double gcc = m_gD_BC.G();
+ const nl_double gec = m_alpha_r * gcc;
+ const nl_double gce = m_alpha_f * gee;
+ const nl_double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I();
+ const nl_double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I();
+ const nl_double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity;
+ const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
+
+ m_D_EB.set_mat( gee, gec - gee, -Ie,
+ gce - gee, gee - gec, Ie);
+ m_D_CB.set_mat( gcc, gce - gcc, -Ic,
+ gec - gcc, gcc - gce, Ic);
+ m_D_EC.set_mat( 0, -gec, 0,
+ -gce, 0, 0);
+}
+
+
+NETLIB_UPDATE_PARAM(QBJT_EB)
+{
+ nl_double IS = m_model.m_IS;
+ nl_double BF = m_model.m_BF;
+ nl_double NF = m_model.m_NF;
+ nl_double BR = m_model.m_BR;
+ nl_double NR = m_model.m_NR;
+ //nl_double VJE = m_model.dValue("VJE", 0.75);
-} // namespace analog
+ set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
-namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB, "QBJT_EB", "MODEL")
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch, "QBJT_SW", "MODEL")
-} // namespace devices
+ m_alpha_f = BF / (1.0 + BF);
+ m_alpha_r = BR / (1.0 + BR);
+
+ m_gD_BE.set_param(IS / m_alpha_f, NF, netlist().gmin());
+ m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin());
+}
+
+ } //namespace analog
+
+ namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB)
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_bjt.h b/src/lib/netlist/analog/nld_bjt.h
index 3a8478f19f7..9e1f82afbaa 100644
--- a/src/lib/netlist/analog/nld_bjt.h
+++ b/src/lib/netlist/analog/nld_bjt.h
@@ -8,7 +8,7 @@
#ifndef NLD_BJT_H_
#define NLD_BJT_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_fourterm.h b/src/lib/netlist/analog/nld_fourterm.h
index 66c47c0be29..b4bb5db1059 100644
--- a/src/lib/netlist/analog/nld_fourterm.h
+++ b/src/lib/netlist/analog/nld_fourterm.h
@@ -9,7 +9,7 @@
#define NLD_FOURTERM_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp
deleted file mode 100644
index ea717fdefee..00000000000
--- a/src/lib/netlist/analog/nld_mosfet.cpp
+++ /dev/null
@@ -1,488 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * 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 "netlist/solver/nld_solver.h"
-#include "netlist/nl_setup.h"
-#include "nlid_twoterm.h"
-
-#include <cmath>
-
-#define BODY_CONNECTED_TO_SOURCE (1)
-
-namespace netlist
-{
-namespace analog
-{
-
- using constants = plib::constants<nl_double>;
-
- // -----------------------------------------------------------------------------
- // nld_FET - Base classes
- // -----------------------------------------------------------------------------
-
- /*! Class representing the nmos model paramers.
- *
- * This is the model representation of the nmos model. Typically, SPICE uses
- * the following parameters. A "Y" in the first column indicates that the
- * parameter is actually used in netlist.
- *
- * | NL? |Name | Description|Units |Default |Example |
- * |:---:|------|-----------------------------------------------------------------------|-------|---------:|----------------:|
- * | Y |Vto | Zero-bias threshold voltage | V | 0 | 1 |
- * | Y |Kp | Transconductance parameter | A/V² | 0.00002 | 0.00003 |
- * | Y |Gamma | Bulk threshold parameter | V^½ | 0 | 0.37 |
- * | Y |Phi | Surface inversion potential | V | 0.6 | 0.65 |
- * | Y |Lambda| Channel-length modulation (level 1 and 2 only) | 1/V | 0 | 0.02 |
- * | |Rd | Drain ohmic resistance |W|0|1|
- * | |Rs | Source ohmic resistance |W|0|1|
- * | |Cbd | Zero-bias B-D junction capacitance |F|0|20f|
- * | |Cbs | Zero-bias B-S junction capacitance |F|0|20f|
- * | Y |Is | Bulk junction saturation current |A|0.00000000000001|1E-015|
- * | Y |N | Bulk diode emission coefficient |-|1|*
- * | |Pb | Bulk junction potential |V|0.8|0.87|8|
- * | |Cgso | Gate-source overlap capacitance per meter channel width |F/m|0|0.00000000004|
- * | |Cgdo | Gate-drain overlap capacitance per meter channel width |F/m|0|0.00000000004|*
- * | |Cgbo | Gate-bulk overlap capacitance per meter channel width |F/m|0|0.0000000002|*
- * | |Rsh | Drain and source diffusion sheet resistance |W|0|10|*
- * | |Cj | Zero-bias bulk junction bottom capacitance per square meter of junction area|F/m²|0|0.0002|*
- * | |Mj | Bulk junction bottom grading coefficient |-|0.5|0.5|*
- * | |Cjsw | Zero-bias bulk junction sidewall capacitance per meter of junction perimeter|F/m|0|1p|*
- * | |Mjsw | Bulk junction sidewall grading coefficient |-|.50 level 1 .33 level 2,3||
- * | |Js | Bulk junction saturation current per square-meter of junction area|A/m|0|0.00000001|
- * | Y |Tox | Oxide thickness |m|0.0000001|0.0000001|
- * | Y |Nsub | Substrate doping |1/cm³|0|4000000000000000|
- * | |Nss | Surface state density |1/cm²|0|10000000000|
- * | |Nfs | Fast surface state |1/cm²|0|10000000000|*
- * | |TPG | Type of gate material: +1 opp. to substrate -1 same as substrate 0 Al gate|-|1|
- * | |Xj | Metallurgical junction depth |m|0|1µ|*
- * | Y |Ld | Lateral diffusion |m|0|0.8µ|
- * | Y |Uo | Surface mobility |cm²/V/s|600|700|
- * | |Ucrit | Critical field for mobility degradation (level 2 only) |V/cm|10000|10000|
- * | |Uexp | Critical field exponent in mobility degradation (level 2 only) |-|0|0.1|
- * | |Utra | Transverse field coefficient (level 2 only) |-|0|0.3|*
- * | |Vmax | Maximum carrier drift velocity (levels 2 & 3 only) |m/s|0|50000|
- * | |Neff | Total channel-charge exponent (level 2 only) |-|1|5|
- * | |Kf | Flicker noise coefficient |-|0|1E-026|
- * | |Af | Flicker noise exponent |-|1|1.2|
- * | |Fc | Coefficient for forward-bias depletion capacitance formula |-|0.5|
- * | |Delta | Width effect on threshold voltage(levels 2 and 3) |-|0|1|
- * | |Theta | Mobility modulation (level 3 only) |-|0|0.1|
- * | |Eta | Static feedback (level 3 only) |-|0|1|
- * | |Kappa | Saturation field (level 3 only) |0.2|0.5|
- * | |Tnom | Parameter measurement temperature |ºC|27|50||
- * | Y |L | Length scaling |-|1.0||
- * | Y |W | Width scaling |-|1.0||
- * */
-
- class fet_model_t : public param_model_t
- {
- public:
- fet_model_t(device_t &device, const pstring &name, const pstring &val)
- : param_model_t(device, name, val)
- , m_VTO(*this, "VTO")
- , m_N(*this, "N")
- , m_ISS(*this, "IS") // Haven't seen a model using ISS / ISD
- , m_ISD(*this, "IS")
- , m_LD(*this, "LD")
- , m_L(*this, "L")
- , m_W(*this, "W")
- , m_TOX(*this, "TOX")
- , m_KP(*this, "KP")
- , m_UO(*this, "UO")
- , m_PHI(*this, "PHI")
- , m_NSUB(*this, "NSUB")
- , m_GAMMA(*this, "GAMMA")
- , m_LAMBDA(*this, "LAMBDA")
- , m_RD(*this, "RD")
- , m_RS(*this, "RS")
- {}
-
- value_t m_VTO; //!< Threshold voltage [V]
- value_t m_N; //!< Bulk diode emission coefficient
- value_t m_ISS; //!< Body diode saturation current
- value_t m_ISD; //!< Body diode saturation current
- value_t m_LD; //!< Lateral diffusion [m]
- value_t m_L; //!< Length scaling
- value_t m_W; //!< Width scaling
- value_t m_TOX; //!< Oxide thickness
- value_t m_KP; //!< Transconductance parameter [A/V²]
- value_t m_UO; //!< Surface mobility [cm²/V/s]
- value_t m_PHI; //!< Surface inversion potential [V]
- value_t m_NSUB;//!< Substrate doping [1/cm³]
- value_t m_GAMMA; //!< Bulk threshold parameter [V^½]
- value_t m_LAMBDA; //!< Channel-length modulation [1/V]
- value_t m_RD; //!< Drain ohmic resistance
- value_t m_RS; //!< Source ohmic resistance
- };
-
- // Have a common start for mosfets
-
- NETLIB_OBJECT(FET)
- {
- public:
- enum q_type {
- FET_NMOS,
- FET_PMOS
- };
-
- NETLIB_CONSTRUCTOR(FET)
- , m_model(*this, "MODEL", "NMOS")
- , m_qtype(FET_NMOS)
- {
- }
-
- NETLIB_IS_DYNAMIC(true)
-
- //NETLIB_RESETI();
- NETLIB_UPDATEI() { }
-
- q_type qtype() const { return m_qtype; }
- bool is_qtype(q_type atype) const { return m_qtype == atype; }
- void set_qtype(q_type atype) { m_qtype = atype; }
- protected:
-
- fet_model_t m_model;
- private:
- q_type m_qtype;
- };
-
- // -----------------------------------------------------------------------------
- // nld_QBJT_EB
- // -----------------------------------------------------------------------------
-
-
- NETLIB_OBJECT_DERIVED(MOSFET, FET)
- {
- public:
- NETLIB_CONSTRUCTOR_DERIVED(MOSFET, FET)
- , m_DG(*this, "m_DG", true)
- , m_SG(*this, "m_SG", true)
- , m_SD(*this, "m_SD", true)
- , m_D_BD(*this, "m_D_BD")
-#if (!BODY_CONNECTED_TO_SOURCE)
- , m_D_BS(*this, "m_D_BS")
-#endif
- , m_phi(0.0)
- , m_gamma(0.0)
- , m_vto(0.0)
- , m_beta(0.0)
- , m_lambda(0.0)
- , m_Leff(0.0)
- , m_Cox(0.0)
- {
- register_subalias("S", m_SG.m_P); // Source
- register_subalias("G", m_SG.m_N); // Gate
-
- register_subalias("D", m_DG.m_P); // Drain
-
- connect(m_SG.m_P, m_SD.m_P);
- connect(m_SG.m_N, m_DG.m_N);
- connect(m_DG.m_P, m_SD.m_N);
-
-#if 0
- if (m_model.m_CJE > 0.0)
- {
- create_and_register_subdevice("m_CJE", m_CJE);
- connect("B", "m_CJE.1");
- connect("E", "m_CJE.2");
- }
- if (m_model.m_CJC > 0.0)
- {
- create_and_register_subdevice("m_CJC", m_CJC);
- connect("B", "m_CJC.1");
- connect("C", "m_CJC.2");
- }
-#endif
- }
-
- protected:
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- private:
-
- nld_twoterm m_DG;
- nld_twoterm m_SG;
- nld_twoterm m_SD;
-
- generic_diode<diode_e::MOS> m_D_BD;
-#if (!BODY_CONNECTED_TO_SOURCE)
- generic_diode<diode_e::MOS> m_D_BS;
-#endif
-
- nl_double m_phi;
- nl_double m_gamma;
- nl_double m_vto;
- nl_double m_beta;
- nl_double m_lambda;
-
- /* used in capacitance calculation */
- nl_double m_Leff;
- nl_double m_Cox;
-
- //NETLIB_SUBXX(analog, C) m_CJE;
- //NETLIB_SUBXX(analog, C) m_CJC;
- };
-
-
-
- // ----------------------------------------------------------------------------------------
- // nld_Q - Ebers Moll
- // ----------------------------------------------------------------------------------------
-
-
- NETLIB_UPDATE(MOSFET)
- {
- if (!m_SG.m_P.net().isRailNet())
- m_SG.m_P.solve_now(); // Basis
- else if (!m_SG.m_N.net().isRailNet())
- m_SG.m_N.solve_now(); // Emitter
- else
- m_DG.m_N.solve_now(); // Collector
- }
-
- NETLIB_RESET(MOSFET)
- {
- NETLIB_NAME(FET)::reset();
-#if 0
- if (m_CJE)
- {
- m_CJE->reset();
- m_CJE->m_C.setTo(m_model.m_CJE);
- }
- if (m_CJC)
- {
- m_CJC->reset();
- m_CJC->m_C.setTo(m_model.m_CJC);
- }
-#endif
- }
-
- NETLIB_UPDATE_TERMINALS(MOSFET)
- {
- const nl_double polarity = (qtype() == FET_NMOS ? 1.0 : -1.0);
-
- const nl_double Ugd = -m_DG.deltaV() * polarity; // Gate - Drain
- const nl_double Ugs = -m_SG.deltaV() * polarity; // Gate - Source
- const nl_double Ubs = 0.0; // Bulk - Source == 0 if connected
- const nl_double Ubd = m_SD.deltaV() * polarity; // Bulk - Drain = Source - Drain
- const nl_double Uds = Ugs - Ugd;
-
-#if (!BODY_CONNECTED_TO_SOURCE)
- m_D_BS.update_diode(Ubs);
-#endif
- m_D_BD.update_diode(Ubd);
-
- // Are we in forward mode ?
- const bool is_forward = Uds >= 0;
-
- // calculate Vth
- const nl_double Vbulk = is_forward ? Ubs : Ubd;
- const nl_double phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : 0.0;
- const nl_double Vth = m_vto * polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi));
-
- const nl_double Vctrl = (is_forward ? Ugs : Ugd) - Vth;
-
- nl_double Ids, gm, gds, gmb;
-
- if (Vctrl <= 0.0)
- {
- // cutoff region
- Ids = 0.0;
- gm = 0.0;
- gds = 0.0;
- gmb = 0.0;
- }
- else
- {
- const nl_double Vds = std::abs(Uds);
- const nl_double b = m_beta * (1.0 + m_lambda * Vds);
- if (Vctrl <= Vds)
- {
- // saturation region
- Ids = b * Vctrl * Vctrl / 2.0;
- gm = b * Vctrl;
- gds = m_lambda * m_beta * Vctrl * Vctrl / 2.0;
- }
- else
- {
- // linear region
- Ids = b * Vds * (Vctrl - Vds / 2);
- gm = b * Vds;
- gds = b * (Vctrl - Vds) + m_lambda * m_beta * Vds * (Vctrl - Vds / 2.0);
- }
-
- // backgate transconductance
- const nl_double bgtc = (phi_m_Vbulk != 0.0) ? (m_gamma / phi_m_Vbulk / 2.0) : 0.0;
- gmb = gm * bgtc;
- }
-
- // FIXME: these are needed to compute capacitance
- // nl_double Udsat = pol * std::max (Utst, 0.0);
- // Uon = pol * Vth;
-
- // compute bulk diode equivalent currents
-
- const nl_double IeqBD = m_D_BD.Ieq();
- const nl_double gbd = m_D_BD.G();
-#if 0
- const nl_double IeqBS = m_D_BS.Ieq();
- const nl_double gbs = m_D_BS.G();
-#else
- const nl_double IeqBS = 0.0;
- const nl_double gbs = 0.0;
-#endif
- // exchange controlling nodes if necessary
- const nl_double gsource = is_forward ? (gm + gmb) : 0;
- const nl_double gdrain = is_forward ? 0.0 : (gm + gmb);
-
- const nl_double IeqDS = (is_forward) ?
- Ids - gm * Ugs - gmb * Ubs - gds * Uds
- : -Ids - gm * Ugd - gmb * Ubd - gds * Uds;
-
- // IG = 0
- const nl_double IG = 0.0;
- const nl_double ID = (+IeqBD - IeqDS) * polarity;
- const nl_double IS = (+IeqBS + IeqDS) * polarity;
- const nl_double IB = (-IeqBD - IeqBS) * polarity;
-
- const nl_double gGG = 0.0; // ok
- const nl_double gGD = 0.0; // ok
- const nl_double gGS = 0.0; // ok
- const nl_double gGB = 0.0; // ok
-
- const nl_double gDG = gm; // ok
- const nl_double gDD = gds + gbd - gdrain; // ok
- const nl_double gDS = -gds - gsource; // ok
- const nl_double gDB = gmb - gbd; // ok
-
- const nl_double gSG = -gm; // ok
- const nl_double gSD = -gds + gdrain; // ok
- const nl_double gSS = gbs + gds + gsource; // ok
- const nl_double gSB = -gbs - gmb;
-
- const nl_double gBG = 0.0; // ok
- const nl_double gBD = -gbd; // ok
- const nl_double gBS = -gbs;
- const nl_double gBB = gbs + gbd; // ok
-
- // Source connected to body, Diode S-B shorted!
- const nl_double gSSBB = gSS + gBB + gBS + gSB;
-
- // S G
- m_SG.set_mat( gSSBB, gSG + gBG, +(IS + IB), // S
- gGS + gGB, gGG, IG ); // G
- // D G
- m_DG.set_mat( gDD, gDG, +ID, // D
- gGD, 0.0, 0.0 ); // G
- // S D
- m_SD.set_mat( 0.0, gSD + gBD, 0.0, // S
- gDS + gDB, 0.0, 0.0); // D
-
- }
-
-
- NETLIB_UPDATE_PARAM(MOSFET)
- {
- set_qtype((m_model.model_type() == "NMOS") ? FET_NMOS : FET_PMOS);
-
- /*
- * From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm :
- *
- * VTO, KP, LAMBDA, PHI and GAMMA. These parameters are computed
- * if the process parameters(NSUB, TOX,...) are given, but
- * user-specified values always override.
- *
- * But couldn't find a formula for lambda anywhere
- *
- */
-
- m_lambda = m_model.m_LAMBDA; // FIXME: m_lambda only set once
-
- // calculate effective channel length
- m_Leff = m_model.m_L - 2 * m_model.m_LD;
- nl_assert_always(m_Leff > 0.0, "Effective Lateral diffusion would be negative for model " + m_model.name());
- if (m_model.m_TOX > 0.0)
- m_Cox = (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX);
- else
- m_Cox = 0.0;
-
- // calculate DC transconductance coefficient
- if (m_model.m_KP > 0)
- m_beta = m_model.m_KP * m_model.m_W / m_Leff;
- else if (m_Cox > 0 && m_model.m_UO > 0)
- m_beta = m_model.m_UO * 1e-4 * m_Cox * m_model.m_W / m_Leff;
- else
- m_beta = 2e-5 * m_model.m_W / m_Leff;
-
- // Bulk diodes
-
- m_D_BD.set_param(m_model.m_ISD, m_model.m_N, exec().gmin(), constants::T0());
-#if (!BODY_CONNECTED_TO_SOURCE)
- m_D_BS.set_param(m_model.m_ISS, m_model.m_N, exec().gmin(), constants::T0());
-#endif
-
- //FIXME::UT can disappear
- const double Vt = constants::T0() * constants::k_b() / constants::Q_e();
-
- // calculate surface potential if not given
-
- if (m_model.m_PHI > 0.0)
- m_phi = m_model.m_PHI;
- else if (m_model.m_NSUB > 0.0)
- {
- nl_assert_always(m_model.m_NSUB * 1e6 >= constants::NiSi(), "Error calculating phi for model " + m_model.name());
- m_phi = 2 * Vt * std::log (m_model.m_NSUB * 1e6 / constants::NiSi());
- }
- else
- m_phi = 0.6;
-
- // calculate bulk threshold if not given
- if (m_model.m_GAMMA > 0.0)
- m_gamma = m_model.m_GAMMA;
- else
- {
- if (m_Cox > 0 && m_model.m_NSUB > 0)
- m_gamma = std::sqrt (2.0 * constants::Q_e() * constants::eps_Si() * constants::eps_0() * m_model.m_NSUB * 1e6) / m_Cox;
- else
- m_gamma = 0.0;
- }
-
- m_vto = m_model.m_VTO;
- nl_assert_always(m_vto != 0.0, "Threshold voltage not specified for " + m_model.name());
-
- /* FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models
- * specify VTO so skip this here.
- */
-
- m_Cox = m_Cox * m_model.m_W * m_Leff;
-
- }
-
-} // namespace analog
-
-namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, MOSFET, "MOSFET", "MODEL")
-} // namespace devices
-
-} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_mosfet.h b/src/lib/netlist/analog/nld_mosfet.h
deleted file mode 100644
index 32011d709d8..00000000000
--- a/src/lib/netlist/analog/nld_mosfet.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * nld_mosfet.h
- *
- */
-
-#ifndef NLD_MOSFET_H_
-#define NLD_MOSFET_H_
-
-#include "netlist/nl_setup.h"
-
-// -----------------------------------------------------------------------------
-// Macros
-// -----------------------------------------------------------------------------
-
-#define MOSFET(name, model) \
- NET_REGISTER_DEV(MOSFET, name) \
- NETDEV_PARAMI(name, MODEL, model)
-
-#endif /* NLD_MOSFET_H_ */
diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp
index 8c3c655bfa9..5f55a26f5d0 100644
--- a/src/lib/netlist/analog/nld_opamps.cpp
+++ b/src/lib/netlist/analog/nld_opamps.cpp
@@ -6,10 +6,10 @@
*/
#include "nld_opamps.h"
-#include "netlist/nl_base.h"
-#include "netlist/nl_errstr.h"
-#include "nlid_fourterm.h"
+#include "../nl_base.h"
+#include "../nl_errstr.h"
#include "nlid_twoterm.h"
+#include "nlid_fourterm.h"
#include <cmath>
@@ -129,10 +129,10 @@ namespace netlist
}
else if (m_type == 3)
{
- create_and_register_subdevice("CP1", m_CP);
- create_and_register_subdevice("EBUF", m_EBUF);
- create_and_register_subdevice("DN", m_DN, "D(IS=1e-15 N=1)");
- create_and_register_subdevice("DP", m_DP, "D(IS=1e-15 N=1)");
+ register_sub("CP1", m_CP);
+ register_sub("EBUF", m_EBUF);
+ register_sub("DN", m_DN, "D(IS=1e-15 N=1)");
+ register_sub("DP", m_DP, "D(IS=1e-15 N=1)");
//m_DP->m_model.setTo("D(IS=1e-15 N=1)");
//m_DN->m_model.setTo("D(IS=1e-15 N=1)");
@@ -201,7 +201,7 @@ namespace netlist
NETLIB_RESET(opamp)
{
- m_G1.reset();
+ m_G1.do_reset();
m_G1.m_RI.setTo(m_model.m_RI);
if (m_type == 1)
@@ -213,11 +213,11 @@ namespace netlist
}
else if (m_type == 3)
{
- m_EBUF->reset();
- m_DP->reset();
- m_DN->reset();
- m_CP->reset();
- m_RP.reset();
+ m_EBUF->do_reset();
+ m_DP->do_reset();
+ m_DN->do_reset();
+ m_CP->do_reset();
+ m_RP.do_reset();
m_EBUF->m_G.setTo(1.0);
m_EBUF->m_RO.setTo(m_model.m_RO);
@@ -239,6 +239,6 @@ namespace netlist
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, opamp, "OPAMP", "MODEL")
- } // namespace devices
+ NETLIB_DEVICE_IMPL_NS(analog, opamp)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_opamps.h b/src/lib/netlist/analog/nld_opamps.h
index 4a07f646587..d05a19aa3dc 100644
--- a/src/lib/netlist/analog/nld_opamps.h
+++ b/src/lib/netlist/analog/nld_opamps.h
@@ -10,7 +10,7 @@
#ifndef NLD_OPAMPS_H_
#define NLD_OPAMPS_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp
index 0e62fe13952..1575551f260 100644
--- a/src/lib/netlist/analog/nld_switches.cpp
+++ b/src/lib/netlist/analog/nld_switches.cpp
@@ -6,13 +6,10 @@
*/
#include "nlid_twoterm.h"
-#include "netlist/nl_base.h"
-#include "netlist/nl_factory.h"
-#include "netlist/solver/nld_solver.h"
+#include "../nl_base.h"
+#include "../nl_factory.h"
-/* FIXME : convert to parameters */
-
-#define R_OFF (1.0 / exec().gmin())
+#define R_OFF (1.0 / netlist().gmin())
#define R_ON 0.01
namespace netlist
@@ -27,7 +24,7 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(switch1)
, m_R(*this, "R")
- , m_POS(*this, "POS", false)
+ , m_POS(*this, "POS", 0)
{
register_subalias("1", m_R.m_P);
register_subalias("2", m_R.m_N);
@@ -49,11 +46,6 @@ namespace netlist
NETLIB_UPDATE(switch1)
{
- }
-
- NETLIB_UPDATE_PARAM(switch1)
- {
- m_R.solve_now();
if (!m_POS())
{
m_R.set_R(R_OFF);
@@ -62,8 +54,13 @@ namespace netlist
{
m_R.set_R(R_ON);
}
- m_R.solve_later();
+ m_R.update_dev();
+ }
+
+ NETLIB_UPDATE_PARAM(switch1)
+ {
+ update();
}
// ----------------------------------------------------------------------------------------
@@ -75,7 +72,7 @@ namespace netlist
NETLIB_CONSTRUCTOR(switch2)
, m_R1(*this, "R1")
, m_R2(*this, "R2")
- , m_POS(*this, "POS", false)
+ , m_POS(*this, "POS", 0)
{
connect(m_R1.m_N, m_R2.m_N);
@@ -113,31 +110,19 @@ namespace netlist
m_R2.set_R(R_ON);
}
- //m_R1.update_dev(time);
- //m_R2.update_dev(time);
+ m_R1.update_dev();
+ m_R2.update_dev();
}
NETLIB_UPDATE_PARAM(switch2)
{
- if (!m_POS())
- {
- m_R1.set_R(R_ON);
- m_R2.set_R(R_OFF);
- }
- else
- {
- m_R1.set_R(R_OFF);
- m_R2.set_R(R_ON);
- }
-
- m_R1.solve_now();
- m_R2.solve_now();
+ update();
}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, switch1, "SWITCH", "")
- NETLIB_DEVICE_IMPL_NS(analog, switch2, "SWITCH2", "")
- } // namespace devices
+ NETLIB_DEVICE_IMPL_NS(analog, switch1)
+ NETLIB_DEVICE_IMPL_NS(analog, switch2)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_switches.h b/src/lib/netlist/analog/nld_switches.h
index 7aa31c925ae..3cd561f84b1 100644
--- a/src/lib/netlist/analog/nld_switches.h
+++ b/src/lib/netlist/analog/nld_switches.h
@@ -10,7 +10,7 @@
#ifndef NLD_SWITCHES_H_
#define NLD_SWITCHES_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index b175f40af97..d5cf6f6d228 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -4,7 +4,7 @@
#ifndef NLD_TWOTERM_H_
#define NLD_TWOTERM_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nlid_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp
index 7fa6a2f3809..aa2723fe8e1 100644
--- a/src/lib/netlist/analog/nlid_fourterm.cpp
+++ b/src/lib/netlist/analog/nlid_fourterm.cpp
@@ -5,8 +5,8 @@
*
*/
-#include "netlist/solver/nld_solver.h"
-#include "netlist/nl_factory.h"
+#include "../solver/nld_solver.h"
+#include "../nl_factory.h"
#include "nlid_fourterm.h"
#include <cmath>
@@ -24,16 +24,16 @@ namespace netlist
NETLIB_RESET(VCCS)
{
const nl_double m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A
- const nl_double GI = plib::constants<nl_double>::one() / m_RI();
+ const nl_double GI = NL_FCONST(1.0) / m_RI();
- m_IP.set_conductivity(GI);
- m_IN.set_conductivity(GI);
+ m_IP.set(GI);
+ m_IN.set(GI);
- m_OP.set_go_gt(-m_mult, plib::constants<nl_double>::zero());
- m_OP1.set_go_gt(m_mult, plib::constants<nl_double>::zero());
+ m_OP.set(m_mult, NL_FCONST(0.0));
+ m_OP1.set(-m_mult, NL_FCONST(0.0));
- m_ON.set_go_gt(m_mult, plib::constants<nl_double>::zero());
- m_ON1.set_go_gt(-m_mult, plib::constants<nl_double>::zero());
+ m_ON.set(-m_mult, NL_FCONST(0.0));
+ m_ON1.set(m_mult, NL_FCONST(0.0));
}
NETLIB_UPDATE(VCCS)
@@ -63,6 +63,11 @@ NETLIB_UPDATE_PARAM(LVCCS)
NETLIB_NAME(VCCS)::update_param();
}
+NETLIB_UPDATE(LVCCS)
+{
+ NETLIB_NAME(VCCS)::update();
+}
+
NETLIB_UPDATE_TERMINALS(LVCCS)
{
const nl_double m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A
@@ -79,11 +84,11 @@ NETLIB_UPDATE_TERMINALS(LVCCS)
const nl_double beta = m_mult * (1.0 - X*X);
const nl_double I = m_cur_limit() * X - beta * m_vi;
- m_OP.set_go_gt_I(-beta, plib::constants<nl_double>::zero(), I);
- m_OP1.set_go_gt(beta, plib::constants<nl_double>::zero());
+ m_OP.set(beta, NL_FCONST(0.0), I);
+ m_OP1.set(-beta, NL_FCONST(0.0));
- m_ON.set_go_gt_I(beta, plib::constants<nl_double>::zero(), -I);
- m_ON1.set_go_gt(-beta, plib::constants<nl_double>::zero());
+ m_ON.set(-beta, NL_FCONST(0.0), -I);
+ m_ON1.set(beta, NL_FCONST(0.0));
}
// ----------------------------------------------------------------------------------------
@@ -100,25 +105,30 @@ NETLIB_UPDATE_PARAM(CCCS)
NETLIB_NAME(VCCS)::update_param();
}
+NETLIB_UPDATE(CCCS)
+{
+ NETLIB_NAME(VCCS)::update();
+}
+
// ----------------------------------------------------------------------------------------
// nld_VCVS
// ----------------------------------------------------------------------------------------
NETLIB_RESET(VCVS)
{
- m_gfac = plib::constants<nl_double>::one() / m_RO();
+ m_gfac = NL_FCONST(1.0) / m_RO();
NETLIB_NAME(VCCS)::reset();
- m_OP2.set_conductivity(plib::constants<nl_double>::one() / m_RO());
- m_ON2.set_conductivity(plib::constants<nl_double>::one() / m_RO());
+ m_OP2.set(NL_FCONST(1.0) / m_RO());
+ m_ON2.set(NL_FCONST(1.0) / m_RO());
}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, VCVS, "VCVS", "")
- NETLIB_DEVICE_IMPL_NS(analog, VCCS, "VCCS", "")
- NETLIB_DEVICE_IMPL_NS(analog, CCCS, "CCCS", "")
- NETLIB_DEVICE_IMPL_NS(analog, LVCCS, "LVCCS", "")
- } // namespace devices
+ NETLIB_DEVICE_IMPL_NS(analog, VCVS)
+ NETLIB_DEVICE_IMPL_NS(analog, VCCS)
+ NETLIB_DEVICE_IMPL_NS(analog, CCCS)
+ NETLIB_DEVICE_IMPL_NS(analog, LVCCS)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h
index 5ca6a747116..641fc72427b 100644
--- a/src/lib/netlist/analog/nlid_fourterm.h
+++ b/src/lib/netlist/analog/nlid_fourterm.h
@@ -8,8 +8,7 @@
#ifndef NLID_FOURTERM_H_
#define NLID_FOURTERM_H_
-#include "netlist/nl_base.h"
-#include "plib/putil.h"
+#include "../nl_base.h"
namespace netlist {
namespace analog {
@@ -41,32 +40,39 @@ namespace netlist {
NETLIB_CONSTRUCTOR(VCCS)
, m_G(*this, "G", 1.0)
, m_RI(*this, "RI", 1e9)
- , m_OP(*this, "OP", &m_IP)
- , m_ON(*this, "ON", &m_IP)
- , m_IP(*this, "IP", &m_IN) // <= this should be NULL and terminal be filtered out prior to solving...
- , m_IN(*this, "IN", &m_IP) // <= this should be NULL and terminal be filtered out prior to solving...
- , m_OP1(*this, "_OP1", &m_IN)
- , m_ON1(*this, "_ON1", &m_IN)
+ , m_OP(*this, "OP")
+ , m_ON(*this, "ON")
+ , m_IP(*this, "IP")
+ , m_IN(*this, "IN")
+ , m_OP1(*this, "_OP1")
+ , m_ON1(*this, "_ON1")
, m_gfac(1.0)
{
+ m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
+ m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
+
+ m_OP.m_otherterm = &m_IP;
+ m_OP1.m_otherterm = &m_IN;
+
+ m_ON.m_otherterm = &m_IP;
+ m_ON1.m_otherterm = &m_IN;
+
connect(m_OP, m_OP1);
connect(m_ON, m_ON1);
- m_gfac = plib::constants<nl_double>::one();
+ m_gfac = NL_FCONST(1.0);
}
- NETLIB_RESETI();
-
param_double_t m_G;
param_double_t m_RI;
protected:
+ NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI()
{
NETLIB_NAME(VCCS)::reset();
}
-
terminal_t m_OP;
terminal_t m_ON;
@@ -92,14 +98,14 @@ namespace netlist {
NETLIB_IS_DYNAMIC(true)
+ param_double_t m_cur_limit; /* current limit */
+
protected:
- //NETLIB_UPDATEI();
+ NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
- private:
- param_double_t m_cur_limit; /* current limit */
nl_double m_vi;
};
@@ -131,13 +137,12 @@ namespace netlist {
public:
NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
{
- m_gfac = plib::constants<nl_double>::one() / m_RI();
+ m_gfac = NL_FCONST(1.0) / m_RI();
}
- NETLIB_RESETI();
-
protected:
- //NETLIB_UPDATEI();
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
};
@@ -175,28 +180,29 @@ namespace netlist {
public:
NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
, m_RO(*this, "RO", 1.0)
- , m_OP2(*this, "_OP2", &m_ON2)
- , m_ON2(*this, "_ON2", &m_OP2)
+ , m_OP2(*this, "_OP2")
+ , m_ON2(*this, "_ON2")
{
+ m_OP2.m_otherterm = &m_ON2;
+ m_ON2.m_otherterm = &m_OP2;
+
connect(m_OP2, m_OP1);
connect(m_ON2, m_ON1);
}
- NETLIB_RESETI();
-
param_double_t m_RO;
- private:
+ protected:
//NETLIB_UPDATEI();
+ NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
terminal_t m_OP2;
terminal_t m_ON2;
-
};
- } // namespace analog
-} // namespace netlist
+ }
+}
#endif /* NLD_FOURTERM_H_ */
diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp
index 5019c98c0e4..f54c2b3e68f 100644
--- a/src/lib/netlist/analog/nlid_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -5,10 +5,10 @@
*
*/
-#include "netlist/solver/nld_solver.h"
+#include "../solver/nld_solver.h"
-#include "netlist/nl_factory.h"
#include "nlid_twoterm.h"
+#include "../nl_factory.h"
#include <cmath>
@@ -16,34 +16,81 @@ namespace netlist
{
namespace analog
{
-
// ----------------------------------------------------------------------------------------
-// nld_twoterm
+// generic_diode
// ----------------------------------------------------------------------------------------
-void NETLIB_NAME(twoterm)::solve_now()
+generic_diode::generic_diode(device_t &dev, pstring name)
+ : m_Vd(dev, name + ".m_Vd", 0.7)
+ , m_Id(dev, name + ".m_Id", 0.0)
+ , m_G(dev, name + ".m_G", 1e-15)
+ , m_Vt(0.0)
+ , m_Vmin(0.0)
+ , m_Is(0.0)
+ , m_logIs(0.0)
+ , m_n(0.0)
+ , m_gmin(1e-15)
+ , m_VtInv(0.0)
+ , m_Vcrit(0.0)
{
- /* we only need to call the non-rail terminal */
- if (m_P.has_net() && !m_P.net().isRailNet())
- m_P.solve_now();
- else if (m_N.has_net() && !m_N.net().isRailNet())
- m_N.solve_now();
+ set_param(1e-15, 1, 1e-15);
}
-void NETLIB_NAME(twoterm)::solve_later(netlist_time delay)
+void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double gmin)
{
- /* we only need to call the non-rail terminal */
- if (m_P.has_net() && !m_P.net().isRailNet())
- m_P.schedule_solve_after(delay);
- else if (m_N.has_net() && !m_N.net().isRailNet())
- m_N.schedule_solve_after(delay);
+ static constexpr double csqrt2 = 1.414213562373095048801688724209; //std::sqrt(2.0);
+ m_Is = Is;
+ m_logIs = std::log(Is);
+ m_n = n;
+ m_gmin = gmin;
+
+ m_Vt = 0.0258 * m_n;
+ m_Vmin = -5.0 * m_Vt;
+
+ m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
+ m_VtInv = 1.0 / m_Vt;
+}
+
+void generic_diode::update_diode(const nl_double nVd)
+{
+ if (nVd < m_Vmin)
+ {
+ m_Vd = nVd;
+ m_G = m_gmin;
+ m_Id = - m_Is;
+ }
+ else if (nVd < m_Vcrit)
+ {
+ m_Vd = nVd;
+ //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
+ }
+ else
+ {
+ const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
+ m_Vd = m_Vd + std::log1p(a) * m_Vt;
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
+ }
}
+// ----------------------------------------------------------------------------------------
+// nld_twoterm
+// ----------------------------------------------------------------------------------------
NETLIB_UPDATE(twoterm)
{
/* only called if connected to a rail net ==> notify the solver to recalculate */
- solve_now();
+ /* we only need to call the non-rail terminal */
+ if (m_P.has_net() && !m_P.net().isRailNet())
+ m_P.solve_now();
+ else if (m_N.has_net() && !m_N.net().isRailNet())
+ m_N.solve_now();
}
// ----------------------------------------------------------------------------------------
@@ -53,7 +100,12 @@ NETLIB_UPDATE(twoterm)
NETLIB_RESET(R_base)
{
NETLIB_NAME(twoterm)::reset();
- set_R(1.0 / exec().gmin());
+ set_R(1.0 / netlist().gmin());
+}
+
+NETLIB_UPDATE(R_base)
+{
+ NETLIB_NAME(twoterm)::update();
}
// ----------------------------------------------------------------------------------------
@@ -62,14 +114,14 @@ NETLIB_RESET(R_base)
NETLIB_UPDATE_PARAM(R)
{
- solve_now();
- set_R(std::max(m_R(), exec().gmin()));
+ update_dev();
+ set_R(std::max(m_R(), netlist().gmin()));
}
NETLIB_RESET(R)
{
NETLIB_NAME(twoterm)::reset();
- set_R(std::max(m_R(), exec().gmin()));
+ set_R(std::max(m_R(), netlist().gmin()));
}
// ----------------------------------------------------------------------------------------
@@ -82,22 +134,21 @@ NETLIB_RESET(POT)
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R2.set_R(std::max(m_R() * (plib::constants<nl_double>::one() - v), exec().gmin()));
+ m_R1.set_R(std::max(m_R() * v, netlist().gmin()));
+ m_R2.set_R(std::max(m_R() * (NL_FCONST(1.0) - v), netlist().gmin()));
}
NETLIB_UPDATE_PARAM(POT)
{
- m_R1.solve_now();
- m_R2.solve_now();
+ m_R1.update_dev();
+ m_R2.update_dev();
nl_double v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
- if (m_Reverse())
- v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
- m_R2.set_R(std::max(m_R() * (plib::constants<nl_double>::one() - v), exec().gmin()));
+
+ m_R1.set_R(std::max(m_R() * v, netlist().gmin()));
+ m_R2.set_R(std::max(m_R() * (NL_FCONST(1.0) - v), netlist().gmin()));
}
@@ -113,13 +164,13 @@ NETLIB_RESET(POT2)
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
if (m_Reverse())
v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
+ m_R1.set_R(std::max(m_R() * v, netlist().gmin()));
}
NETLIB_UPDATE_PARAM(POT2)
{
- m_R1.solve_now();
+ m_R1.update_dev();
nl_double v = m_Dial();
@@ -127,7 +178,38 @@ NETLIB_UPDATE_PARAM(POT2)
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
if (m_Reverse())
v = 1.0 - v;
- m_R1.set_R(std::max(m_R() * v, exec().gmin()));
+ m_R1.set_R(std::max(m_R() * v, netlist().gmin()));
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_C
+// ----------------------------------------------------------------------------------------
+
+NETLIB_RESET(C)
+{
+ // FIXME: Startup conditions
+ set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
+ //set(netlist().gmin(), 0.0, 0.0);
+}
+
+NETLIB_UPDATE_PARAM(C)
+{
+ m_GParallel = netlist().gmin();
+}
+
+NETLIB_UPDATE(C)
+{
+ NETLIB_NAME(twoterm)::update();
+}
+
+NETLIB_TIMESTEP(C)
+{
+ /* Gpar should support convergence */
+ const nl_double G = m_C() / step + m_GParallel;
+ const nl_double I = -G * deltaV();
+ set_mat( G, -G, -I,
+ -G, G, I);
+ //set(G, 0.0, I);
}
// ----------------------------------------------------------------------------------------
@@ -136,9 +218,9 @@ NETLIB_UPDATE_PARAM(POT2)
NETLIB_RESET(L)
{
- m_gmin = exec().gmin();
+ m_GParallel = netlist().gmin();
m_I = 0.0;
- m_G = m_gmin;
+ m_G = m_GParallel;
set_mat( m_G, -m_G, -m_I,
-m_G, m_G, m_I);
//set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
@@ -148,11 +230,16 @@ NETLIB_UPDATE_PARAM(L)
{
}
+NETLIB_UPDATE(L)
+{
+ NETLIB_NAME(twoterm)::update();
+}
+
NETLIB_TIMESTEP(L)
{
/* Gpar should support convergence */
m_I += m_I + m_G * deltaV();
- m_G = step / m_L() + m_gmin;
+ m_G = step / m_L() + m_GParallel;
set_mat( m_G, -m_G, -m_I,
-m_G, m_G, m_I);
//set(m_G, 0.0, m_I);
@@ -167,8 +254,8 @@ NETLIB_RESET(D)
nl_double Is = m_model.m_IS;
nl_double n = m_model.m_N;
- m_D.set_param(Is, n, exec().gmin(), constants::T0());
- set_G_V_I(m_D.G(), 0.0, m_D.Ieq());
+ m_D.set_param(Is, n, netlist().gmin());
+ set(m_D.G(), 0.0, m_D.Ieq());
}
NETLIB_UPDATE_PARAM(D)
@@ -176,7 +263,12 @@ NETLIB_UPDATE_PARAM(D)
nl_double Is = m_model.m_IS;
nl_double n = m_model.m_N;
- m_D.set_param(Is, n, exec().gmin(), constants::T0());
+ m_D.set_param(Is, n, netlist().gmin());
+}
+
+NETLIB_UPDATE(D)
+{
+ NETLIB_NAME(twoterm)::update();
}
NETLIB_UPDATE_TERMINALS(D)
@@ -189,18 +281,65 @@ NETLIB_UPDATE_TERMINALS(D)
//set(m_D.G(), 0.0, m_D.Ieq());
}
+// ----------------------------------------------------------------------------------------
+// nld_VS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_RESET(VS)
+{
+ NETLIB_NAME(twoterm)::reset();
+ this->set(1.0 / m_R(), m_V(), 0.0);
+}
+
+NETLIB_UPDATE(VS)
+{
+ NETLIB_NAME(twoterm)::update();
+}
+
+NETLIB_TIMESTEP(VS)
+{
+ this->set(1.0 / m_R(),
+ m_compiled.evaluate(std::vector<double>({netlist().time().as_double()})),
+ 0.0);
+}
+
+// ----------------------------------------------------------------------------------------
+// nld_CS
+// ----------------------------------------------------------------------------------------
+
+NETLIB_RESET(CS)
+{
+ NETLIB_NAME(twoterm)::reset();
+ const nl_double I = m_I();
+
+ set_mat(0.0, 0.0, -I,
+ 0.0, 0.0, I);
+ //this->set(0.0, 0.0, m_I());
+}
+
+NETLIB_UPDATE(CS)
+{
+ NETLIB_NAME(twoterm)::update();
+}
+
+NETLIB_TIMESTEP(CS)
+{
+ const double I = m_compiled.evaluate(std::vector<double>({netlist().time().as_double()}));
+ set_mat(0.0, 0.0, -I,
+ 0.0, 0.0, I);
+}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, R, "RES", "R")
- NETLIB_DEVICE_IMPL_NS(analog, POT, "POT", "R")
- NETLIB_DEVICE_IMPL_NS(analog, POT2, "POT2", "R")
- NETLIB_DEVICE_IMPL_NS(analog, C, "CAP", "C")
- NETLIB_DEVICE_IMPL_NS(analog, L, "IND", "L")
- NETLIB_DEVICE_IMPL_NS(analog, D, "DIODE", "MODEL")
- NETLIB_DEVICE_IMPL_NS(analog, VS, "VS", "V")
- NETLIB_DEVICE_IMPL_NS(analog, CS, "CS", "I")
- } // namespace devices
+ NETLIB_DEVICE_IMPL_NS(analog, R)
+ NETLIB_DEVICE_IMPL_NS(analog, POT)
+ NETLIB_DEVICE_IMPL_NS(analog, POT2)
+ NETLIB_DEVICE_IMPL_NS(analog, C)
+ NETLIB_DEVICE_IMPL_NS(analog, L)
+ NETLIB_DEVICE_IMPL_NS(analog, D)
+ NETLIB_DEVICE_IMPL_NS(analog, VS)
+ NETLIB_DEVICE_IMPL_NS(analog, CS)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h
index 470fb35c96e..7778f5f4585 100644
--- a/src/lib/netlist/analog/nlid_twoterm.h
+++ b/src/lib/netlist/analog/nlid_twoterm.h
@@ -33,12 +33,8 @@
#ifndef NLID_TWOTERM_H_
#define NLID_TWOTERM_H_
-#include "netlist/nl_base.h"
-#include "netlist/nl_setup.h"
-#include "netlist/solver/nld_solver.h"
-#include "plib/pfunction.h"
-
-#include <cmath>
+#include "../nl_base.h"
+#include "../plib/pfunction.h"
// -----------------------------------------------------------------------------
// Implementation
@@ -52,27 +48,14 @@ namespace netlist
// nld_twoterm
// -----------------------------------------------------------------------------
- template <class C>
- inline core_device_t &bselect(bool b, C &d1, core_device_t &d2)
- {
- auto *h = dynamic_cast<core_device_t *>(&d1);
- return b ? *h : d2;
- }
- template<>
- inline core_device_t &bselect(bool b, netlist_state_t &d1, core_device_t &d2)
- {
- plib::unused_var(d1);
- if (b)
- throw nl_exception("bselect with netlist and b==true");
- return d2;
- }
-
NETLIB_OBJECT(twoterm)
{
NETLIB_CONSTRUCTOR_EX(twoterm, bool terminals_owned = false)
- , m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1", &m_N)
- , m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2", &m_P)
+ , m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1")
+ , m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
{
+ m_P.m_otherterm = &m_N;
+ m_N.m_otherterm = &m_P;
}
terminal_t m_P;
@@ -80,36 +63,36 @@ NETLIB_OBJECT(twoterm)
//NETLIB_UPDATE_TERMINALSI() { }
//NETLIB_RESETI() { }
-
-public:
-
NETLIB_UPDATEI();
- void solve_now();
-
- void solve_later(netlist_time delay = netlist_time::from_nsec(1));
-
- void set_G_V_I(const nl_double G, const nl_double V, const nl_double I)
+public:
+ /* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
{
/* GO, GT, I */
- m_P.set_go_gt_I( -G, G, ( V) * G - I);
- m_N.set_go_gt_I( -G, G, ( -V) * G + I);
+ m_P.set( G, G, ( V) * G - I);
+ m_N.set( G, G, ( -V) * G + I);
}
- nl_double deltaV() const
+ /* inline */ nl_double deltaV() const
{
return m_P.net().Q_Analog() - m_N.net().Q_Analog();
}
- void set_mat(const nl_double a11, const nl_double a12, const nl_double rhs1,
- const nl_double a21, const nl_double a22, const nl_double rhs2)
+ void set_mat(const nl_double a11, const nl_double a12, const nl_double r1,
+ const nl_double a21, const nl_double a22, const nl_double r2)
{
/* GO, GT, I */
- m_P.set_go_gt_I(a12, a11, rhs1);
- m_N.set_go_gt_I(a21, a22, rhs2);
+ m_P.set(-a12, a11, r1);
+ m_N.set(-a21, a22, r2);
}
private:
+ template <class C>
+ static core_device_t &bselect(bool b, C &d1, core_device_t &d2)
+ {
+ core_device_t *h = dynamic_cast<core_device_t *>(&d1);
+ return b ? *h : d2;
+ }
};
@@ -123,17 +106,17 @@ NETLIB_OBJECT_DERIVED(R_base, twoterm)
{
}
- void set_R(const nl_double R)
+public:
+ inline void set_R(const nl_double R)
{
- const nl_double G = plib::constants<nl_double>::one() / R;
+ const nl_double G = NL_FCONST(1.0) / R;
set_mat( G, -G, 0.0,
-G, G, 0.0);
}
- NETLIB_RESETI();
-
protected:
- //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
};
@@ -144,6 +127,7 @@ NETLIB_OBJECT_DERIVED(R, R_base)
{
}
+ param_double_t m_R;
protected:
@@ -152,7 +136,6 @@ protected:
NETLIB_UPDATE_PARAMI();
private:
- param_double_t m_R;
/* protect set_R ... it's a recipe to desaster when used to bypass the parameter */
using NETLIB_NAME(R_base)::set_R;
};
@@ -168,8 +151,7 @@ NETLIB_OBJECT(POT)
, m_R2(*this, "_R2")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", false)
- , m_Reverse(*this, "REVERSE", false)
+ , m_DialIsLog(*this, "DIALLOG", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
@@ -190,7 +172,6 @@ private:
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
- param_logic_t m_Reverse;
};
NETLIB_OBJECT(POT2)
@@ -199,8 +180,8 @@ NETLIB_OBJECT(POT2)
, m_R1(*this, "_R1")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", false)
- , m_Reverse(*this, "REVERSE", false)
+ , m_DialIsLog(*this, "DIALLOG", 0)
+ , m_Reverse(*this, "REVERSE", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
@@ -220,83 +201,6 @@ private:
param_logic_t m_Reverse;
};
-// -----------------------------------------------------------------------------
-// A generic capacitor model
-// -----------------------------------------------------------------------------
-
-enum class capacitor_e
-{
- CHARGE_CONSERVING,
- CONSTANT_CAPACITY
-};
-
-template <capacitor_e TYPE>
-class generic_capacitor
-{
-};
-
-
-template <>
-class generic_capacitor<capacitor_e::CHARGE_CONSERVING>
-{
-public:
- generic_capacitor(device_t &dev, const pstring &name)
- : m_h(dev, name + ".m_h", 0.0)
- , m_charge(dev, name + ".m_charge", 0.0)
- , m_gmin(0.0)
- {
- }
-
- constexpr capacitor_e type() const { return capacitor_e::CHARGE_CONSERVING; }
-
- constexpr nl_double G(nl_double cap) const
- {
- return cap * m_h + m_gmin;
- }
-
- constexpr nl_double Ieq(nl_double cap, nl_double v) const
- {
- return m_h * (cap * v - m_charge) - G(cap) * v;
- }
-
- void timestep(nl_double cap, nl_double v, nl_double step)
- {
- m_h = 1.0 / step;
- m_charge = cap * v;
- }
-
- void setparams(nl_double gmin) { m_gmin = gmin; }
-
-private:
- state_var<double> m_h;
- state_var<double> m_charge;
- nl_double m_gmin;
-};
-
-template <>
-class generic_capacitor<capacitor_e::CONSTANT_CAPACITY>
-{
-public:
- generic_capacitor(device_t &dev, const pstring &name)
- : m_h(dev, name + ".m_h", 0.0)
- , m_gmin(0.0)
- {
- }
-
- constexpr capacitor_e type() const { return capacitor_e::CONSTANT_CAPACITY; }
- constexpr nl_double G(nl_double cap) const { return cap * m_h + m_gmin; }
- constexpr nl_double Ieq(nl_double cap, nl_double v) const { return - G(cap) * v; }
-
- void timestep(nl_double cap, nl_double v, nl_double step)
- {
- plib::unused_var(cap, v);
- m_h = 1.0 / step;
- }
- void setparams(nl_double gmin) { m_gmin = gmin; }
-private:
- state_var<nl_double> m_h;
- nl_double m_gmin;
-};
// -----------------------------------------------------------------------------
// nld_C
@@ -307,45 +211,25 @@ NETLIB_OBJECT_DERIVED(C, twoterm)
public:
NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
, m_C(*this, "C", 1e-6)
- , m_cap(*this, "m_cap")
+ , m_GParallel(0.0)
{
+ //register_term("1", m_P);
+ //register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
- NETLIB_TIMESTEPI()
- {
- m_cap.timestep(m_C(), deltaV(), step);
- if (m_cap.type() == capacitor_e::CONSTANT_CAPACITY)
- {
- const nl_double I = m_cap.Ieq(m_C(), deltaV());
- const nl_double G = m_cap.G(m_C());
- set_mat( G, -G, -I,
- -G, G, I);
- }
- }
-
- NETLIB_IS_DYNAMIC(m_cap.type() == capacitor_e::CHARGE_CONSERVING)
- NETLIB_UPDATE_TERMINALSI()
- {
- const nl_double I = m_cap.Ieq(m_C(), deltaV());
- const nl_double G = m_cap.G(m_C());
- set_mat( G, -G, -I,
- -G, G, I);
- }
+ NETLIB_TIMESTEPI();
param_double_t m_C;
- NETLIB_RESETI()
- {
- m_cap.setparams(exec().gmin());
- }
protected:
- //NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI() { }
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
private:
- generic_capacitor<capacitor_e::CHARGE_CONSERVING> m_cap;
- //generic_capacitor<capacitor_e::CONSTANT_CAPACITY> m_cap;
+ nl_double m_GParallel;
+
};
// -----------------------------------------------------------------------------
@@ -357,7 +241,7 @@ NETLIB_OBJECT_DERIVED(L, twoterm)
public:
NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
, m_L(*this, "L", 1e-6)
- , m_gmin(0.0)
+ , m_GParallel(0.0)
, m_G(0.0)
, m_I(0.0)
{
@@ -367,16 +251,16 @@ public:
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
- NETLIB_RESETI();
+
+ param_double_t m_L;
protected:
- //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
- param_double_t m_L;
-
- nl_double m_gmin;
+ nl_double m_GParallel;
nl_double m_G;
nl_double m_I;
};
@@ -385,82 +269,14 @@ private:
// A generic diode model to be used in other devices (Diode, BJT ...)
// -----------------------------------------------------------------------------
-enum class diode_e
-{
- BIPOLAR,
- MOS
-};
-
-template <diode_e TYPE>
class generic_diode
{
public:
- generic_diode(device_t &dev, const pstring &name)
- : m_Vd(dev, name + ".m_Vd", 0.7)
- , m_Id(dev, name + ".m_Id", 0.0)
- , m_G(dev, name + ".m_G", 1e-15)
- , m_Vt(0.0)
- , m_Vmin(0.0) // not used in MOS model
- , m_Is(0.0)
- , m_logIs(0.0)
- , m_n(0.0)
- , m_gmin(1e-15)
- , m_VtInv(0.0)
- , m_Vcrit(0.0)
- {
- set_param(1e-15, 1, 1e-15, 300.0);
- }
-
- void update_diode(const double nVd)
- {
- if (TYPE == diode_e::BIPOLAR && nVd < m_Vmin)
- {
- m_Vd = nVd;
- m_G = m_gmin;
- m_Id = - m_Is;
- }
- else if (TYPE == diode_e::MOS && nVd < constants::zero())
- {
- m_Vd = nVd;
- m_G = m_Is * m_VtInv + m_gmin;
- m_Id = m_G * m_Vd;
- }
- // FIXME: For MOS, stop here, the critical code path will not converge
- else if (TYPE == diode_e::MOS || nVd < m_Vcrit)
- {
- m_Vd = nVd;
- const double IseVDVt = std::exp(std::min(700.0, m_logIs + m_Vd * m_VtInv));
- m_Id = IseVDVt - m_Is;
- m_G = IseVDVt * m_VtInv + m_gmin;
- }
- else
- {
- const double a = std::max((nVd - m_Vd) * m_VtInv, constants::cast(-0.99));
- m_Vd = m_Vd + std::log1p(a) * m_Vt;
- //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
- const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
- m_Id = IseVDVt - m_Is;
- m_G = IseVDVt * m_VtInv + m_gmin;
- }
- }
-
-
- void set_param(const double Is, const double n, double gmin, double temp)
- {
- static constexpr double csqrt2 = 1.414213562373095048801688724209; //std::sqrt(2.0);
- m_Is = Is;
- m_logIs = std::log(Is);
- m_n = n;
- m_gmin = gmin;
+ generic_diode(device_t &dev, pstring name);
- m_Vt = m_n * temp * constants::k_b() / constants::Q_e();
-
- m_Vmin = -5.0 * m_Vt;
-
- m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
- m_VtInv = 1.0 / m_Vt;
- }
+ void update_diode(const double nVd);
+ void set_param(const double Is, const double n, double gmin);
double I() const { return m_Id; }
double G() const { return m_G; }
@@ -551,15 +367,15 @@ public:
NETLIB_IS_DYNAMIC(true)
NETLIB_UPDATE_TERMINALSI();
- NETLIB_RESETI();
+
+ diode_model_t m_model;
protected:
- //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
-private:
- diode_model_t m_model;
- generic_diode<diode_e::BIPOLAR> m_D;
+ generic_diode m_D;
};
@@ -573,11 +389,10 @@ NETLIB_OBJECT_DERIVED(VS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
- , m_t(*this, "m_t", 0.0)
, m_R(*this, "R", 0.1)
, m_V(*this, "V", 0.0)
, m_func(*this,"FUNC", "")
- , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
+ , m_compiled(this->name() + ".FUNCC", this, this->netlist().state())
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@@ -586,26 +401,12 @@ public:
}
NETLIB_IS_TIMESTEP(m_func() != "")
-
- NETLIB_TIMESTEPI()
- {
- m_t += step;
- this->set_G_V_I(1.0 / m_R(),
- m_compiled.evaluate(std::vector<double>({m_t})),
- 0.0);
- }
+ NETLIB_TIMESTEPI();
protected:
- // NETLIB_UPDATEI() { NETLIB_NAME(twoterm)::update(time); }
-
- NETLIB_RESETI()
- {
- NETLIB_NAME(twoterm)::reset();
- this->set_G_V_I(1.0 / m_R(), m_V(), 0.0);
- }
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
-private:
- state_var<double> m_t;
param_double_t m_R;
param_double_t m_V;
param_str_t m_func;
@@ -620,10 +421,9 @@ NETLIB_OBJECT_DERIVED(CS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
- , m_t(*this, "m_t", 0.0)
, m_I(*this, "I", 1.0)
, m_func(*this,"FUNC", "")
- , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
+ , m_compiled(this->name() + ".FUNCC", this, this->netlist().state())
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@@ -632,33 +432,19 @@ public:
}
NETLIB_IS_TIMESTEP(m_func() != "")
- NETLIB_TIMESTEPI()
- {
- m_t += step;
- const double I = m_compiled.evaluate(std::vector<double>({m_t}));
- set_mat(0.0, 0.0, -I,
- 0.0, 0.0, I);
- }
-
+ NETLIB_TIMESTEPI();
protected:
- //NETLIB_UPDATEI() { NETLIB_NAME(twoterm)::update(time); }
- NETLIB_RESETI()
- {
- NETLIB_NAME(twoterm)::reset();
- set_mat(0.0, 0.0, -m_I(),
- 0.0, 0.0, m_I());
- }
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
-private:
- state_var<double> m_t;
param_double_t m_I;
param_str_t m_func;
plib::pfunction m_compiled;
};
- } // namespace analog
+ } //namespace devices
} // namespace netlist
#endif /* NLD_TWOTERM_H_ */
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 647c7df6f12..807ddbd6c7a 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -12,27 +12,6 @@
SRC = ..
VSBUILD = $(SRC)/buildVS
DOC = $(SRC)/documentation
-TIDY_DB = ../compile_commands.json
-
-TIDY_FLAGSX = -checks=*,-google*,-hicpp*,-readability*,-fuchsia*,cert-*,-android-*,
-TIDY_FLAGSX += -llvm-header-guard,-cppcoreguidelines-pro-type-reinterpret-cast,
-TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-owning-memory,
-TIDY_FLAGSX += -modernize-use-default-member-init,-cppcoreguidelines-pro-bounds-constant-array-index,
-TIDY_FLAGSX += -modernize-pass-by-value,-cppcoreguidelines-pro-type-static-cast-downcast,
-TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers,
-TIDY_FLAGSX += -cppcoreguidelines-macro-usage,
-TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,
-TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses
-
-space :=
-space +=
-TIDY_FLAGS = $(subst $(space),,$(TIDY_FLAGSX))
-
-TIDY_FLAGS = -checks=llvm-include-order,llvm-namespace-comment,modernize-use-override,modernize-use-using -fix
-#TIDY_FLAGS = -checks=llvm-include-order -fix
-#TIDY_FLAGS = -checks=llvm-namespace-comment -fix
-#TIDY_FLAGS = -checks=modernize-use-override -fix
-#TIDY_FLAGS = -checks=modernize-use-using -fix
ifeq ($(subst Windows_NT,windows,$(OS)),windows)
OBJ = obj/mingw
@@ -44,7 +23,7 @@ endif
# LTO = -flto=4 -fuse-linker-plugin -flto-partition=balanced -Wodr
-CFLAGS = $(LTO) -g -O3 -std=c++11 -I$(CURDIR)/.. -I$(CURDIR)/../.. $(CEXTRAFLAGS)
+CFLAGS = $(LTO) -g -O3 -std=c++11 -march=native -I../.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter $(CEXTRAFLAGS)
LDFLAGS = $(LTO) -g -O3 -std=c++11 $(LDEXTRAFLAGS)
LIBS = -lpthread -ldl
@@ -53,7 +32,6 @@ LD = @g++
MD = @mkdir
RM = @rm
DOXYGEN = @doxygen
-CLANG_TIDY = clang-tidy-9
TARGETS = nltool nlwav
@@ -75,6 +53,7 @@ OBJS = $(POBJS) $(NLOBJS)
POBJS := \
$(POBJ)/pstring.o \
+ $(POBJ)/palloc.o \
$(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
$(POBJ)/pexception.o \
@@ -94,7 +73,6 @@ NLOBJS := \
$(NLOBJ)/nl_setup.o \
$(NLOBJ)/nl_factory.o \
$(NLOBJ)/analog/nld_bjt.o \
- $(NLOBJ)/analog/nld_mosfet.o \
$(NLOBJ)/analog/nlid_fourterm.o \
$(NLOBJ)/analog/nld_switches.o \
$(NLOBJ)/analog/nlid_twoterm.o \
@@ -114,7 +92,6 @@ NLOBJS := \
$(NLOBJ)/devices/nld_7485.o \
$(NLOBJ)/devices/nld_7490.o \
$(NLOBJ)/devices/nld_7493.o \
- $(NLOBJ)/devices/nld_7497.o \
$(NLOBJ)/devices/nld_74107.o \
$(NLOBJ)/devices/nld_74123.o \
$(NLOBJ)/devices/nld_74153.o \
@@ -176,12 +153,10 @@ DOCS = \
$(DOC)/test1-50r.svg \
ALL_OBJS = $(OBJS) $(PMAIN) $(NLOBJ)/prg/nltool.o $(NLOBJ)/prg/nlwav.o
-
-ALL_TIDY_FILES = $(ALL_OBJS:.o=.json)
SOURCES = $(patsubst $(OBJ)%, $(SRC)%, $(ALL_OBJS:.o=.cpp))
ALLFILES = $(SOURCES) $(VSBUILDS) $(DOCS)
-MAKEFILE_TARGETS_WITHOUT_INCLUDE := clean doc clang mingw nvcc
+MAKEFILE_TARGETS_WITHOUT_INCLUDE := clean doc clang mingw
# git archive HEAD --prefix=project-name-version/ \
@@ -225,33 +200,19 @@ maketree: $(sort $(OBJDIRS))
# Special targets
#-------------------------------------------------
-.PHONY: clang clang-5 mingw doc native
-
-native:
- $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
+.PHONY: clang clang-5 mingw doc
clang:
- $(MAKE) CC=clang++-9 LD=clang++-9 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors"
+ $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-march=native -Weverything -Werror -override -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
clang-5:
$(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-inconsistent-missing-destructor-override -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
-nvcc:
- $(MAKE) CC=/usr/local/cuda-9.0/bin/nvcc LD=/usr/local/cuda-9.2/bin/nvcc \
- CEXTRAFLAGS="-x cu -DNVCCBUILD=1 --expt-extended-lambda --expt-relaxed-constexpr --default-stream per-thread --restrict"
-
-tidy_db: compile_commands_prefix $(ALL_TIDY_FILES) compile_commands_postfix
-
#
-# -Wno-c++11-narrowing : seems a bit broken
# Mostly done: -Wno-weak-vtables -Wno-cast-align
# FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors
# FIXME: -Winconsistent-missing-destructor-override : c++ community has diverging opinions on this https://github.com/isocpp/CppCoreGuidelines/issues/721
# FIXME: -Wunreachable-code : False warnings, this a documented clang bug: https://llvm.org/bugs/show_bug.cgi?id=28994
-# -Wweak-template-vtables
-#
-# These have to be given:
-# -Wno-missing-variable-declarations : Device factory code, on purpose
mingw:
$(MAKE) CEXTRAFLAGS="-DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0501 -DWIN32_LEAN_AND_MEAN" \
@@ -276,7 +237,7 @@ doc: nltool
@echo creating .depend
@rm -f ./.depend
@for i in $(SOURCES); do \
- $(CC) $(CFLAGS) -MM $$i -MT `echo $$i | sed -e 's+$(SRC)+$(OBJ)+' -e 's+.cpp+.o+' ` >> ./.depend; \
+ $(CC) $(CFLAGS) -MM $$i -MT `echo $$i | sed -e 's+$(SRC)+$(OBJ)+' -e 's+.cpp+.o+' ` >>./.depend; \
done
depend: .depend
@@ -287,18 +248,6 @@ ifeq ($(filter $(MAKECMDGOALS),$(MAKEFILE_TARGETS_WITHOUT_INCLUDE)),)
endif
#-------------------------------------------------
-# clang tidy
-#-------------------------------------------------
-tidy: tidy_db
- @echo running tidy
- @for i in $(SOURCES); do \
- $(CLANG_TIDY) $$i $(TIDY_FLAGS) -header-filter=.*; \
- done
-
-tidy_db: compile_commands_prefix $(ALL_TIDY_FILES) compile_commands_postfix
-
-
-#-------------------------------------------------
# generic rules
#-------------------------------------------------
@@ -319,15 +268,3 @@ $(OBJ)/%.a:
$(RM) $@
$(AR) $(ARFLAGS) $@ $^
-$(OBJ)/%.json: $(SRC)/%.cpp
- @echo Building compile database entry for $< ...
- @echo { \"directory\": \".\", >> $(TIDY_DB)
- @echo \"command\": \"$(CC) $(CDEFS) $(CFLAGS) -c $< -o dummy.o\", >> $(TIDY_DB)
- @echo \"file\": \"$(CURDIR)/$<\" } >> $(TIDY_DB)
- @echo "," >> $(TIDY_DB)
-
-compile_commands_prefix:
- @echo "[" > $(TIDY_DB)
-
-compile_commands_postfix:
- @echo "]" >> $(TIDY_DB)
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp
index c0353f2489a..e0f0277daac 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -9,159 +9,152 @@
****************************************************************************/
#include "net_lib.h"
-#include "netlist/nl_factory.h"
-#include "netlist/solver/nld_solver.h"
+#include "../nl_factory.h"
+#include "../solver/nld_solver.h"
#define xstr(s) # s
-#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip
+#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip;
-#define LIB_DECL(nic, decl) factory.register_device( decl ( pstring(xstr(nic))) );
-#define LIB_ENTRY(nic) { NETLIB_DEVICE_DECL(nic); LIB_DECL(NETLIB_NAME(nic), decl_ ## nic) }
+#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) );
+#define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }
namespace netlist
{
-namespace devices
-{
-
- void initialize_factory(factory::list_t &factory)
+ namespace devices
{
- LIB_ENTRY(R)
- LIB_ENTRY(POT)
- LIB_ENTRY(POT2)
- LIB_ENTRY(C)
- LIB_ENTRY(L)
- LIB_ENTRY(D)
- LIB_ENTRY(VS)
- LIB_ENTRY(CS)
- LIB_ENTRY(VCVS)
- LIB_ENTRY(VCCS)
- LIB_ENTRY(CCCS)
- LIB_ENTRY(LVCCS)
- LIB_ENTRY(opamp)
- LIB_ENTRY(dummy_input)
- LIB_ENTRY(frontier) // not intended to be used directly
- LIB_ENTRY(function) // only for macro devices - NO FEEDBACK loops
- LIB_ENTRY(QBJT_EB)
- LIB_ENTRY(QBJT_switch)
- LIB_ENTRY(MOSFET)
- LIB_ENTRY(logic_input_ttl)
- LIB_ENTRY(logic_input)
- LIB_ENTRY(analog_input)
- LIB_ENTRY(log)
- LIB_ENTRY(logD)
- LIB_ENTRY(clock)
- LIB_ENTRY(extclock)
- LIB_ENTRY(mainclock)
- LIB_ENTRY(gnd)
- LIB_ENTRY(netlistparams)
- LIB_ENTRY(solver)
- LIB_ENTRY(res_sw)
- LIB_ENTRY(switch1)
- LIB_ENTRY(switch2)
- LIB_ENTRY(nicRSFF)
- LIB_ENTRY(nicDelay)
- LIB_ENTRY(2102A)
- LIB_ENTRY(2102A_dip)
- LIB_ENTRY(2716)
- LIB_ENTRY(2716_dip)
- LIB_ENTRY(7448)
- LIB_ENTRY(7448_dip)
- LIB_ENTRY(7450)
- LIB_ENTRY(7450_dip)
- LIB_ENTRY(7473)
- LIB_ENTRY(7473_dip)
- LIB_ENTRY(7473A)
- LIB_ENTRY(7473A_dip)
- LIB_ENTRY(7474)
- LIB_ENTRY(7474_dip)
- LIB_ENTRY(7475)
- LIB_ENTRY(7475_dip)
- LIB_ENTRY(7477)
- LIB_ENTRY(7477_dip)
- LIB_ENTRY(7483)
- LIB_ENTRY(7483_dip)
- LIB_ENTRY(7485)
- LIB_ENTRY(7485_dip)
- LIB_ENTRY(7490)
- LIB_ENTRY(7490_dip)
- LIB_ENTRY(7493)
- LIB_ENTRY(7493_dip)
- LIB_ENTRY(7497)
- LIB_ENTRY(7497_dip)
- LIB_ENTRY(74107)
- LIB_ENTRY(74107_dip)
- LIB_ENTRY(74107A) // FIXME: implement missing DIP
- LIB_ENTRY(74123)
- LIB_ENTRY(74123_dip)
- LIB_ENTRY(74153)
- LIB_ENTRY(74153_dip)
- LIB_ENTRY(74161)
- LIB_ENTRY(74161_dip)
- LIB_ENTRY(74164)
- LIB_ENTRY(74164_dip)
- LIB_ENTRY(74165)
- LIB_ENTRY(74165_dip)
- LIB_ENTRY(74166)
- LIB_ENTRY(74166_dip)
- LIB_ENTRY(74174)
- LIB_ENTRY(74175)
- LIB_ENTRY(74192)
- LIB_ENTRY(74193)
- LIB_ENTRY(74194)
- LIB_ENTRY(74365)
- //ENTRY(74279, TTL_74279, "") // only dip available
- LIB_ENTRY(SN74LS629)
- LIB_ENTRY(82S16)
- LIB_ENTRY(82S115)
- LIB_ENTRY(82S123)
- LIB_ENTRY(82S126)
- LIB_ENTRY(9310)
- LIB_ENTRY(9314)
- LIB_ENTRY(9316)
- LIB_ENTRY(9322)
- LIB_ENTRY(9334)
- LIB_ENTRY(AM2847)
- // FIXME: duplicate?
- LIB_ENTRY(CD4020_WI)
- LIB_ENTRY(CD4020)
- LIB_ENTRY(CD4066_GATE)
- LIB_ENTRY(CD4316_GATE)
- LIB_ENTRY(4538_dip)
- LIB_ENTRY(schmitt_trigger)
- /* entries with suffix WI are legacy only */
- //ENTRY(4066, CD_4066, "+A,B")
- LIB_ENTRY(NE555)
- LIB_ENTRY(NE555_dip)
- LIB_ENTRY(MC1455P)
- LIB_ENTRY(MC1455P_dip)
- LIB_ENTRY(TMS4800)
- LIB_ENTRY(TMS4800_dip)
- LIB_ENTRY(r2r_dac)
- LIB_ENTRY(tristate)
- LIB_ENTRY(tristate3)
- LIB_ENTRY(74174_dip)
- LIB_ENTRY(74175_dip)
- LIB_ENTRY(74192_dip)
- LIB_ENTRY(74193_dip)
- LIB_ENTRY(74194_dip)
- LIB_ENTRY(74365_dip)
- LIB_ENTRY(82S16_dip)
- LIB_ENTRY(82S115_dip)
- LIB_ENTRY(82S123_dip)
- LIB_ENTRY(82S126_dip)
- LIB_ENTRY(9602_dip)
- LIB_ENTRY(9310_dip)
- LIB_ENTRY(9314_dip)
- LIB_ENTRY(9316_dip)
- LIB_ENTRY(9322_dip)
- LIB_ENTRY(9334_dip)
- LIB_ENTRY(AM2847_dip)
- LIB_ENTRY(SN74LS629_dip)
- LIB_ENTRY(MM5837_dip)
- }
+ void initialize_factory(factory::list_t &factory)
+{
+ ENTRYX(R, RES, "R")
+ ENTRYX(POT, POT, "R")
+ ENTRYX(POT2, POT2, "R")
+ ENTRYX(C, CAP, "C")
+ ENTRYX(L, IND, "L")
+ ENTRYX(D, DIODE, "MODEL")
+ ENTRYX(VS, VS, "V")
+ ENTRYX(CS, CS, "I")
+ ENTRYX(VCVS, VCVS, "")
+ ENTRYX(VCCS, VCCS, "")
+ ENTRYX(CCCS, CCCS, "")
+ ENTRYX(LVCCS, LVCCS, "")
+ ENTRYX(opamp, OPAMP, "MODEL")
+ ENTRYX(dummy_input, DUMMY_INPUT, "")
+ ENTRYX(frontier, FRONTIER_DEV, "+I,+G,+Q") // not intended to be used directly
+ ENTRYX(function, AFUNC, "N,FUNC") // only for macro devices - NO FEEDBACK loops
+ ENTRYX(QBJT_EB, QBJT_EB, "MODEL")
+ ENTRYX(QBJT_switch, QBJT_SW, "MODEL")
+ ENTRYX(logic_input, TTL_INPUT, "IN")
+ ENTRYX(logic_input, LOGIC_INPUT, "IN,FAMILY")
+ ENTRYX(analog_input, ANALOG_INPUT, "IN")
+ ENTRYX(log, LOG, "+I")
+ ENTRYX(logD, LOGD, "+I,+I2")
+ ENTRYX(clock, CLOCK, "FREQ")
+ ENTRYX(extclock, EXTCLOCK, "FREQ,PATTERN")
+ ENTRYX(mainclock, MAINCLOCK, "FREQ")
+ ENTRYX(gnd, GND, "")
+ ENTRYX(netlistparams, PARAMETER, "")
+ ENTRYX(solver, SOLVER, "FREQ")
+ ENTRYX(res_sw, RES_SWITCH, "+IN,+P1,+P2")
+ ENTRYX(switch1, SWITCH, "")
+ ENTRYX(switch2, SWITCH2, "")
+ ENTRYX(nicRSFF, NETDEV_RSFF, "")
+ ENTRYX(nicDelay, NETDEV_DELAY, "")
+ ENTRYX(2716, EPROM_2716, "+GQ,+EPQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
+ ENTRYX(TMS4800, ROM_TMS4800, "+AR,+OE1,+OE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
+ ENTRYX(2102A, RAM_2102A, "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI")
+ ENTRYX(7450, TTL_7450_ANDORINVERT, "+A,+B,+C,+D")
+ ENTRYX(7448, TTL_7448, "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ")
+ ENTRYX(7473, TTL_7473, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(7473A, TTL_7473A, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(7474, TTL_7474, "+CLK,+D,+CLRQ,+PREQ")
+ ENTRYX(7475, TTL_7475, "")
+ ENTRYX(7477, TTL_7477, "")
+ ENTRYX(7483, TTL_7483, "+A1,+A2,+A3,+A4,+B1,+B2,+B3,+B4,+C0")
+ ENTRYX(7485, TTL_7485, "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN")
+ ENTRYX(7490, TTL_7490, "+A,+B,+R1,+R2,+R91,+R92")
+ ENTRYX(7493, TTL_7493, "+CLKA,+CLKB,+R1,+R2")
+ ENTRYX(74107, TTL_74107, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(74107A, TTL_74107A, "+CLK,+J,+K,+CLRQ")
+ ENTRYX(74123, TTL_74123, "")
+ ENTRYX(74153, TTL_74153, "+C0,+C1,+C2,+C3,+A,+B,+G")
+ ENTRYX(74161, TTL_74161, "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
+ ENTRYX(74164, TTL_74164, "+A,+B,+CLRQ,+CLK")
+ ENTRYX(74165, TTL_74165, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H")
+ ENTRYX(74166, TTL_74166, "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ")
+ ENTRYX(74174, TTL_74174, "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ")
+ ENTRYX(74175, TTL_74175, "+CLK,+D1,+D2,+D3,+D4,+CLRQ")
+ ENTRYX(74192, TTL_74192, "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ ENTRYX(74193, TTL_74193, "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ ENTRYX(74194, TTL_74194, "+CLK,+S0,+S1,+SRIN,+A,+B,+C,+D,+SLIN,+CLRQ")
+ ENTRYX(74365, TTL_74365, "+G1Q,+G2Q,+A1,+A2,+A3,+A4,+A5,+A6")
+ //ENTRY(74279, TTL_74279, "") // only dip available
+ ENTRYX(SN74LS629, SN74LS629, "CAP")
+ ENTRYX(82S16, TTL_82S16, "")
+ ENTRYX(82S115, PROM_82S115, "+CE1Q,+CE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+STROBE")
+ ENTRYX(82S123, PROM_82S123, "+CEQ,+A0,+A1,+A2,+A3,+A4")
+ ENTRYX(82S126, PROM_82S126, "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7")
+ ENTRYX(9310, TTL_9310, "")
+ ENTRYX(9314, TTL_9314, "+EQ,+MRQ,+S0Q,+S1Q,+S2Q,+S3Q,+D0,+D1,+D2,+D3")
+ ENTRYX(9316, TTL_9316, "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D")
+ ENTRYX(9322, TTL_9322, "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE")
+ ENTRYX(9334, TTL_9334, "+CQ,+EQ,+D,+A0,+A1,+A2")
+ ENTRYX(AM2847, TTL_AM2847, "+CP,+INA,+INB,+INC,+IND,+RCA,+RCB,+RCC,+RCD")
+ ENTRYX(CD4020, CD4020, "")
+ ENTRYX(CD4066_GATE, CD4066_GATE, "")
+ ENTRYX(CD4316_GATE, CD4316_GATE, "")
+ ENTRYX(schmitt_trigger, SCHMITT_TRIGGER, "MODEL")
+ /* entries with suffix WI are legacy only */
+ ENTRYX(CD4020, CD4020_WI, "+IP,+RESET,+VDD,+VSS")
+ //ENTRY(4066, CD_4066, "+A,B")
+ ENTRYX(NE555, NE555, "")
+ ENTRYX(r2r_dac, R2R_DAC, "VIN,R,N")
+ ENTRYX(tristate, TTL_TRISTATE, "+CEQ1,+D1,+CEQ2,+D2")
+ ENTRYX(tristate3, TTL_TRISTATE3, "")
+ ENTRYX(2102A_dip, RAM_2102A_DIP, "")
+ ENTRYX(2716_dip, EPROM_2716_DIP, "")
+ ENTRYX(tms4800_dip, ROM_TMS4800_DIP, "")
+ ENTRYX(4538_dip, CD4538_DIP, "")
+ ENTRYX(7448_dip, TTL_7448_DIP, "")
+ ENTRYX(7450_dip, TTL_7450_DIP, "")
+ ENTRYX(7473_dip, TTL_7473_DIP, "")
+ ENTRYX(7473A_dip, TTL_7473A_DIP, "")
+ ENTRYX(7474_dip, TTL_7474_DIP, "")
+ ENTRYX(7475_dip, TTL_7475_DIP, "")
+ ENTRYX(7477_dip, TTL_7477_DIP, "")
+ ENTRYX(7483_dip, TTL_7483_DIP, "")
+ ENTRYX(7485_dip, TTL_7485_DIP, "")
+ ENTRYX(7490_dip, TTL_7490_DIP, "")
+ ENTRYX(7493_dip, TTL_7493_DIP, "")
+ ENTRYX(74107_dip, TTL_74107_DIP, "")
+ ENTRYX(74123_dip, TTL_74123_DIP, "")
+ ENTRYX(74153_dip, TTL_74153_DIP, "")
+ ENTRYX(74161_dip, TTL_74161_DIP, "")
+ ENTRYX(74164_dip, TTL_74164_DIP, "")
+ ENTRYX(74165_dip, TTL_74165_DIP, "")
+ ENTRYX(74166_dip, TTL_74166_DIP, "")
+ ENTRYX(74174_dip, TTL_74174_DIP, "")
+ ENTRYX(74175_dip, TTL_74175_DIP, "")
+ ENTRYX(74192_dip, TTL_74192_DIP, "")
+ ENTRYX(74193_dip, TTL_74193_DIP, "")
+ ENTRYX(74194_dip, TTL_74194_DIP, "")
+ ENTRYX(74365_dip, TTL_74365_DIP, "")
+ ENTRYX(82S16_dip, TTL_82S16_DIP, "")
+ ENTRYX(82S115_dip, PROM_82S115_DIP, "")
+ ENTRYX(82S123_dip, PROM_82S123_DIP, "")
+ ENTRYX(82S126_dip, PROM_82S126_DIP, "")
+ ENTRYX(9602_dip, TTL_9602_DIP, "")
+ ENTRYX(9310_dip, TTL_9310_DIP, "")
+ ENTRYX(9314_dip, TTL_9314_DIP, "")
+ ENTRYX(9316_dip, TTL_9316_DIP, "")
+ ENTRYX(9322_dip, TTL_9322_DIP, "")
+ ENTRYX(9334_dip, TTL_9334_DIP, "")
+ ENTRYX(AM2847_dip, TTL_AM2847_DIP, "")
+ ENTRYX(SN74LS629_dip, SN74LS629_DIP, "1.CAP1,2.CAP2")
+ ENTRYX(NE555_dip, NE555_DIP, "")
+ ENTRYX(MM5837_dip, MM5837_DIP, "")
+}
-} //namespace devices
+ } //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index abf58ccee16..4dead624fc2 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -35,8 +35,18 @@
#include "nld_2102A.h"
#include "nld_2716.h"
+#include "nld_tms4800.h"
#include "nld_4020.h"
#include "nld_4066.h"
+#include "nld_7448.h"
+#include "nld_7450.h"
+#include "nld_7473.h"
+#include "nld_7474.h"
+#include "nld_7475.h"
+#include "nld_7483.h"
+#include "nld_7485.h"
+#include "nld_7490.h"
+#include "nld_7493.h"
#include "nld_74107.h"
#include "nld_74123.h"
#include "nld_74153.h"
@@ -50,32 +60,21 @@
#include "nld_74193.h"
#include "nld_74194.h"
#include "nld_74365.h"
-#include "nld_7448.h"
-#include "nld_7450.h"
-#include "nld_7473.h"
-#include "nld_7474.h"
-#include "nld_7475.h"
-#include "nld_7483.h"
-#include "nld_7485.h"
-#include "nld_7490.h"
-#include "nld_7493.h"
-#include "nld_7497.h"
#include "nld_74ls629.h"
+#include "nld_82S16.h"
#include "nld_82S115.h"
#include "nld_82S123.h"
#include "nld_82S126.h"
-#include "nld_82S16.h"
#include "nld_9310.h"
#include "nld_9316.h"
#include "nld_9322.h"
-#include "nld_tms4800.h"
#include "nld_am2847.h"
#include "nld_dm9314.h"
#include "nld_dm9334.h"
-#include "nld_mm5837.h"
#include "nld_ne555.h"
+#include "nld_mm5837.h"
#include "nld_r2r_dac.h"
@@ -85,17 +84,16 @@
#include "nld_log.h"
-#include "netlist/macro/nlm_cd4xxx.h"
-#include "netlist/macro/nlm_opamp.h"
-#include "netlist/macro/nlm_other.h"
-#include "netlist/macro/nlm_ttl74xx.h"
-
-#include "netlist/analog/nld_bjt.h"
-#include "netlist/analog/nld_fourterm.h"
-#include "netlist/analog/nld_mosfet.h"
-#include "netlist/analog/nld_opamps.h"
-#include "netlist/analog/nld_switches.h"
-#include "netlist/analog/nld_twoterm.h"
+#include "../macro/nlm_cd4xxx.h"
+#include "../macro/nlm_ttl74xx.h"
+#include "../macro/nlm_opamp.h"
+#include "../macro/nlm_other.h"
+
+#include "../analog/nld_bjt.h"
+#include "../analog/nld_fourterm.h"
+#include "../analog/nld_switches.h"
+#include "../analog/nld_twoterm.h"
+#include "../analog/nld_opamps.h"
#include "nld_legacy.h"
#endif
diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp
index 0ec7132b401..5296bf2d029 100644
--- a/src/lib/netlist/devices/nld_2102A.cpp
+++ b/src/lib/netlist/devices/nld_2102A.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_2102A.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
#define ADDR2BYTE(a) ((a) >> 3)
#define ADDR2BIT(a) ((a) & 0x7)
@@ -39,7 +39,7 @@ namespace netlist
logic_output_t m_DO;
- state_array<uint8_t, 128> m_ram; // 1024x1 bits
+ state_var<uint8_t[128]> m_ram; // 1024x1 bits
param_ptr_t m_RAM;
};
@@ -97,8 +97,8 @@ namespace netlist
m_ram[i] = 0;
}
- NETLIB_DEVICE_IMPL(2102A, "RAM_2102A", "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI")
- NETLIB_DEVICE_IMPL(2102A_dip,"RAM_2102A_DIP","")
+ NETLIB_DEVICE_IMPL(2102A)
+ NETLIB_DEVICE_IMPL(2102A_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2102A.h b/src/lib/netlist/devices/nld_2102A.h
index aa53efde47d..52d892d4d40 100644
--- a/src/lib/netlist/devices/nld_2102A.h
+++ b/src/lib/netlist/devices/nld_2102A.h
@@ -24,7 +24,7 @@
#ifndef NLD_2102A_H_
#define NLD_2102A_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define RAM_2102A(name, cCEQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cRWQ, cDI) \
NET_REGISTER_DEV(RAM_2102A, name) \
diff --git a/src/lib/netlist/devices/nld_2716.cpp b/src/lib/netlist/devices/nld_2716.cpp
index b021bc95003..cb53d60e205 100644
--- a/src/lib/netlist/devices/nld_2716.cpp
+++ b/src/lib/netlist/devices/nld_2716.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_2716.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -92,8 +92,8 @@ namespace netlist
m_D[i].push((d >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(2716, "EPROM_2716", "+GQ,+EPQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
- NETLIB_DEVICE_IMPL(2716_dip, "EPROM_2716_DIP", "")
+ NETLIB_DEVICE_IMPL(2716)
+ NETLIB_DEVICE_IMPL(2716_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2716.h b/src/lib/netlist/devices/nld_2716.h
index 363086d6a37..f4776242e6a 100644
--- a/src/lib/netlist/devices/nld_2716.h
+++ b/src/lib/netlist/devices/nld_2716.h
@@ -28,7 +28,7 @@
#ifndef NLD_2716_H_
#define NLD_2716_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define EPROM_2716(name, cGQ, cEPQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cA10) \
NET_REGISTER_DEV(EPROM_2716, name) \
diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp
index 13518f9d3cb..8403d42bef2 100644
--- a/src/lib/netlist/devices/nld_4020.cpp
+++ b/src/lib/netlist/devices/nld_4020.cpp
@@ -96,9 +96,9 @@ namespace netlist
m_sub.m_IP.activate_hl();
}
- NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const unsigned cnt))
+ inline NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const unsigned cnt))
{
- static constexpr const std::array<netlist_time, 14> out_delayQn = {
+ /* static */ const netlist_time out_delayQn[14] = {
NLTIME_FROM_NS(180), NLTIME_FROM_NS(280),
NLTIME_FROM_NS(380), NLTIME_FROM_NS(480),
NLTIME_FROM_NS(580), NLTIME_FROM_NS(680),
@@ -113,8 +113,7 @@ namespace netlist
m_Q[i].push((cnt >> i) & 1, out_delayQn[i]);
}
- NETLIB_DEVICE_IMPL(CD4020, "CD4020", "")
- NETLIB_DEVICE_IMPL_ALIAS(CD4020_WI, CD4020, "CD4020_WI", "+IP,+RESET,+VDD,+VSS")
+ NETLIB_DEVICE_IMPL(CD4020)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_4020.h b/src/lib/netlist/devices/nld_4020.h
index f24251fb1dc..fd6b234da46 100644
--- a/src/lib/netlist/devices/nld_4020.h
+++ b/src/lib/netlist/devices/nld_4020.h
@@ -27,7 +27,7 @@
#ifndef NLD_4020_H_
#define NLD_4020_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
/* FIXME: only used in mario.c */
#define CD4020_WI(name, cIP, cRESET, cVDD, cVSS) \
diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp
index 0c7511ca438..ebd269a023a 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -5,11 +5,9 @@
*
*/
-#include "nld_4066.h"
-
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/solver/nld_solver.h"
#include "nlid_cmos.h"
+#include "../analog/nlid_twoterm.h"
+#include "nld_4066.h"
namespace netlist
{
@@ -29,7 +27,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- private:
+ public:
NETLIB_SUB(vdd_vss) m_supply;
analog::NETLIB_SUB(R_base) m_R;
@@ -41,36 +39,45 @@ namespace netlist
{
// Start in off condition
// FIXME: is ROFF correct?
- m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
+ m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
}
NETLIB_UPDATE(CD4066_GATE)
{
nl_double sup = (m_supply.vdd() - m_supply.vss());
- nl_double low = plib::constants<nl_double>::cast(0.45) * sup;
- nl_double high = plib::constants<nl_double>::cast(0.55) * sup;
+ nl_double low = NL_FCONST(0.45) * sup;
+ nl_double high = NL_FCONST(0.55) * sup;
nl_double in = m_control() - m_supply.vss();
- nl_double rON = m_base_r() * plib::constants<nl_double>::cast(5.0) / sup;
+ nl_double rON = m_base_r() * NL_FCONST(5.0) / sup;
nl_double R = -1.0;
if (in < low)
{
- R = plib::constants<nl_double>::one() / exec().gmin();
+ R = NL_FCONST(1.0) / netlist().gmin();
}
else if (in > high)
{
R = rON;
}
- if (R > plib::constants<nl_double>::zero())
+ if (R > NL_FCONST(0.0))
{
- m_R.update();
- m_R.set_R(R);
- m_R.solve_later();
+ // We only need to update the net first if this is a time stepping net
+ if ((1)) // m_R.m_P.net().as_analog().solver().is_timestep())
+ {
+ m_R.update_dev();
+ m_R.set_R(R);
+ m_R.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ }
+ else
+ {
+ m_R.set_R(R);
+ m_R.update_dev();
+ }
}
}
- NETLIB_DEVICE_IMPL(CD4066_GATE, "CD4066_GATE", "")
+ NETLIB_DEVICE_IMPL(CD4066_GATE)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_4066.h b/src/lib/netlist/devices/nld_4066.h
index d339464a108..e9fd579496c 100644
--- a/src/lib/netlist/devices/nld_4066.h
+++ b/src/lib/netlist/devices/nld_4066.h
@@ -24,7 +24,7 @@
#ifndef NLD_4066_H_
#define NLD_4066_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define CD4066_GATE(name) \
NET_REGISTER_DEV(CD4066_GATE, name)
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
index c8ee1a90643..b9758ff036b 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -5,10 +5,9 @@
*
*/
-#include "nld_4316.h"
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/solver/nld_solver.h"
#include "nlid_cmos.h"
+#include "../analog/nlid_twoterm.h"
+#include "nld_4316.h"
namespace netlist { namespace devices {
@@ -38,20 +37,19 @@ namespace netlist { namespace devices {
NETLIB_RESET(CD4316_GATE)
{
- m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
+ m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
}
NETLIB_UPDATE(CD4316_GATE)
{
- m_R.update();
+ m_R.update_dev();
if (m_S() && !m_E())
m_R.set_R(m_base_r());
else
- m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
- m_R.solve_later(NLTIME_FROM_NS(1));
+ m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
+ m_R.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
}
- NETLIB_DEVICE_IMPL(CD4316_GATE, "CD4316_GATE", "")
+ NETLIB_DEVICE_IMPL(CD4316_GATE)
-} // namespace devices
- } // namespace netlist
+} } // namesapce netlist::devices
diff --git a/src/lib/netlist/devices/nld_4316.h b/src/lib/netlist/devices/nld_4316.h
index 278a2793a6f..eb1d13f5542 100644
--- a/src/lib/netlist/devices/nld_4316.h
+++ b/src/lib/netlist/devices/nld_4316.h
@@ -25,7 +25,7 @@
#ifndef NLD_4316_H_
#define NLD_4316_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define CD4316_GATE(name) \
NET_REGISTER_DEV(CD4316_GATE, name)
diff --git a/src/lib/netlist/devices/nld_74107.cpp b/src/lib/netlist/devices/nld_74107.cpp
index 763760e2c6a..c5a12a15fb4 100644
--- a/src/lib/netlist/devices/nld_74107.cpp
+++ b/src/lib/netlist/devices/nld_74107.cpp
@@ -6,15 +6,15 @@
*/
#include "nld_74107.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
namespace devices
{
- static constexpr const netlist_time delay_107[2] = { NLTIME_FROM_NS(16), NLTIME_FROM_NS(25) };
- static constexpr const netlist_time delay_107A[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(15) };
+ static constexpr netlist_time delay_107[2] = { NLTIME_FROM_NS(16), NLTIME_FROM_NS(25) };
+ static constexpr netlist_time delay_107A[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(15) };
NETLIB_OBJECT(74107A)
{
@@ -22,12 +22,11 @@ namespace netlist
, m_clk(*this, "CLK", NETLIB_DELEGATE(74107A, clk))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
+ , m_delay(delay_107A)
, m_J(*this, "J")
, m_K(*this, "K")
, m_clrQ(*this, "CLRQ")
{
- m_delay[0] = delay_107A[0];
- m_delay[1] = delay_107A[1];
}
friend class NETLIB_NAME(74107_dip);
@@ -44,7 +43,7 @@ namespace netlist
logic_output_t m_Q;
logic_output_t m_QQ;
- netlist_time m_delay[2];
+ const netlist_time *m_delay;
logic_input_t m_J;
logic_input_t m_K;
@@ -62,8 +61,7 @@ namespace netlist
public:
NETLIB_CONSTRUCTOR_DERIVED(74107, 74107A)
{
- m_delay[0] = delay_107[0];
- m_delay[1] = delay_107[1];
+ m_delay = delay_107;
}
};
@@ -139,9 +137,9 @@ namespace netlist
m_clk.activate_hl();
}
- NETLIB_DEVICE_IMPL(74107, "TTL_74107", "+CLK,+J,+K,+CLRQ")
- NETLIB_DEVICE_IMPL(74107A, "TTL_74107A", "+CLK,+J,+K,+CLRQ")
- NETLIB_DEVICE_IMPL(74107_dip, "TTL_74107_DIP", "")
+ NETLIB_DEVICE_IMPL(74107)
+ NETLIB_DEVICE_IMPL(74107A)
+ NETLIB_DEVICE_IMPL(74107_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74107.h b/src/lib/netlist/devices/nld_74107.h
index c6f8864610a..b59848cbb05 100644
--- a/src/lib/netlist/devices/nld_74107.h
+++ b/src/lib/netlist/devices/nld_74107.h
@@ -64,7 +64,7 @@
#ifndef NLD_74107_H_
#define NLD_74107_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74107A(name, cCLK, cJ, cK, cCLRQ) \
NET_REGISTER_DEV(TTL_74107A, name) \
diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp
index 32e47a47ef2..9055c5ce140 100644
--- a/src/lib/netlist/devices/nld_74123.cpp
+++ b/src/lib/netlist/devices/nld_74123.cpp
@@ -6,7 +6,7 @@
*/
#include "nlid_system.h"
-#include "netlist/analog/nlid_twoterm.h"
+#include "../analog/nlid_twoterm.h"
#include <cmath>
@@ -257,8 +257,8 @@ namespace netlist
{
m_KP = 1.0 / (1.0 + exp(m_K()));
- m_RP.reset();
- m_RN.reset();
+ m_RP.do_reset();
+ m_RN.do_reset();
//m_RP.set_R(R_OFF);
//m_RN.set_R(R_OFF);
@@ -276,8 +276,8 @@ namespace netlist
NETLIB_RESET(74123_dip)
{
- //m_1.reset();
- //m_2.reset();
+ //m_1.do_reset();
+ //m_2.do_reset();
}
NETLIB_UPDATE(9602_dip)
@@ -289,8 +289,8 @@ namespace netlist
NETLIB_RESET(9602_dip)
{
- //m_1.reset();
- //m_2.reset();
+ //m_1.do_reset();
+ //m_2.do_reset();
}
NETLIB_UPDATE(4538_dip)
@@ -302,14 +302,14 @@ namespace netlist
NETLIB_RESET(4538_dip)
{
- m_1.reset();
- m_2.reset();
+ m_1.do_reset();
+ m_2.do_reset();
}
- NETLIB_DEVICE_IMPL(74123, "TTL_74123", "")
- NETLIB_DEVICE_IMPL(74123_dip, "TTL_74123_DIP", "")
- NETLIB_DEVICE_IMPL(4538_dip, "CD4538_DIP", "")
- NETLIB_DEVICE_IMPL(9602_dip, "TTL_9602_DIP", "")
+ NETLIB_DEVICE_IMPL(74123)
+ NETLIB_DEVICE_IMPL(74123_dip)
+ NETLIB_DEVICE_IMPL(4538_dip)
+ NETLIB_DEVICE_IMPL(9602_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74123.h b/src/lib/netlist/devices/nld_74123.h
index 3eca141b613..dfd75f746c7 100644
--- a/src/lib/netlist/devices/nld_74123.h
+++ b/src/lib/netlist/devices/nld_74123.h
@@ -49,7 +49,7 @@
#ifndef NLD_74123_H_
#define NLD_74123_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74123(name) \
NET_REGISTER_DEV(TTL_74123, name)
diff --git a/src/lib/netlist/devices/nld_74153.cpp b/src/lib/netlist/devices/nld_74153.cpp
index 136fe61520b..b74c09f8cc0 100644
--- a/src/lib/netlist/devices/nld_74153.cpp
+++ b/src/lib/netlist/devices/nld_74153.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74153.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -120,19 +120,19 @@ namespace netlist
NETLIB_UPDATE(74153)
{
m_sub.m_chan = (m_A() | (m_B()<<1));
- m_sub.update();
+ m_sub.update_dev();
}
NETLIB_UPDATE(74153_dip)
{
m_2.m_chan = m_1.m_chan = (m_A() | (m_B()<<1));
- m_1.update();
- m_2.update();
+ m_1.update_dev();
+ m_2.update_dev();
}
- NETLIB_DEVICE_IMPL(74153, "TTL_74153", "+C0,+C1,+C2,+C3,+A,+B,+G")
- NETLIB_DEVICE_IMPL(74153_dip, "TTL_74153_DIP", "")
+ NETLIB_DEVICE_IMPL(74153)
+ NETLIB_DEVICE_IMPL(74153_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74153.h b/src/lib/netlist/devices/nld_74153.h
index f1c0f056cf7..ee77d4224ce 100644
--- a/src/lib/netlist/devices/nld_74153.h
+++ b/src/lib/netlist/devices/nld_74153.h
@@ -45,7 +45,7 @@
#ifndef NLD_74153_H_
#define NLD_74153_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74153(name, cC0, cC1, cC2, cC3, cA, cB, cG) \
NET_REGISTER_DEV(TTL_74153, name) \
diff --git a/src/lib/netlist/devices/nld_74161.cpp b/src/lib/netlist/devices/nld_74161.cpp
index 7a3b54d6368..5eb711fb456 100644
--- a/src/lib/netlist/devices/nld_74161.cpp
+++ b/src/lib/netlist/devices/nld_74161.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74161.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -85,7 +85,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr const netlist_time delay[4] =
+ static constexpr netlist_time delay[4] =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
@@ -126,8 +126,8 @@ namespace netlist
m_RCO.push(tRippleCarryOut, NLTIME_FROM_NS(20)); //FIXME
}
- NETLIB_DEVICE_IMPL(74161, "TTL_74161", "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
- NETLIB_DEVICE_IMPL(74161_dip, "TTL_74161_DIP", "")
+ NETLIB_DEVICE_IMPL(74161)
+ NETLIB_DEVICE_IMPL(74161_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74161.h b/src/lib/netlist/devices/nld_74161.h
index f3fa3eab043..363bc3c7f0d 100644
--- a/src/lib/netlist/devices/nld_74161.h
+++ b/src/lib/netlist/devices/nld_74161.h
@@ -25,7 +25,7 @@
#ifndef NLD_74161_H_
#define NLD_74161_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74161(name, cA, cB, cC, cD, cCLRQ, cLOADQ, cCLK, cENABLEP, cENABLET) \
NET_REGISTER_DEV(TTL_74161, name) \
diff --git a/src/lib/netlist/devices/nld_74164.cpp b/src/lib/netlist/devices/nld_74164.cpp
index b1eb30bb1ba..5b2b1d8d080 100644
--- a/src/lib/netlist/devices/nld_74164.cpp
+++ b/src/lib/netlist/devices/nld_74164.cpp
@@ -9,7 +9,7 @@
*/
#include "nld_74164.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -97,8 +97,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(74164, "TTL_74164", "+A,+B,+CLRQ,+CLK")
- NETLIB_DEVICE_IMPL(74164_dip, "TTL_74164_DIP", "")
+ NETLIB_DEVICE_IMPL(74164)
+ NETLIB_DEVICE_IMPL(74164_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74164.h b/src/lib/netlist/devices/nld_74164.h
index dd4e6bd1303..d7f29d386de 100644
--- a/src/lib/netlist/devices/nld_74164.h
+++ b/src/lib/netlist/devices/nld_74164.h
@@ -42,7 +42,7 @@
#ifndef NLD_74164_H_
#define NLD_74164_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74164(name, cA, cB, cCLRQ, cCLK) \
NET_REGISTER_DEV(TTL_74164, name) \
diff --git a/src/lib/netlist/devices/nld_74165.cpp b/src/lib/netlist/devices/nld_74165.cpp
index 521bf4d63d2..678c1b1782e 100644
--- a/src/lib/netlist/devices/nld_74165.cpp
+++ b/src/lib/netlist/devices/nld_74165.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74165.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -86,7 +86,6 @@ namespace netlist
}
else if (!m_CLK() || m_CLKINH())
{
- // FIXME: qh is overwritten below?
qh = old_qh;
}
else if (!m_last_CLK)
@@ -102,8 +101,8 @@ namespace netlist
m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing
}
- NETLIB_DEVICE_IMPL(74165, "TTL_74165", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H")
- NETLIB_DEVICE_IMPL(74165_dip, "TTL_74165_DIP", "")
+ NETLIB_DEVICE_IMPL(74165)
+ NETLIB_DEVICE_IMPL(74165_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74165.h b/src/lib/netlist/devices/nld_74165.h
index d282bab622b..e38ca7bab86 100644
--- a/src/lib/netlist/devices/nld_74165.h
+++ b/src/lib/netlist/devices/nld_74165.h
@@ -27,7 +27,7 @@
#ifndef NLD_74165_H_
#define NLD_74165_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74165(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH) \
NET_REGISTER_DEV(TTL_74165, name) \
diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp
index a5049014576..32f075c4da5 100644
--- a/src/lib/netlist/devices/nld_74166.cpp
+++ b/src/lib/netlist/devices/nld_74166.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74166.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -121,8 +121,8 @@ namespace netlist
m_QH.push(qh, delay); //FIXME
}
- NETLIB_DEVICE_IMPL(74166, "TTL_74166", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ")
- NETLIB_DEVICE_IMPL(74166_dip,"TTL_74166_DIP", "")
+ NETLIB_DEVICE_IMPL(74166)
+ NETLIB_DEVICE_IMPL(74166_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74166.h b/src/lib/netlist/devices/nld_74166.h
index 80c86bb3422..b8a8a204374 100644
--- a/src/lib/netlist/devices/nld_74166.h
+++ b/src/lib/netlist/devices/nld_74166.h
@@ -27,7 +27,7 @@
#ifndef NLD_74166_H_
#define NLD_74166_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74166(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH, cCLRQ) \
NET_REGISTER_DEV(TTL_74166, name) \
diff --git a/src/lib/netlist/devices/nld_74174.cpp b/src/lib/netlist/devices/nld_74174.cpp
index 83369075db6..5f4573942bd 100644
--- a/src/lib/netlist/devices/nld_74174.cpp
+++ b/src/lib/netlist/devices/nld_74174.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74174.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -134,8 +134,8 @@ namespace netlist
//m_sub.do_reset();
}
- NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ")
- NETLIB_DEVICE_IMPL(74174_dip,"TTL_74174_DIP", "")
+ NETLIB_DEVICE_IMPL(74174)
+ NETLIB_DEVICE_IMPL(74174_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74174.h b/src/lib/netlist/devices/nld_74174.h
index f1854801291..66824abb7aa 100644
--- a/src/lib/netlist/devices/nld_74174.h
+++ b/src/lib/netlist/devices/nld_74174.h
@@ -36,7 +36,7 @@
#ifndef NLD_74174_H_
#define NLD_74174_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74174(name, cCLK, cD1, cD2, cD3, cD4, cD5, cD6, cCLRQ) \
NET_REGISTER_DEV(TTL_74174, name) \
diff --git a/src/lib/netlist/devices/nld_74175.cpp b/src/lib/netlist/devices/nld_74175.cpp
index a15adb5c60f..5955bcb389e 100644
--- a/src/lib/netlist/devices/nld_74175.cpp
+++ b/src/lib/netlist/devices/nld_74175.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74175.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -111,8 +111,8 @@ namespace netlist
m_data = 0xFF;
}
- NETLIB_DEVICE_IMPL(74175, "TTL_74175", "+CLK,+D1,+D2,+D3,+D4,+CLRQ")
- NETLIB_DEVICE_IMPL(74175_dip,"TTL_74175_DIP", "")
+ NETLIB_DEVICE_IMPL(74175)
+ NETLIB_DEVICE_IMPL(74175_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74175.h b/src/lib/netlist/devices/nld_74175.h
index 4bc8c1175ba..27e01b55b05 100644
--- a/src/lib/netlist/devices/nld_74175.h
+++ b/src/lib/netlist/devices/nld_74175.h
@@ -36,7 +36,7 @@
#ifndef NLD_74175_H_
#define NLD_74175_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74175(name, cCLK, cD1, cD2, cD3, cD4, cCLRQ) \
NET_REGISTER_DEV(TTL_74175, name) \
diff --git a/src/lib/netlist/devices/nld_74192.cpp b/src/lib/netlist/devices/nld_74192.cpp
index 954fc351179..1af605d4776 100644
--- a/src/lib/netlist/devices/nld_74192.cpp
+++ b/src/lib/netlist/devices/nld_74192.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74192.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -110,7 +110,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr const netlist_time delay[4] =
+ static constexpr netlist_time delay[4] =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
@@ -162,8 +162,8 @@ namespace netlist
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME
}
- NETLIB_DEVICE_IMPL(74192, "TTL_74192", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
- NETLIB_DEVICE_IMPL(74192_dip,"TTL_74192_DIP", "")
+ NETLIB_DEVICE_IMPL(74192)
+ NETLIB_DEVICE_IMPL(74192_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74192.h b/src/lib/netlist/devices/nld_74192.h
index 9b0139070b8..613d463cf47 100644
--- a/src/lib/netlist/devices/nld_74192.h
+++ b/src/lib/netlist/devices/nld_74192.h
@@ -29,7 +29,7 @@
#ifndef NLD_74192_H_
#define NLD_74192_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74192(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD) \
NET_REGISTER_DEV(TTL_74192, name) \
diff --git a/src/lib/netlist/devices/nld_74193.cpp b/src/lib/netlist/devices/nld_74193.cpp
index 16d7438d799..55d18f3dc1b 100644
--- a/src/lib/netlist/devices/nld_74193.cpp
+++ b/src/lib/netlist/devices/nld_74193.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74193.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -87,7 +87,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr const netlist_time delay[4] =
+ static constexpr netlist_time delay[4] =
{
NLTIME_FROM_NS(40),
NLTIME_FROM_NS(40),
@@ -139,8 +139,8 @@ namespace netlist
m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing
}
- NETLIB_DEVICE_IMPL(74193, "TTL_74193", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
- NETLIB_DEVICE_IMPL(74193_dip, "TTL_74193_DIP", "")
+ NETLIB_DEVICE_IMPL(74193)
+ NETLIB_DEVICE_IMPL(74193_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74193.h b/src/lib/netlist/devices/nld_74193.h
index a4c745d5386..bb14a301f38 100644
--- a/src/lib/netlist/devices/nld_74193.h
+++ b/src/lib/netlist/devices/nld_74193.h
@@ -26,7 +26,7 @@
#ifndef NLD_74193_H_
#define NLD_74193_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74193(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD) \
NET_REGISTER_DEV(TTL_74193, name) \
diff --git a/src/lib/netlist/devices/nld_74194.cpp b/src/lib/netlist/devices/nld_74194.cpp
index 9876aa6b170..d531e792885 100644
--- a/src/lib/netlist/devices/nld_74194.cpp
+++ b/src/lib/netlist/devices/nld_74194.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_74194.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -116,8 +116,8 @@ namespace netlist
m_Q[i].push((q >> i) & 1, NLTIME_FROM_NS(26)); // FIXME: Timing
}
- NETLIB_DEVICE_IMPL(74194, "TTL_74194", "+CLK,+S0,+S1,+SRIN,+A,+B,+C,+D,+SLIN,+CLRQ")
- NETLIB_DEVICE_IMPL(74194_dip, "TTL_74194_DIP", "")
+ NETLIB_DEVICE_IMPL(74194)
+ NETLIB_DEVICE_IMPL(74194_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74194.h b/src/lib/netlist/devices/nld_74194.h
index 5a507982b81..5124a66bcc0 100644
--- a/src/lib/netlist/devices/nld_74194.h
+++ b/src/lib/netlist/devices/nld_74194.h
@@ -26,7 +26,7 @@
#ifndef NLD_74194_H_
#define NLD_74194_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74194(name, cCLK, cS0, cS1, cSRIN, cA, cB, cC, cD, cSLIN, cCLRQ) \
NET_REGISTER_DEV(TTL_74194, name) \
diff --git a/src/lib/netlist/devices/nld_74365.cpp b/src/lib/netlist/devices/nld_74365.cpp
index 753f16bfd22..10456ebbc21 100644
--- a/src/lib/netlist/devices/nld_74365.cpp
+++ b/src/lib/netlist/devices/nld_74365.cpp
@@ -6,20 +6,12 @@
*/
#include "nld_74365.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
namespace devices
{
-
- /* FIXME: This should be a single device, i.e. one tristate buffer only.
- *
- * FIXME: Implement tristate output.
- *
- */
-
-
NETLIB_OBJECT(74365)
{
NETLIB_CONSTRUCTOR(74365)
@@ -76,8 +68,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(74365, "TTL_74365", "+G1Q,+G2Q,+A1,+A2,+A3,+A4,+A5,+A6")
- NETLIB_DEVICE_IMPL(74365_dip, "TTL_74365_DIP", "")
+ NETLIB_DEVICE_IMPL(74365)
+ NETLIB_DEVICE_IMPL(74365_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74365.h b/src/lib/netlist/devices/nld_74365.h
index a50b535383f..ca0eacf6ba1 100644
--- a/src/lib/netlist/devices/nld_74365.h
+++ b/src/lib/netlist/devices/nld_74365.h
@@ -25,7 +25,7 @@
#ifndef NLD_74365_H_
#define NLD_74365_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_74365(name, cG1Q, cG2Q, cA1, cA2, cA3, cA4, cA5, cA6) \
NET_REGISTER_DEV(TTL_74365, name) \
diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp
index 4500229a1c5..cc2e60f23b7 100644
--- a/src/lib/netlist/devices/nld_7448.cpp
+++ b/src/lib/netlist/devices/nld_7448.cpp
@@ -5,10 +5,8 @@
*
*/
+#include "nlid_truthtable.h"
#include "nld_7448.h"
-#include "nlid_truthtable.h"
-
-#include <array>
namespace netlist
{
@@ -135,9 +133,9 @@ namespace netlist
#else
-#define BITS7(b6,b5,b4,b3,b2,b1,b0) ((b6)<<6) | ((b5)<<5) | ((b4)<<4) | ((b3)<<3) | ((b2)<<2) | ((b1)<<1) | ((b0)<<0)
+#define BITS7(b6,b5,b4,b3,b2,b1,b0) (b6<<6) | (b5<<5) | (b4<<4) | (b3<<3) | (b2<<2) | (b1<<1) | (b0<<0)
- static constexpr const std::array<uint8_t, 16> tab7448 =
+ static constexpr uint8_t tab7448[16] =
{
BITS7( 1, 1, 1, 1, 1, 1, 0 ), /* 00 - not blanked ! */
BITS7( 0, 1, 1, 0, 0, 0, 0 ), /* 01 */
@@ -190,13 +188,11 @@ namespace netlist
NETLIB_RESET(7448)
{
m_state = 0;
-#if 0
- m_A.set_state(logic_t::STATE_INP_PASSIVE);
- m_B.set_state(logic_t::STATE_INP_PASSIVE);
- m_C.set_state(logic_t::STATE_INP_PASSIVE);
- m_D.set_state(logic_t::STATE_INP_PASSIVE);
- m_RBIQ.set_state(logic_t::STATE_INP_PASSIVE);
-#endif
+ m_A.inactivate();
+ m_B.inactivate();
+ m_C.inactivate();
+ m_D.inactivate();
+ m_RBIQ.inactivate();
}
NETLIB_FUNC_VOID(7448, update_outputs, (unsigned v))
@@ -215,8 +211,8 @@ namespace netlist
#endif
- NETLIB_DEVICE_IMPL(7448, "TTL_7448", "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ")
- NETLIB_DEVICE_IMPL(7448_dip, "TTL_7448_DIP", "")
+ NETLIB_DEVICE_IMPL(7448)
+ NETLIB_DEVICE_IMPL(7448_dip)
} //namespace devices
diff --git a/src/lib/netlist/devices/nld_7448.h b/src/lib/netlist/devices/nld_7448.h
index b9c03ae6360..89528707bc1 100644
--- a/src/lib/netlist/devices/nld_7448.h
+++ b/src/lib/netlist/devices/nld_7448.h
@@ -24,7 +24,7 @@
#ifndef NLD_7448_H_
#define NLD_7448_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#ifndef NL_AUTO_DEVICES
diff --git a/src/lib/netlist/devices/nld_7450.cpp b/src/lib/netlist/devices/nld_7450.cpp
index aacab46a021..af9b9afada1 100644
--- a/src/lib/netlist/devices/nld_7450.cpp
+++ b/src/lib/netlist/devices/nld_7450.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7450.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -68,10 +68,10 @@ namespace netlist
m_B.activate();
m_C.activate();
m_D.activate();
- auto t1 = m_A() & m_B();
- auto t2 = m_C() & m_D();
+ unsigned t1 = m_A() & m_B();
+ unsigned t2 = m_C() & m_D();
- const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
+ const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
uint_fast8_t res = 0;
if (t1 ^ 1)
@@ -85,20 +85,18 @@ namespace netlist
m_A.inactivate();
m_B.inactivate();
}
- }
- else
- {
+ } else {
if (t2 ^ 1)
{
m_C.inactivate();
m_D.inactivate();
}
}
- m_Q.push(res, times[res]);// ? 22000 : 15000);
+ m_Q.push(res, times[1 - res]);// ? 22000 : 15000);
}
- NETLIB_DEVICE_IMPL(7450, "TTL_7450_ANDORINVERT", "+A,+B,+C,+D")
- NETLIB_DEVICE_IMPL(7450_dip, "TTL_7450_DIP", "")
+ NETLIB_DEVICE_IMPL(7450)
+ NETLIB_DEVICE_IMPL(7450_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7450.h b/src/lib/netlist/devices/nld_7450.h
index 6718afd8f9e..652516758ad 100644
--- a/src/lib/netlist/devices/nld_7450.h
+++ b/src/lib/netlist/devices/nld_7450.h
@@ -24,7 +24,7 @@
#ifndef NLD_7450_H_
#define NLD_7450_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7450_ANDORINVERT(name, cI1, cI2, cI3, cI4) \
NET_REGISTER_DEV(TTL_7450_ANDORINVERT, name) \
diff --git a/src/lib/netlist/devices/nld_7473.cpp b/src/lib/netlist/devices/nld_7473.cpp
index c8abd829264..d9efb9fb710 100644
--- a/src/lib/netlist/devices/nld_7473.cpp
+++ b/src/lib/netlist/devices/nld_7473.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7473.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -142,10 +142,10 @@ namespace netlist
m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing
}
- NETLIB_DEVICE_IMPL(7473, "TTL_7473", "+CLK,+J,+K,+CLRQ")
- NETLIB_DEVICE_IMPL(7473A, "TTL_7473A", "+CLK,+J,+K,+CLRQ")
- NETLIB_DEVICE_IMPL(7473_dip, "TTL_7473_DIP", "")
- NETLIB_DEVICE_IMPL(7473A_dip, "TTL_7473A_DIP", "")
+ NETLIB_DEVICE_IMPL(7473)
+ NETLIB_DEVICE_IMPL(7473A)
+ NETLIB_DEVICE_IMPL(7473_dip)
+ NETLIB_DEVICE_IMPL(7473A_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7473.h b/src/lib/netlist/devices/nld_7473.h
index 3fbaaf4efbc..5313d18570c 100644
--- a/src/lib/netlist/devices/nld_7473.h
+++ b/src/lib/netlist/devices/nld_7473.h
@@ -60,7 +60,7 @@
#ifndef NLD_7473_H_
#define NLD_7473_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7473(name, cCLK, cJ, cK, cCLRQ) \
NET_REGISTER_DEV(TTL_7473, name) \
diff --git a/src/lib/netlist/devices/nld_7474.cpp b/src/lib/netlist/devices/nld_7474.cpp
index 740af6ad3c1..9d020663f46 100644
--- a/src/lib/netlist/devices/nld_7474.cpp
+++ b/src/lib/netlist/devices/nld_7474.cpp
@@ -1,4 +1,3 @@
-
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
@@ -7,47 +6,60 @@
*/
#include "nld_7474.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
namespace devices
{
-
- NETLIB_OBJECT(7474)
+ NETLIB_OBJECT(7474sub)
{
- NETLIB_CONSTRUCTOR(7474)
- , m_D(*this, "D")
- , m_CLRQ(*this, "CLRQ")
- , m_PREQ(*this, "PREQ")
- , m_CLK(*this, "CLK", NETLIB_DELEGATE(7474, clk))
+ NETLIB_CONSTRUCTOR(7474sub)
+ , m_CLK(*this, "CLK")
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
, m_nextD(*this, "m_nextD", 0)
{
}
- private:
NETLIB_RESETI();
NETLIB_UPDATEI();
- NETLIB_HANDLERI(clk);
- logic_input_t m_D;
- logic_input_t m_CLRQ;
- logic_input_t m_PREQ;
+ public:
logic_input_t m_CLK;
logic_output_t m_Q;
logic_output_t m_QQ;
+ state_var<unsigned> m_nextD;
+
+ inline void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ);
- state_var<netlist_sig_t> m_nextD;
+ private:
+
+ };
- void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ)
+ NETLIB_OBJECT(7474)
+ {
+ NETLIB_CONSTRUCTOR(7474)
+ , sub(*this, "sub")
+ , m_D(*this, "D")
+ , m_CLRQ(*this, "CLRQ")
+ , m_PREQ(*this, "PREQ")
{
- // 0: High-to-low 40 ns, 1: Low-to-high 25 ns
- static constexpr const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
- m_Q.push(stateQ, delay[stateQ]);
- m_QQ.push(stateQQ, delay[stateQQ]);
+ register_subalias("CLK", sub.m_CLK);
+
+ register_subalias("Q", sub.m_Q);
+ register_subalias("QQ", sub.m_QQ);
}
+
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+
+ public:
+ NETLIB_SUB(7474sub) sub;
+
+ logic_input_t m_D;
+ logic_input_t m_CLRQ;
+ logic_input_t m_PREQ;
};
NETLIB_OBJECT(7474_dip)
@@ -56,20 +68,20 @@ namespace netlist
, m_1(*this, "1")
, m_2(*this, "2")
{
- register_subalias("1", "1.CLRQ");
- register_subalias("2", "1.D");
- register_subalias("3", "1.CLK");
- register_subalias("4", "1.PREQ");
- register_subalias("5", "1.Q");
- register_subalias("6", "1.QQ");
+ register_subalias("1", m_1.m_CLRQ);
+ register_subalias("2", m_1.m_D);
+ register_subalias("3", m_1.sub.m_CLK);
+ register_subalias("4", m_1.m_PREQ);
+ register_subalias("5", m_1.sub.m_Q);
+ register_subalias("6", m_1.sub.m_QQ);
// register_subalias("7", ); ==> GND
- register_subalias("8", "2.QQ");
- register_subalias("9", "2.Q");
- register_subalias("10", "2.PREQ");
- register_subalias("11", "2.CLK");
- register_subalias("12", "2.D");
- register_subalias("13", "2.CLRQ");
+ register_subalias("8", m_2.sub.m_QQ);
+ register_subalias("9", m_2.sub.m_Q);
+ register_subalias("10", m_2.m_PREQ);
+ register_subalias("11", m_2.sub.m_CLK);
+ register_subalias("12", m_2.m_D);
+ register_subalias("13", m_2.m_CLRQ);
// register_subalias("14", ); ==> VCC
}
NETLIB_UPDATEI();
@@ -80,47 +92,77 @@ namespace netlist
NETLIB_SUB(7474) m_2;
};
- NETLIB_HANDLER(7474, clk)
+ inline void NETLIB_NAME(7474sub)::newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ)
{
- newstate(m_nextD, !m_nextD);
- m_CLK.inactivate();
+ // 0: High-to-low 40 ns, 1: Low-to-high 25 ns
+ const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
+ m_Q.push(stateQ, delay[stateQ]);
+ m_QQ.push(stateQQ, delay[stateQQ]);
+ }
+
+ NETLIB_UPDATE(7474sub)
+ {
+ //if (INP_LH(m_CLK))
+ {
+ newstate(m_nextD, !m_nextD);
+ m_CLK.inactivate();
+ }
}
NETLIB_UPDATE(7474)
{
- const auto preq(m_PREQ());
- const auto clrq(m_CLRQ());
- if (preq & clrq)
+ if (m_PREQ() && m_CLRQ())
{
m_D.activate();
- m_nextD = m_D();
- m_CLK.activate_lh();
+ sub.m_nextD = m_D();
+ sub.m_CLK.activate_lh();
+ }
+ else if (!m_PREQ())
+ {
+ sub.newstate(1, 0);
+ sub.m_CLK.inactivate();
+ m_D.inactivate();
+ }
+ else if (!m_CLRQ())
+ {
+ sub.newstate(0, 1);
+ sub.m_CLK.inactivate();
+ m_D.inactivate();
}
else
{
- newstate(preq ^ 1, clrq ^ 1);
- m_CLK.inactivate();
+ sub.newstate(1, 1);
+ sub.m_CLK.inactivate();
m_D.inactivate();
}
}
NETLIB_RESET(7474)
{
+ sub.do_reset();
+ }
+
+ NETLIB_RESET(7474sub)
+ {
m_CLK.set_state(logic_t::STATE_INP_LH);
- m_D.set_state(logic_t::STATE_INP_ACTIVE);
+
m_nextD = 0;
}
NETLIB_RESET(7474_dip)
{
+ // m_1.do_reset();
+ //m_2.do_reset();
}
NETLIB_UPDATE(7474_dip)
{
+ //m_1.update_dev();
+ //m_2.update_dev();
}
- NETLIB_DEVICE_IMPL(7474, "TTL_7474", "+CLK,+D,+CLRQ,+PREQ")
- NETLIB_DEVICE_IMPL(7474_dip, "TTL_7474_DIP", "")
+ NETLIB_DEVICE_IMPL(7474)
+ NETLIB_DEVICE_IMPL(7474_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7474.h b/src/lib/netlist/devices/nld_7474.h
index 48fd4f3d842..aa48e240387 100644
--- a/src/lib/netlist/devices/nld_7474.h
+++ b/src/lib/netlist/devices/nld_7474.h
@@ -42,7 +42,7 @@
#ifndef NLD_7474_H_
#define NLD_7474_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7474(name, cCLK, cD, cCLRQ, cPREQ) \
NET_REGISTER_DEV(TTL_7474, name) \
diff --git a/src/lib/netlist/devices/nld_7475.cpp b/src/lib/netlist/devices/nld_7475.cpp
index 63fd355d406..b2d28048513 100644
--- a/src/lib/netlist/devices/nld_7475.cpp
+++ b/src/lib/netlist/devices/nld_7475.cpp
@@ -7,7 +7,7 @@
*/
#include "nld_7475.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -101,7 +101,7 @@ namespace netlist
{
unsigned start_q = m_last_Q;
- NETLIB_NAME(7477)::update();
+ NETLIB_PARENT_UPDATE(7477);
for (std::size_t i=0; i<4; i++)
{
@@ -148,10 +148,10 @@ namespace netlist
}
- NETLIB_DEVICE_IMPL(7475, "TTL_7475", "")
- NETLIB_DEVICE_IMPL(7475_dip, "TTL_7475_DIP", "")
- NETLIB_DEVICE_IMPL(7477, "TTL_7477", "")
- NETLIB_DEVICE_IMPL(7477_dip, "TTL_7477_DIP", "")
+ NETLIB_DEVICE_IMPL(7475)
+ NETLIB_DEVICE_IMPL(7475_dip)
+ NETLIB_DEVICE_IMPL(7477)
+ NETLIB_DEVICE_IMPL(7477_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7475.h b/src/lib/netlist/devices/nld_7475.h
index b16fabe61b6..51d09e75a66 100644
--- a/src/lib/netlist/devices/nld_7475.h
+++ b/src/lib/netlist/devices/nld_7475.h
@@ -35,7 +35,7 @@
#ifndef NLD_7475_H_
#define NLD_7475_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) \
NET_CONNECT(name, C1C2, cC1C2) \
diff --git a/src/lib/netlist/devices/nld_7483.cpp b/src/lib/netlist/devices/nld_7483.cpp
index 5f820162209..72c86c003d5 100644
--- a/src/lib/netlist/devices/nld_7483.cpp
+++ b/src/lib/netlist/devices/nld_7483.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7483.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -16,16 +16,14 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(7483)
, m_C0(*this, "C0")
- , m_A1(*this, "A1", NETLIB_DELEGATE(7483, upd_a))
- , m_A2(*this, "A2", NETLIB_DELEGATE(7483, upd_a))
- , m_A3(*this, "A3", NETLIB_DELEGATE(7483, upd_a))
- , m_A4(*this, "A4", NETLIB_DELEGATE(7483, upd_a))
- , m_B1(*this, "B1", NETLIB_DELEGATE(7483, upd_b))
- , m_B2(*this, "B2", NETLIB_DELEGATE(7483, upd_b))
- , m_B3(*this, "B3", NETLIB_DELEGATE(7483, upd_b))
- , m_B4(*this, "B4", NETLIB_DELEGATE(7483, upd_b))
- , m_a(*this, "m_a", 0)
- , m_b(*this, "m_b", 0)
+ , m_A1(*this, "A1")
+ , m_A2(*this, "A2")
+ , m_A3(*this, "A3")
+ , m_A4(*this, "A4")
+ , m_B1(*this, "B1")
+ , m_B2(*this, "B2")
+ , m_B3(*this, "B3")
+ , m_B4(*this, "B4")
, m_lastr(*this, "m_lastr", 0)
, m_S1(*this, "S1")
, m_S2(*this, "S2")
@@ -36,8 +34,6 @@ namespace netlist
}
NETLIB_RESETI();
NETLIB_UPDATEI();
- NETLIB_HANDLERI(upd_a);
- NETLIB_HANDLERI(upd_b);
protected:
logic_input_t m_C0;
@@ -50,9 +46,7 @@ namespace netlist
logic_input_t m_B3;
logic_input_t m_B4;
- state_var_u8 m_a;
- state_var_u8 m_b;
- state_var_u8 m_lastr;
+ state_var<unsigned> m_lastr;
logic_output_t m_S1;
logic_output_t m_S2;
@@ -93,21 +87,12 @@ namespace netlist
m_lastr = 0;
}
- NETLIB_HANDLER(7483, upd_a)
- {
- m_a = static_cast<uint8_t>((m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3));
- NETLIB_NAME(7483)::update();
- }
-
- NETLIB_HANDLER(7483, upd_b)
- {
- m_b = static_cast<uint8_t>((m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3));
- NETLIB_NAME(7483)::update();
- }
-
NETLIB_UPDATE(7483)
{
- auto r = static_cast<uint8_t>(m_a + m_b + m_C0());
+ netlist_sig_t a = (m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3);
+ netlist_sig_t b = (m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3);
+
+ unsigned r = a + b + m_C0();
if (r != m_lastr)
{
@@ -120,8 +105,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(7483, "TTL_7483", "+A1,+A2,+A3,+A4,+B1,+B2,+B3,+B4,+C0")
- NETLIB_DEVICE_IMPL(7483_dip, "TTL_7483_DIP", "")
+ NETLIB_DEVICE_IMPL(7483)
+ NETLIB_DEVICE_IMPL(7483_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7483.h b/src/lib/netlist/devices/nld_7483.h
index ba82d5bbb9c..24952bf0501 100644
--- a/src/lib/netlist/devices/nld_7483.h
+++ b/src/lib/netlist/devices/nld_7483.h
@@ -27,7 +27,7 @@
#ifndef NLD_7483_H_
#define NLD_7483_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7483(name, cA1, cA2, cA3, cA4, cB1, cB2, cB3, cB4, cCI) \
NET_REGISTER_DEV(TTL_7483, name) \
diff --git a/src/lib/netlist/devices/nld_7485.cpp b/src/lib/netlist/devices/nld_7485.cpp
index cadb73000ff..320cf762f26 100644
--- a/src/lib/netlist/devices/nld_7485.cpp
+++ b/src/lib/netlist/devices/nld_7485.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7485.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -101,8 +101,8 @@ namespace netlist
update_outputs(1, 1, 0);
}
- NETLIB_DEVICE_IMPL(7485, "TTL_7485", "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN")
- NETLIB_DEVICE_IMPL(7485_dip, "TTL_7485_DIP", "")
+ NETLIB_DEVICE_IMPL(7485)
+ NETLIB_DEVICE_IMPL(7485_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7485.h b/src/lib/netlist/devices/nld_7485.h
index 7890f4dbd2a..61b87c37ba3 100644
--- a/src/lib/netlist/devices/nld_7485.h
+++ b/src/lib/netlist/devices/nld_7485.h
@@ -23,7 +23,7 @@
#ifndef NLD_7485_H_
#define NLD_7485_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7485(name, cA0, cA1, cA2, cA3, cB0, cB1, cB2, cB3, cLTIN, cEQIN, cGTIN) \
NET_REGISTER_DEV(TTL_7485, name) \
diff --git a/src/lib/netlist/devices/nld_7490.cpp b/src/lib/netlist/devices/nld_7490.cpp
index acbe0fa4d7a..13e69c6aa31 100644
--- a/src/lib/netlist/devices/nld_7490.cpp
+++ b/src/lib/netlist/devices/nld_7490.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7490.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -28,10 +28,10 @@ namespace netlist
{
}
- private:
NETLIB_UPDATEI();
NETLIB_RESETI();
+ protected:
void update_outputs();
logic_input_t m_A;
@@ -52,22 +52,22 @@ namespace netlist
{
NETLIB_CONSTRUCTOR_DERIVED(7490_dip, 7490)
{
- register_subalias("1", "B");
- register_subalias("2", "R1");
- register_subalias("3", "R2");
+ register_subalias("1", m_B);
+ register_subalias("2", m_R1);
+ register_subalias("3", m_R2);
// register_subalias("4", ); --> NC
// register_subalias("5", ); --> VCC
- register_subalias("6", "R91");
- register_subalias("7", "R92");
+ register_subalias("6", m_R91);
+ register_subalias("7", m_R92);
- register_subalias("8", "QC");
- register_subalias("9", "QB");
+ register_subalias("8", m_Q[2]);
+ register_subalias("9", m_Q[1]);
// register_subalias("10", ); --> GND
- register_subalias("11", "QD");
- register_subalias("12", "QA");
+ register_subalias("11", m_Q[3]);
+ register_subalias("12", m_Q[0]);
// register_subalias("13", ); --> NC
- register_subalias("14", "A");
+ register_subalias("14", m_A);
}
};
@@ -78,13 +78,12 @@ namespace netlist
m_last_B = 0;
}
- static constexpr const netlist_time delay[4] =
+ static C14CONSTEXPR const netlist_time delay[4] =
{
NLTIME_FROM_NS(18),
NLTIME_FROM_NS(36) - NLTIME_FROM_NS(18),
NLTIME_FROM_NS(54) - NLTIME_FROM_NS(18),
- NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18)
- };
+ NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18)};
NETLIB_UPDATE(7490)
{
@@ -120,14 +119,14 @@ namespace netlist
m_last_B = new_B;
}
- NETLIB_FUNC_VOID(7490, update_outputs, ())
+ NETLIB_FUNC_VOID(7490, update_outputs, (void))
{
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
}
- NETLIB_DEVICE_IMPL(7490, "TTL_7490", "+A,+B,+R1,+R2,+R91,+R92")
- NETLIB_DEVICE_IMPL(7490_dip, "TTL_7490_DIP", "")
+ NETLIB_DEVICE_IMPL(7490)
+ NETLIB_DEVICE_IMPL(7490_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7490.h b/src/lib/netlist/devices/nld_7490.h
index e2fa5094911..5ff18543b03 100644
--- a/src/lib/netlist/devices/nld_7490.h
+++ b/src/lib/netlist/devices/nld_7490.h
@@ -55,7 +55,7 @@
#ifndef NLD_7490_H_
#define NLD_7490_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7490(name, cA, cB, cR1, cR2, cR91, cR92) \
NET_REGISTER_DEV(TTL_7490, name) \
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index f26e1c237d5..f3c68f7a5c2 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -6,22 +6,23 @@
*/
#include "nld_7493.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
namespace devices
{
- static constexpr const netlist_time out_delay = NLTIME_FROM_NS(18);
- static constexpr const netlist_time out_delay2 = NLTIME_FROM_NS(36);
- static constexpr const netlist_time out_delay3 = NLTIME_FROM_NS(54);
+ static constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
+ static constexpr netlist_time out_delay2 = NLTIME_FROM_NS(36);
+ static constexpr netlist_time out_delay3 = NLTIME_FROM_NS(54);
NETLIB_OBJECT(7493)
{
NETLIB_CONSTRUCTOR(7493)
, m_R1(*this, "R1")
, m_R2(*this, "R2")
+ , m_reset(*this, "_m_reset", 0)
, m_a(*this, "_m_a", 0)
, m_bcd(*this, "_m_b", 0)
, m_CLKA(*this, "CLKA", NETLIB_DELEGATE(7493, updA))
@@ -34,51 +35,35 @@ namespace netlist
}
private:
- NETLIB_RESETI()
- {
- m_a = m_bcd = 0;
- m_CLKA.set_state(logic_t::STATE_INP_HL);
- m_CLKB.set_state(logic_t::STATE_INP_HL);
- }
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
- NETLIB_UPDATEI()
+ NETLIB_HANDLERI(updA)
{
- if (!(m_R1() & m_R2()))
- {
- m_CLKA.activate_hl();
- m_CLKB.activate_hl();
- }
- else
+ if (m_reset)
{
- m_CLKA.inactivate();
- m_CLKB.inactivate();
- m_QA.push(0, NLTIME_FROM_NS(40));
- m_QB.push(0, NLTIME_FROM_NS(40));
- m_QC.push(0, NLTIME_FROM_NS(40));
- m_QD.push(0, NLTIME_FROM_NS(40));
- m_a = m_bcd = 0;
+ m_a ^= 1;
+ m_QA.push(m_a, out_delay);
}
}
- NETLIB_HANDLERI(updA)
- {
- m_a ^= 1;
- m_QA.push(m_a, out_delay);
- }
-
NETLIB_HANDLERI(updB)
{
- auto cnt = (++m_bcd &= 0x07);
- m_QD.push((cnt >> 2) & 1, out_delay3);
- m_QC.push((cnt >> 1) & 1, out_delay2);
- m_QB.push(cnt & 1, out_delay);
+ if (m_reset)
+ {
+ ++m_bcd &= static_cast<std::uint8_t>(0x07);
+ m_QD.push((m_bcd >> 2) & 1, out_delay3);
+ m_QC.push((m_bcd >> 1) & 1, out_delay2);
+ m_QB.push(m_bcd & 1, out_delay);
+ }
}
logic_input_t m_R1;
logic_input_t m_R2;
+ state_var_sig m_reset;
state_var_sig m_a;
- state_var_u8 m_bcd;
+ state_var_sig m_bcd;
logic_input_t m_CLKA;
logic_input_t m_CLKB;
@@ -112,9 +97,37 @@ namespace netlist
}
};
+ NETLIB_RESET(7493)
+ {
+ m_reset = 1;
+ m_a = m_bcd = 0;
+ m_CLKA.set_state(logic_t::STATE_INP_HL);
+ m_CLKB.set_state(logic_t::STATE_INP_HL);
+ }
+
+ NETLIB_UPDATE(7493)
+ {
+ m_reset = (m_R1() & m_R2()) ^ 1;
+
+ if (m_reset)
+ {
+ m_CLKA.activate_hl();
+ m_CLKB.activate_hl();
+ }
+ else
+ {
+ m_CLKA.inactivate();
+ m_CLKB.inactivate();
+ m_QA.push_force(0, NLTIME_FROM_NS(40));
+ m_QB.push_force(0, NLTIME_FROM_NS(40));
+ m_QC.push_force(0, NLTIME_FROM_NS(40));
+ m_QD.push_force(0, NLTIME_FROM_NS(40));
+ m_a = m_bcd = 0;
+ }
+ }
- NETLIB_DEVICE_IMPL(7493, "TTL_7493", "+CLKA,+CLKB,+R1,+R2")
- NETLIB_DEVICE_IMPL(7493_dip, "TTL_7493_DIP", "")
+ NETLIB_DEVICE_IMPL(7493)
+ NETLIB_DEVICE_IMPL(7493_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7493.h b/src/lib/netlist/devices/nld_7493.h
index 68ad90885ec..ce9566aa28f 100644
--- a/src/lib/netlist/devices/nld_7493.h
+++ b/src/lib/netlist/devices/nld_7493.h
@@ -57,7 +57,7 @@
#ifndef NLD_7493_H_
#define NLD_7493_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_7493(name, cCLKA, cCLKB, cR1, cR2) \
NET_REGISTER_DEV(TTL_7493, name) \
diff --git a/src/lib/netlist/devices/nld_7497.cpp b/src/lib/netlist/devices/nld_7497.cpp
deleted file mode 100644
index 1432884b8dd..00000000000
--- a/src/lib/netlist/devices/nld_7497.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Sergey Svishchev
-/*
- * nld_7497.cpp
- *
- * To do:
- *
- * - STRB and EN
- * - Timing
- */
-
-#include "nld_7497.h"
-#include "netlist/nl_base.h"
-
-namespace netlist
-{
- namespace devices
- {
-
- static constexpr const netlist_time out_delay_CLK_Y[2] = { NLTIME_FROM_NS(20), NLTIME_FROM_NS(26) }; // tPHL, tPLH
- static constexpr const netlist_time out_delay_CLK_Z[2] = { NLTIME_FROM_NS(17), NLTIME_FROM_NS(12) };
-
- NETLIB_OBJECT(7497)
- {
- NETLIB_CONSTRUCTOR(7497)
- , m_B(*this, {{"B5", "B4", "B3", "B2", "B1", "B0"}})
- , m_CLK(*this, "CLK", NETLIB_DELEGATE(7497, clk_strb))
- , m_STRBQ(*this, "STRBQ", NETLIB_DELEGATE(7497, clk_strb))
- , m_ENQ(*this, "ENQ")
- , m_UNITYQ(*this, "UNITYQ", NETLIB_DELEGATE(7497, unity))
- , m_CLR(*this, "CLR", NETLIB_DELEGATE(7497, clr))
- , m_Y(*this, "Y")
- , m_ZQ(*this, "ZQ")
- , m_ENOUTQ(*this, "ENOUTQ")
- , m_cnt(*this, "_m_cnt", 0)
- , m_rate(*this, "_m_rate", 0)
- , m_state(*this, "_m_state", 0)
- , m_lastclock(*this, "_m_lastclock", 0)
- {
- }
-
- private:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
-
- NETLIB_HANDLERI(noop) { }
- NETLIB_HANDLERI(unity);
- NETLIB_HANDLERI(clr);
- NETLIB_HANDLERI(clk_strb);
-
- protected:
- object_array_t<logic_input_t, 6> m_B;
- logic_input_t m_CLK;
- logic_input_t m_STRBQ;
- logic_input_t m_ENQ;
- logic_input_t m_UNITYQ;
- logic_input_t m_CLR;
-
- logic_output_t m_Y;
- logic_output_t m_ZQ;
- logic_output_t m_ENOUTQ;
-
- state_var_u8 m_cnt;
- state_var_u8 m_rate;
- state_var_sig m_state;
- state_var_sig m_lastclock;
-
- void newstate(const netlist_sig_t state)
- {
- m_state = state;
- m_ZQ.push(state, out_delay_CLK_Z[state]);
- //netlist_sig_t y = (state ^ 1) | (m_UNITY() ^ 1); // OR with negated inputs == NAND
- netlist_sig_t y = (state & m_UNITYQ()) ^ 1; // OR with negated inputs == NAND
- m_Y.push(y, out_delay_CLK_Y[y]);
- }
-
- uint8_t rate()
- {
- uint8_t a = 0;
-
- for (std::size_t i = 0; i < 6; i++)
- a |= (m_B[i]() << i);
-
- return a;
- }
- };
-
- NETLIB_RESET(7497)
- {
- m_cnt = 0;
- m_rate = 0;
- m_lastclock = 0;
- }
-
- NETLIB_UPDATE(7497)
- {
- m_rate = rate();
- clk_strb();
- }
-
- NETLIB_HANDLER(7497, unity)
- {
- newstate (m_state);
- }
-
- NETLIB_HANDLER(7497, clr)
- {
- m_cnt = 0;
- clk_strb();
- }
-
- NETLIB_HANDLER(7497, clk_strb)
- {
- netlist_sig_t clk = m_CLK();
-
- if (!m_lastclock && clk && !m_ENQ() && !m_CLR())
- {
- m_cnt++;
- m_cnt &= 63;
- }
- m_lastclock = clk;
-
- const netlist_sig_t clk_strb = (clk ^ 1) & (m_STRBQ() ^ 1);
-
- const netlist_sig_t cntQ = m_cnt;
-
- // NOR GATE
- netlist_sig_t p1 = ((cntQ & 63) == 31 && (m_rate & 32)) ||
- ((cntQ & 31) == 15 && (m_rate & 16)) ||
- ((cntQ & 15) == 7 && (m_rate & 8)) ||
- ((cntQ & 7) == 3 && (m_rate & 4)) ||
- ((cntQ & 3) == 1 && (m_rate & 2)) ||
- ((cntQ & 1) == 0 && (m_rate & 1));
-
- p1 = (p1 & clk_strb) ^ 1;
-
- newstate(p1);
-
- // NAND gate
- if ((m_cnt == 63) && !m_ENQ())
- m_ENOUTQ.push(0, out_delay_CLK_Y[0]); // XXX timing
- else
- m_ENOUTQ.push(1, out_delay_CLK_Y[1]);
-
- }
-
- NETLIB_OBJECT_DERIVED(7497_dip, 7497)
- {
- NETLIB_CONSTRUCTOR_DERIVED(7497_dip, 7497)
- {
- register_subalias("1", m_B[4]); // B0
- register_subalias("2", m_B[1]); // B4
- register_subalias("3", m_B[0]); // B5
- register_subalias("4", m_B[5]); // B0
- register_subalias("5", m_ZQ);
- register_subalias("6", m_Y);
- register_subalias("7", m_ENOUTQ);
-
- register_subalias("9", m_CLK);
- register_subalias("10", m_STRBQ);
- register_subalias("11", m_UNITYQ);
- register_subalias("12", m_ENQ);
- register_subalias("13", m_CLR);
- register_subalias("14", m_B[3]); // B2
- register_subalias("15", m_B[2]); // B3
- }
- };
-
-
- NETLIB_DEVICE_IMPL(7497, "TTL_7497", "+CLK,+STRBQ,+ENQ,+UNITYQ,+CLR,+B0,+B1,+B2,+B3,+B4,+B5")
- NETLIB_DEVICE_IMPL(7497_dip, "TTL_7497_DIP", "")
-
- } //namespace devices
-} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7497.h b/src/lib/netlist/devices/nld_7497.h
deleted file mode 100644
index 8d14e08a49b..00000000000
--- a/src/lib/netlist/devices/nld_7497.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Sergey Svishchev
-/*
- * nld_7497.h
- *
- * SN7497: Synchronous 6-Bit Binary Rate Multiplier
- *
- * +--------------+
- * B1 |1 16| VCC
- * B4 |2 15| B3
- * B5 |3 14| B2
- * B0 |4 7497 13| CLR
- * Z |5 12| UNITY/CAS
- * Y |6 11| ENin (EN)
- * ENout |7 10| STRB
- * GND |8 9| CLK
- * +--------------+
- *
- * Naming conventions follow TI datasheet
- *
- * The counter is enabled when the clear, strobe, and enable inputs are low.
- *
- * When the rate input is binary 0 (all rate inputs low), Z remains high [and Y low].
- *
- * The unity/cascade input, when connected to the clock input, passes
- * clock frequency (inverted) to the Y output when the rate input/decoding
- * gates are inhibited by the strobe.
- *
- * When CLR is H, states of CLK and STRB can affect Y and Z. Default are
- * Y L, Z H, ENout H.
- *
- * Unity/cascade is used to inhibit output Y (UNITY L -> Y H)
- */
-
-#ifndef NLD_7497_H_
-#define NLD_7497_H_
-
-#include "netlist/nl_setup.h"
-
-#define TTL_7497(name, cCLK, cSTRB, cEN, cUNITY, cCLR, cB0, cB1, cB2, cB3, cB4, cB5) \
- NET_REGISTER_DEV(TTL_7497, name) \
- NET_CONNECT(name, CLK, cCLK) \
- NET_CONNECT(name, STRBQ, cSTRB) \
- NET_CONNECT(name, ENQ, cEN) \
- NET_CONNECT(name, UNITYQ,cUNITY) \
- NET_CONNECT(name, CLR, cCLR) \
- NET_CONNECT(name, B0, cB0) \
- NET_CONNECT(name, B1, cB1) \
- NET_CONNECT(name, B2, cB2) \
- NET_CONNECT(name, B3, cB3) \
- NET_CONNECT(name, B4, cB4) \
- NET_CONNECT(name, B5, cB5)
-
-#define TTL_7497_DIP(name) \
- NET_REGISTER_DEV(TTL_7497_DIP, name)
-
-#endif /* NLD_7497_H_ */
diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp
index b7bb729b334..d6dc268ed28 100644
--- a/src/lib/netlist/devices/nld_74ls629.cpp
+++ b/src/lib/netlist/devices/nld_74ls629.cpp
@@ -40,7 +40,7 @@
#include "nld_74ls629.h"
-#include "netlist/analog/nlid_twoterm.h"
+#include "../analog/nlid_twoterm.h"
namespace netlist
{
@@ -100,14 +100,11 @@ namespace netlist
{
m_R_FC.set_R(90000.0);
m_R_RNG.set_R(90000.0);
- m_clock.reset();
+ m_clock.do_reset();
}
NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI()
- {
- /* update param may be called from anywhere, update_dev(time) is not a good idea */
- }
+ NETLIB_UPDATE_PARAMI() { update_dev(); }
public:
NETLIB_SUB(SN74LS629clk) m_clock;
@@ -148,8 +145,8 @@ namespace netlist
NETLIB_RESETI()
{
- m_1.reset();
- m_2.reset();
+ m_1.do_reset();
+ m_2.do_reset();
}
private:
@@ -210,7 +207,7 @@ namespace netlist
freq += k9 * v_rng * v_freq_3;
freq += k10 * v_rng * v_freq_4;
- freq *= plib::constants<nl_double>::cast(0.1e-6) / m_CAP();
+ freq *= NL_FCONST(0.1e-6) / m_CAP();
// FIXME: we need a possibility to remove entries from queue ...
// or an exact model ...
@@ -234,8 +231,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP")
- NETLIB_DEVICE_IMPL(SN74LS629_dip, "SN74LS629_DIP", "1.CAP1,2.CAP2")
+ NETLIB_DEVICE_IMPL(SN74LS629)
+ NETLIB_DEVICE_IMPL(SN74LS629_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74ls629.h b/src/lib/netlist/devices/nld_74ls629.h
index 30d15d70865..3351524a60b 100644
--- a/src/lib/netlist/devices/nld_74ls629.h
+++ b/src/lib/netlist/devices/nld_74ls629.h
@@ -28,7 +28,7 @@
#ifndef NLD_74LS629_H_
#define NLD_74LS629_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define SN74LS629(name, p_cap) \
NET_REGISTER_DEV(SN74LS629, name) \
diff --git a/src/lib/netlist/devices/nld_82S115.cpp b/src/lib/netlist/devices/nld_82S115.cpp
index 8ae6cbb6097..2e24bbf9fed 100644
--- a/src/lib/netlist/devices/nld_82S115.cpp
+++ b/src/lib/netlist/devices/nld_82S115.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_82S115.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -106,8 +106,8 @@ namespace netlist
m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(40)); // FIXME: Timing
}
- NETLIB_DEVICE_IMPL(82S115, "PROM_82S115", "+CE1Q,+CE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+STROBE")
- NETLIB_DEVICE_IMPL(82S115_dip, "PROM_82S115_DIP", "")
+ NETLIB_DEVICE_IMPL(82S115)
+ NETLIB_DEVICE_IMPL(82S115_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S115.h b/src/lib/netlist/devices/nld_82S115.h
index 8c13fd8b51e..ef7f1ec3910 100644
--- a/src/lib/netlist/devices/nld_82S115.h
+++ b/src/lib/netlist/devices/nld_82S115.h
@@ -28,7 +28,7 @@
#ifndef NLD_82S115_H_
#define NLD_82S115_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define PROM_82S115(name, cCE1Q, cCE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cSTROBE) \
NET_REGISTER_DEV(PROM_82S115, name) \
diff --git a/src/lib/netlist/devices/nld_82S123.cpp b/src/lib/netlist/devices/nld_82S123.cpp
index 4a80b57e349..a8a6bfc9b57 100644
--- a/src/lib/netlist/devices/nld_82S123.cpp
+++ b/src/lib/netlist/devices/nld_82S123.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_82S123.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -77,8 +77,8 @@ namespace netlist
m_O[i].push((o >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(82S123, "PROM_82S123", "+CEQ,+A0,+A1,+A2,+A3,+A4")
- NETLIB_DEVICE_IMPL(82S123_dip, "PROM_82S123_DIP", "")
+ NETLIB_DEVICE_IMPL(82S123)
+ NETLIB_DEVICE_IMPL(82S123_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S123.h b/src/lib/netlist/devices/nld_82S123.h
index 2c18377934d..dbf6bf63180 100644
--- a/src/lib/netlist/devices/nld_82S123.h
+++ b/src/lib/netlist/devices/nld_82S123.h
@@ -25,7 +25,7 @@
#ifndef NLD_82S123_H_
#define NLD_82S123_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define PROM_82S123(name, cCEQ, cA0, cA1, cA2, cA3, cA4) \
NET_REGISTER_DEV(PROM_82S123, name) \
diff --git a/src/lib/netlist/devices/nld_82S126.cpp b/src/lib/netlist/devices/nld_82S126.cpp
index b1752908645..dcacd1ec876 100644
--- a/src/lib/netlist/devices/nld_82S126.cpp
+++ b/src/lib/netlist/devices/nld_82S126.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_82S126.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -79,8 +79,8 @@ namespace netlist
m_O[i].push((o >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(82S126, "PROM_82S126", "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7")
- NETLIB_DEVICE_IMPL(82S126_dip, "PROM_82S126_DIP", "")
+ NETLIB_DEVICE_IMPL(82S126)
+ NETLIB_DEVICE_IMPL(82S126_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S126.h b/src/lib/netlist/devices/nld_82S126.h
index ed7aa131819..3079bb8e2e0 100644
--- a/src/lib/netlist/devices/nld_82S126.h
+++ b/src/lib/netlist/devices/nld_82S126.h
@@ -24,7 +24,7 @@
#ifndef NLD_82S126_H_
#define NLD_82S126_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define PROM_82S126(name, cCE1Q, cCE2Q, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7) \
NET_REGISTER_DEV(PROM_82S126, name) \
diff --git a/src/lib/netlist/devices/nld_82S16.cpp b/src/lib/netlist/devices/nld_82S16.cpp
index e3176c7b30f..7441f6c677e 100644
--- a/src/lib/netlist/devices/nld_82S16.cpp
+++ b/src/lib/netlist/devices/nld_82S16.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_82S16.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -15,55 +15,19 @@ namespace netlist
NETLIB_OBJECT(82S16)
{
NETLIB_CONSTRUCTOR(82S16)
- , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }}, NETLIB_DELEGATE(82S16, addr))
- , m_CE1Q(*this, "CE1Q", NETLIB_DELEGATE(82S16, enq))
- , m_CE2Q(*this, "CE2Q", NETLIB_DELEGATE(82S16, enq))
- , m_CE3Q(*this, "CE3Q", NETLIB_DELEGATE(82S16, enq))
+ , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }})
+ , m_CE1Q(*this, "CE1Q")
+ , m_CE2Q(*this, "CE2Q")
+ , m_CE3Q(*this, "CE3Q")
, m_WEQ(*this, "WEQ")
, m_DIN(*this, "DIN")
, m_DOUTQ(*this, "DOUTQ")
, m_ram(*this, "m_ram", 0)
- , m_addr(*this, "m_addr", 0)
- , m_enq(*this, "m_enq", 0)
{
}
NETLIB_RESETI();
NETLIB_UPDATEI();
- NETLIB_HANDLERI(addr)
- {
- uint8_t adr = 0;
- for (std::size_t i=0; i<8; i++)
- {
- //m_A[i].activate();
- adr |= (m_A[i]() << i);
- }
- m_addr = adr;
- NETLIB_NAME(82S16)::update();
- }
- NETLIB_HANDLERI(enq)
- {
- const auto last = m_enq;
- m_enq = m_CE1Q() || m_CE2Q() || m_CE3Q();
- if (!last && m_enq)
- {
- // FIXME: Outputs are tristate. This needs to be properly implemented
- m_DOUTQ.push(1, NLTIME_FROM_NS(20));
- for (std::size_t i=0; i<8; i++)
- m_A[i].inactivate();
- m_WEQ.inactivate();
- m_DIN.inactivate();
- }
- else if (last && !m_enq)
- {
- for (std::size_t i=0; i<8; i++)
- m_A[i].activate();
- m_WEQ.activate();
- m_DIN.activate();
- NETLIB_NAME(82S16)::update();
- }
- }
-
protected:
object_array_t<logic_input_t, 8> m_A;
@@ -74,9 +38,7 @@ namespace netlist
logic_input_t m_DIN;
logic_output_t m_DOUTQ;
- state_array<uint64_t, 4> m_ram; // 256 bits
- state_var_u8 m_addr; // 256 bits
- state_var_sig m_enq;
+ state_var<uint64_t[4]> m_ram; // 256 bits
};
NETLIB_OBJECT_DERIVED(82S16_dip, 82S16)
@@ -107,9 +69,22 @@ namespace netlist
// FIXME: optimize device (separate address decoder!)
NETLIB_UPDATE(82S16)
{
- if (!m_enq)
+ if (m_CE1Q() || m_CE2Q() || m_CE3Q())
{
- const auto adr(m_addr);
+ // FIXME: Outputs are tristate. This needs to be properly implemented
+ m_DOUTQ.push(1, NLTIME_FROM_NS(20));
+ //for (int i=0; i<8; i++)
+ //m_A[i].inactivate();
+ }
+ else
+ {
+ unsigned int adr = 0;
+ for (std::size_t i=0; i<8; i++)
+ {
+ //m_A[i].activate();
+ adr |= (m_A[i]() << i);
+ }
+
if (!m_WEQ())
{
m_ram[adr >> 6] = (m_ram[adr >> 6]
@@ -126,12 +101,10 @@ namespace netlist
{
m_ram[i] = 0;
}
- m_addr = 0;
- m_enq = 0;
}
- NETLIB_DEVICE_IMPL(82S16, "TTL_82S16", "")
- NETLIB_DEVICE_IMPL(82S16_dip, "TTL_82S16_DIP", "")
+ NETLIB_DEVICE_IMPL(82S16)
+ NETLIB_DEVICE_IMPL(82S16_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S16.h b/src/lib/netlist/devices/nld_82S16.h
index 47d6189a79b..d1117246d87 100644
--- a/src/lib/netlist/devices/nld_82S16.h
+++ b/src/lib/netlist/devices/nld_82S16.h
@@ -24,7 +24,7 @@
#ifndef NLD_82S16_H_
#define NLD_82S16_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_82S16(name) \
NET_REGISTER_DEV(TTL_82S16, name)
diff --git a/src/lib/netlist/devices/nld_9310.cpp b/src/lib/netlist/devices/nld_9310.cpp
index b416015df24..ad752adb605 100644
--- a/src/lib/netlist/devices/nld_9310.cpp
+++ b/src/lib/netlist/devices/nld_9310.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_9310.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
#define MAXCNT 9
@@ -14,7 +14,6 @@ namespace netlist
{
namespace devices
{
- //FIXME: Convert sub devices into NETDEV_DELEGATE logic
NETLIB_OBJECT(9310_subABCD)
{
NETLIB_CONSTRUCTOR(9310_subABCD)
@@ -140,8 +139,8 @@ namespace netlist
NETLIB_RESET(9310)
{
- sub.reset();
- subABCD.reset();
+ sub.do_reset();
+ subABCD.do_reset();
}
NETLIB_RESET(9310_subABCD)
@@ -158,35 +157,32 @@ namespace netlist
NETLIB_UPDATE(9310_sub)
{
- auto cnt(m_cnt);
-
if (m_loadq)
{
- if (cnt < MAXCNT - 1)
+ if (m_cnt < MAXCNT - 1)
{
- ++cnt;
- update_outputs(cnt);
+ ++m_cnt;
+ update_outputs(m_cnt);
}
- else if (cnt == MAXCNT - 1)
+ else if (m_cnt == MAXCNT - 1)
{
- cnt = MAXCNT;
+ m_cnt = MAXCNT;
m_RC.push(m_ent, NLTIME_FROM_NS(20));
m_QA.push(1, NLTIME_FROM_NS(20));
}
else // MAXCNT
{
m_RC.push(0, NLTIME_FROM_NS(20));
- cnt = 0;
- update_outputs_all(cnt, NLTIME_FROM_NS(20));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
{
- cnt = m_ABCD->read_ABCD();
- m_RC.push(m_ent & (cnt == MAXCNT), NLTIME_FROM_NS(27));
- update_outputs_all(cnt, NLTIME_FROM_NS(22));
+ m_cnt = m_ABCD->read_ABCD();
+ m_RC.push(m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(22));
}
- m_cnt = cnt;
}
NETLIB_UPDATE(9310)
@@ -227,10 +223,10 @@ namespace netlist
#if 0
// for (int i=0; i<4; i++)
// m_Q[i], (cnt >> i) & 1, delay[i]);
- m_QA.push((cnt >> 0) & 1, out_delay);
- m_QB.push((cnt >> 1) & 1, out_delay);
- m_QC.push((cnt >> 2) & 1, out_delay);
- m_QD.push((cnt >> 3) & 1, out_delay);
+ m_QA, (cnt >> 0) & 1, out_delay);
+ m_QB, (cnt >> 1) & 1, out_delay);
+ m_QC, (cnt >> 2) & 1, out_delay);
+ m_QD, (cnt >> 3) & 1, out_delay);
#else
if ((cnt & 1) == 1)
m_QA.push(1, out_delay);
@@ -266,8 +262,8 @@ namespace netlist
#endif
}
- NETLIB_DEVICE_IMPL(9310, "TTL_9310", "")
- NETLIB_DEVICE_IMPL(9310_dip, "TTL_9310_DIP", "")
+ NETLIB_DEVICE_IMPL(9310)
+ NETLIB_DEVICE_IMPL(9310_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_9310.h b/src/lib/netlist/devices/nld_9310.h
index 65df9c04ce4..02cb45b2d86 100644
--- a/src/lib/netlist/devices/nld_9310.h
+++ b/src/lib/netlist/devices/nld_9310.h
@@ -45,7 +45,7 @@
#ifndef NLD_9310_H_
#define NLD_9310_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_9310(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \
NET_REGISTER_DEV(TTL_9310, name) \
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index 2b17eabb3ec..7c478fd4b05 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_9316.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -20,73 +20,32 @@ namespace netlist
NETLIB_CONSTRUCTOR(9316)
, m_CLK(*this, "CLK", NETLIB_DELEGATE(9316, clk))
, m_ENT(*this, "ENT")
- , m_RC(*this, "RC")
, m_LOADQ(*this, "LOADQ")
+ , m_cnt(*this, "m_cnt", 0)
, m_ENP(*this, "ENP")
, m_CLRQ(*this, "CLRQ")
- , m_A(*this, "A", NETLIB_DELEGATE(9316, abcd))
- , m_B(*this, "B", NETLIB_DELEGATE(9316, abcd))
- , m_C(*this, "C", NETLIB_DELEGATE(9316, abcd))
- , m_D(*this, "D", NETLIB_DELEGATE(9316, abcd))
+ , m_A(*this, "A", NETLIB_DELEGATE(9316, noop))
+ , m_B(*this, "B", NETLIB_DELEGATE(9316, noop))
+ , m_C(*this, "C", NETLIB_DELEGATE(9316, noop))
+ , m_D(*this, "D", NETLIB_DELEGATE(9316, noop))
, m_Q(*this, {{ "QA", "QB", "QC", "QD" }})
- , m_cnt(*this, "m_cnt", 0)
- , m_abcd(*this, "m_abcd", 0)
- , m_loadq(*this, "m_loadq", 0)
- , m_ent(*this, "m_ent", 0)
+ , m_RC(*this, "RC")
{
}
private:
- NETLIB_RESETI()
- {
- m_CLK.set_state(logic_t::STATE_INP_LH);
- m_cnt = 0;
- m_abcd = 0;
- }
-
- NETLIB_UPDATEI()
- {
- const auto CLRQ(m_CLRQ());
- m_ent = m_ENT();
- m_loadq = m_LOADQ();
-
- if (((m_loadq ^ 1) || (m_ent && m_ENP())) && CLRQ)
- {
- m_CLK.activate_lh();
- }
- else
- {
- m_CLK.inactivate();
- if (!CLRQ && (m_cnt>0))
- {
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(36));
- }
- }
- m_RC.push(m_ent && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
- }
-
-
- NETLIB_HANDLERI(clk)
- {
- auto cnt = (m_loadq ? m_cnt + 1 : m_abcd) & MAXCNT;
- m_RC.push(m_ent && (cnt == MAXCNT), NLTIME_FROM_NS(27));
- update_outputs_all(cnt, NLTIME_FROM_NS(20));
- m_cnt = cnt;
- }
-
- NETLIB_HANDLERI(abcd)
- {
- m_abcd = static_cast<uint8_t>((m_D() << 3) | (m_C() << 2) | (m_B() << 1) | (m_A() << 0));
- }
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_HANDLERI(clk);
+ NETLIB_HANDLERI(noop) { }
logic_input_t m_CLK;
- logic_input_t m_ENT;
-
- logic_output_t m_RC;
+ logic_input_t m_ENT;
logic_input_t m_LOADQ;
+ state_var<unsigned> m_cnt;
+
logic_input_t m_ENP;
logic_input_t m_CLRQ;
@@ -96,15 +55,12 @@ namespace netlist
logic_input_t m_D;
object_array_t<logic_output_t, 4> m_Q;
+ logic_output_t m_RC;
- /* counter state */
- state_var<unsigned> m_cnt;
- /* cached pins */
- state_var_u8 m_abcd;
- state_var_sig m_loadq;
- state_var_sig m_ent;
- void update_outputs_all(unsigned cnt, netlist_time out_delay) noexcept
+ private:
+ //inline void update_outputs_all(const unsigned &cnt, const netlist_time &out_delay) noexcept
+ inline void update_outputs_all(const unsigned &cnt, const netlist_time &out_delay) noexcept
{
m_Q[0].push((cnt >> 0) & 1, out_delay);
m_Q[1].push((cnt >> 1) & 1, out_delay);
@@ -137,9 +93,63 @@ namespace netlist
}
};
+ NETLIB_RESET(9316)
+ {
+ m_CLK.set_state(logic_t::STATE_INP_LH);
+ m_cnt = 0;
+ }
+
+ NETLIB_HANDLER(9316, clk)
+ {
+ if (m_LOADQ())
+ {
+ ++m_cnt &= MAXCNT;
+ //m_RC.push(m_ENT() && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ if (m_cnt == MAXCNT)
+ {
+ m_RC.push(m_ENT(), NLTIME_FROM_NS(27));
+ update_outputs_all(MAXCNT, NLTIME_FROM_NS(20));
+ }
+ else if (m_cnt == 0)
+ {
+ m_RC.push(0, NLTIME_FROM_NS(27));
+ update_outputs_all(0, NLTIME_FROM_NS(20));
+ }
+ else
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
+ }
+ else
+ {
+ m_cnt = (m_D() << 3) | (m_C() << 2) | (m_B() << 1) | (m_A() << 0);
+ m_RC.push(m_ENT() && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(22));
+ }
+ }
+
+ NETLIB_UPDATE(9316)
+ {
+ const netlist_sig_t CLRQ(m_CLRQ());
+ const netlist_sig_t ENT(m_ENT());
+
+ if (((m_LOADQ() ^ 1) || (ENT && m_ENP())) && CLRQ)
+ {
+ m_CLK.activate_lh();
+ }
+ else
+ {
+ m_CLK.inactivate();
+ if (!CLRQ && (m_cnt>0))
+ {
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(36));
+ }
+ }
+ m_RC.push(ENT && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ }
+
- NETLIB_DEVICE_IMPL(9316, "TTL_9316", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D")
- NETLIB_DEVICE_IMPL(9316_dip, "TTL_9316_DIP", "")
+ NETLIB_DEVICE_IMPL(9316)
+ NETLIB_DEVICE_IMPL(9316_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_9316.h b/src/lib/netlist/devices/nld_9316.h
index 8ab1789d7c7..8deb21dfccd 100644
--- a/src/lib/netlist/devices/nld_9316.h
+++ b/src/lib/netlist/devices/nld_9316.h
@@ -51,7 +51,7 @@
#ifndef NLD_9316_H_
#define NLD_9316_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_9316(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \
NET_REGISTER_DEV(TTL_9316, name) \
diff --git a/src/lib/netlist/devices/nld_9322.cpp b/src/lib/netlist/devices/nld_9322.cpp
index abf9bf9f6ef..6c408498be7 100644
--- a/src/lib/netlist/devices/nld_9322.cpp
+++ b/src/lib/netlist/devices/nld_9322.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_9322.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -105,14 +105,14 @@ namespace netlist
NETLIB_UPDATE(9322)
{
- m_1.update();
- m_2.update();
- m_3.update();
- m_4.update();
+ m_1.update_dev();
+ m_2.update_dev();
+ m_3.update_dev();
+ m_4.update_dev();
}
- NETLIB_DEVICE_IMPL(9322, "TTL_9322", "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE")
- NETLIB_DEVICE_IMPL(9322_dip, "TTL_9322_DIP", "")
+ NETLIB_DEVICE_IMPL(9322)
+ NETLIB_DEVICE_IMPL(9322_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_9322.h b/src/lib/netlist/devices/nld_9322.h
index 986c6b9e7f7..7de0f053b05 100644
--- a/src/lib/netlist/devices/nld_9322.h
+++ b/src/lib/netlist/devices/nld_9322.h
@@ -21,7 +21,7 @@
#ifndef NLD_9322_H_
#define NLD_9322_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_9322(name, cSELECT, cA1, cB1, cA2, cB2, cA3, cB3, cA4, cB4, cSTROBE) \
NET_REGISTER_DEV(TTL_9322, name) \
diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp
index 825696f0938..5d0c5cb71a3 100644
--- a/src/lib/netlist/devices/nld_am2847.cpp
+++ b/src/lib/netlist/devices/nld_am2847.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_am2847.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -30,7 +30,7 @@ namespace netlist
logic_input_t m_RC;
logic_input_t m_IN;
- state_array<uint16_t, 5> m_buffer;
+ state_var<uint16_t[5]> m_buffer;
logic_output_t m_OUT;
};
@@ -116,7 +116,7 @@ namespace netlist
/* do nothing */
}
- NETLIB_FUNC_VOID(Am2847_shifter, shift, ())
+ inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
{
uint32_t out = m_buffer[0] & 1;
uint32_t in = (m_RC() ? out : m_IN());
@@ -130,8 +130,8 @@ namespace netlist
m_OUT.push(out, NLTIME_FROM_NS(200));
}
- NETLIB_DEVICE_IMPL(AM2847, "TTL_AM2847", "+CP,+INA,+INB,+INC,+IND,+RCA,+RCB,+RCC,+RCD")
- NETLIB_DEVICE_IMPL(AM2847_dip, "TTL_AM2847_DIP", "")
+ NETLIB_DEVICE_IMPL(AM2847)
+ NETLIB_DEVICE_IMPL(AM2847_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_am2847.h b/src/lib/netlist/devices/nld_am2847.h
index ff4a95b8e81..70d288d3eec 100644
--- a/src/lib/netlist/devices/nld_am2847.h
+++ b/src/lib/netlist/devices/nld_am2847.h
@@ -21,7 +21,7 @@
#ifndef NLD_AM2847_H_
#define NLD_AM2847_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_AM2847(name, cCP, cINA, cINB, cINC, cIND, cRCA, cRCB, cRCC, cRCD) \
NET_REGISTER_DEV(TTL_AM2847, name) \
diff --git a/src/lib/netlist/devices/nld_dm9314.cpp b/src/lib/netlist/devices/nld_dm9314.cpp
index 93b958de539..fd3b8666078 100644
--- a/src/lib/netlist/devices/nld_dm9314.cpp
+++ b/src/lib/netlist/devices/nld_dm9314.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_dm9314.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -107,8 +107,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(9314, "TTL_9314", "+EQ,+MRQ,+S0Q,+S1Q,+S2Q,+S3Q,+D0,+D1,+D2,+D3")
- NETLIB_DEVICE_IMPL(9314_dip, "TTL_9314_DIP", "")
+ NETLIB_DEVICE_IMPL(9314)
+ NETLIB_DEVICE_IMPL(9314_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_dm9314.h b/src/lib/netlist/devices/nld_dm9314.h
index 59c60591ce7..6188bbef42f 100644
--- a/src/lib/netlist/devices/nld_dm9314.h
+++ b/src/lib/netlist/devices/nld_dm9314.h
@@ -21,7 +21,7 @@
#ifndef NLD_DM9314_H_
#define NLD_DM9314_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_9314(name, cEQ, cMRQ, cS0Q, cS1Q, cS2Q, cS3Q, cD0, cD1, cD2, cD3) \
NET_REGISTER_DEV(TTL_9314, name) \
diff --git a/src/lib/netlist/devices/nld_dm9334.cpp b/src/lib/netlist/devices/nld_dm9334.cpp
index c08ce53efed..8dceded5390 100644
--- a/src/lib/netlist/devices/nld_dm9334.cpp
+++ b/src/lib/netlist/devices/nld_dm9334.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_dm9334.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -143,8 +143,8 @@ namespace netlist
m_Q[i].push((q >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(9334, "TTL_9334", "+CQ,+EQ,+D,+A0,+A1,+A2")
- NETLIB_DEVICE_IMPL(9334_dip, "TTL_9334_DIP", "")
+ NETLIB_DEVICE_IMPL(9334)
+ NETLIB_DEVICE_IMPL(9334_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_dm9334.h b/src/lib/netlist/devices/nld_dm9334.h
index e54208e3ba4..1a07e051333 100644
--- a/src/lib/netlist/devices/nld_dm9334.h
+++ b/src/lib/netlist/devices/nld_dm9334.h
@@ -65,7 +65,7 @@
#ifndef NLD_DM9334_H_
#define NLD_DM9334_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_9334(name, cCQ, cEQ, cD, cA0, cA1, cA2) \
NET_REGISTER_DEV(TTL_9334, name) \
diff --git a/src/lib/netlist/devices/nld_legacy.cpp b/src/lib/netlist/devices/nld_legacy.cpp
index 738230646e0..28fe0ad8188 100644
--- a/src/lib/netlist/devices/nld_legacy.cpp
+++ b/src/lib/netlist/devices/nld_legacy.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_legacy.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -25,7 +25,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- private:
+ protected:
logic_input_t m_S;
logic_input_t m_R;
@@ -49,7 +49,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- private:
+ protected:
logic_input_t m_I;
logic_output_t m_Q;
@@ -100,8 +100,8 @@ namespace netlist
m_last = nval;
}
- NETLIB_DEVICE_IMPL(nicRSFF, "NETDEV_RSFF", "")
- NETLIB_DEVICE_IMPL(nicDelay, "NETDEV_DELAY", "")
+ NETLIB_DEVICE_IMPL(nicRSFF)
+ NETLIB_DEVICE_IMPL(nicDelay)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_legacy.h b/src/lib/netlist/devices/nld_legacy.h
index aa3aec6f147..33f7d0caaf8 100644
--- a/src/lib/netlist/devices/nld_legacy.h
+++ b/src/lib/netlist/devices/nld_legacy.h
@@ -13,7 +13,7 @@
#ifndef NLD_LEGACY_H_
#define NLD_LEGACY_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp
index 6b1b3d8efc1..29218aaa09a 100644
--- a/src/lib/netlist/devices/nld_log.cpp
+++ b/src/lib/netlist/devices/nld_log.cpp
@@ -5,10 +5,10 @@
*
*/
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
+#include "../plib/pstream.h"
+#include "../plib/pfmtlog.h"
#include "nld_log.h"
-#include "plib/pfmtlog.h"
-#include "plib/pstream.h"
//#include "sound/wavwrite.h"
namespace netlist
@@ -19,15 +19,15 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(log)
, m_I(*this, "I")
- , m_strm(pstring(plib::pfmt("{1}.log")(this->name())))
- , m_writer(&m_strm)
+ , m_strm(plib::pfmt("{1}.log")(this->name()))
+ , m_writer(m_strm)
{
}
NETLIB_UPDATEI()
{
/* use pstring::sprintf, it is a LOT faster */
- m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_double()).e(static_cast<double>(m_I())));
+ m_writer.writeline(plib::pfmt("{1:.9} {2}").e(netlist().time().as_double()).e(static_cast<double>(m_I())));
}
NETLIB_RESETI() { }
@@ -46,7 +46,7 @@ namespace netlist
NETLIB_UPDATEI()
{
- m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_double()).e(static_cast<double>(m_I() - m_I2())));
+ m_writer.writeline(plib::pfmt("{1:.9} {2}").e(netlist().time().as_double()).e(static_cast<double>(m_I() - m_I2())));
}
NETLIB_RESETI() { }
@@ -89,8 +89,8 @@ namespace netlist
#endif
- NETLIB_DEVICE_IMPL(log, "LOG", "+I")
- NETLIB_DEVICE_IMPL(logD, "LOGD", "+I,+I2")
+ NETLIB_DEVICE_IMPL(log)
+ NETLIB_DEVICE_IMPL(logD)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_log.h b/src/lib/netlist/devices/nld_log.h
index 13c71ea7257..6364022cea2 100644
--- a/src/lib/netlist/devices/nld_log.h
+++ b/src/lib/netlist/devices/nld_log.h
@@ -18,10 +18,10 @@
#ifndef NLD_LOG_H_
#define NLD_LOG_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define LOG(name, cI) \
- NET_REGISTER_DEV(LOG, name) \
+ NET_REGISTER_DEV(??PG, name) \
NET_CONNECT(name, I, cI)
#define LOGD(name, cI, cI2) \
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index f6c2566bd43..e97ae41e437 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -6,8 +6,8 @@
*/
#include "nld_mm5837.h"
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/solver/nld_matrix_solver.h"
+#include "../solver/nld_matrix_solver.h"
+#include "../analog/nlid_twoterm.h"
#define R_LOW (1000.0)
#define R_HIGH (1000.0)
@@ -69,13 +69,13 @@ namespace netlist
{
//m_V0.initial(0.0);
//m_RV.do_reset();
- m_RV.set_G_V_I(plib::constants<nl_double>::one() / R_LOW, 0.0, 0.0);
+ m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
m_inc = netlist_time::from_double(1.0 / m_FREQ());
if (m_FREQ() < 24000 || m_FREQ() > 56000)
log().warning(MW_1_FREQUENCY_OUTSIDE_OF_SPECS_1, m_FREQ());
m_shift = 0x1ffff;
- m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
+ m_is_timestep = m_RV.m_P.net().solver()->is_timestep();
}
NETLIB_UPDATE_PARAM(MM5837_dip)
@@ -107,14 +107,14 @@ namespace netlist
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
- m_RV.update();
- m_RV.set_G_V_I(plib::constants<nl_double>::one() / R, V, plib::constants<nl_double>::zero());
- m_RV.solve_later(NLTIME_FROM_NS(1));
+ m_RV.update_dev();
+ m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
+ m_RV.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
}
}
- NETLIB_DEVICE_IMPL(MM5837_dip, "MM5837_DIP", "")
+ NETLIB_DEVICE_IMPL(MM5837_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_mm5837.h b/src/lib/netlist/devices/nld_mm5837.h
index 8f764aa651f..4af397d9965 100644
--- a/src/lib/netlist/devices/nld_mm5837.h
+++ b/src/lib/netlist/devices/nld_mm5837.h
@@ -19,7 +19,7 @@
#ifndef NLD_MM5837_H_
#define NLD_MM5837_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define MM5837_DIP(name) \
NET_REGISTER_DEV(MM5837_DIP, name)
diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp
index 5e990d2e974..8795197bd57 100644
--- a/src/lib/netlist/devices/nld_ne555.cpp
+++ b/src/lib/netlist/devices/nld_ne555.cpp
@@ -46,8 +46,8 @@
*/
#include "nld_ne555.h"
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/solver/nld_solver.h"
+#include "../analog/nlid_twoterm.h"
+#include "../solver/nld_solver.h"
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
@@ -62,37 +62,31 @@ namespace netlist
, m_R1(*this, "R1")
, m_R2(*this, "R2")
, m_R3(*this, "R3")
- , m_ROUT(*this, "ROUT")
, m_RDIS(*this, "RDIS")
, m_RESET(*this, "RESET") // Pin 4
, m_THRES(*this, "THRESH") // Pin 6
, m_TRIG(*this, "TRIG") // Pin 2
- , m_OUT(*this, "_OUT") // to Pin 3 via ROUT
+ , m_OUT(*this, "OUT") // Pin 3
, m_last_out(*this, "m_last_out", false)
, m_ff(*this, "m_ff", false)
- , m_last_reset(*this, "m_last_reset", false)
{
register_subalias("GND", m_R3.m_N); // Pin 1
register_subalias("CONT", m_R1.m_N); // Pin 5
register_subalias("DISCH", m_RDIS.m_P); // Pin 7
register_subalias("VCC", m_R1.m_P); // Pin 8
- register_subalias("OUT", m_ROUT.m_P); // Pin 3
connect(m_R1.m_N, m_R2.m_P);
- connect(m_R1.m_N, m_R2.m_P);
connect(m_R2.m_N, m_R3.m_P);
connect(m_RDIS.m_N, m_R3.m_N);
- connect(m_OUT, m_ROUT.m_N);
}
NETLIB_UPDATEI();
NETLIB_RESETI();
- private:
+ protected:
analog::NETLIB_SUB(R_base) m_R1;
analog::NETLIB_SUB(R_base) m_R2;
analog::NETLIB_SUB(R_base) m_R3;
- analog::NETLIB_SUB(R_base) m_ROUT;
analog::NETLIB_SUB(R_base) m_RDIS;
logic_input_t m_RESET;
@@ -100,51 +94,52 @@ namespace netlist
analog_input_t m_TRIG;
analog_output_t m_OUT;
+ private:
state_var<bool> m_last_out;
state_var<bool> m_ff;
- state_var<bool> m_last_reset;
- nl_double clamp(const nl_double v, const nl_double a, const nl_double b)
- {
- nl_double ret = v;
- nl_double vcc = m_R1.m_P();
-
- if (ret > vcc - a)
- ret = vcc - a;
- if (ret < b)
- ret = b;
- return ret;
- }
+ inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
+
};
NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
{
NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555)
{
- register_subalias("1", "GND"); // Pin 1
- register_subalias("2", "TRIG"); // Pin 2
- register_subalias("3", "OUT"); // Pin 3
- register_subalias("4", "RESET"); // Pin 4
- register_subalias("5", "CONT"); // Pin 5
- register_subalias("6", "THRESH"); // Pin 6
- register_subalias("7", "DISCH"); // Pin 7
- register_subalias("8", "VCC"); // Pin 8
+ register_subalias("1", m_R3.m_N); // Pin 1
+ register_subalias("2", m_TRIG); // Pin 2
+ register_subalias("3", m_OUT); // Pin 3
+ register_subalias("4", m_RESET); // Pin 4
+ register_subalias("5", m_R1.m_N); // Pin 5
+ register_subalias("6", m_THRES); // Pin 6
+ register_subalias("7", m_RDIS.m_P); // Pin 7
+ register_subalias("8", m_R1.m_P); // Pin 8
}
};
+ inline nl_double NETLIB_NAME(NE555)::clamp(const nl_double v, const nl_double a, const nl_double b)
+ {
+ nl_double ret = v;
+ nl_double vcc = m_R1.m_P();
+
+ if (ret > vcc - a)
+ ret = vcc - a;
+ if (ret < b)
+ ret = b;
+ return ret;
+ }
+
NETLIB_RESET(NE555)
{
- m_R1.reset();
- m_R2.reset();
- m_R3.reset();
- m_ROUT.reset();
- m_RDIS.reset();
+ m_R1.do_reset();
+ m_R2.do_reset();
+ m_R3.do_reset();
+ m_RDIS.do_reset();
- /* FIXME make resistances a parameter, properly model other variants */
+ /* FIXME make resistance a parameter, properly model other variants */
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
- m_ROUT.set_R(20);
m_RDIS.set_R(R_OFF);
m_last_out = true;
@@ -154,47 +149,39 @@ namespace netlist
{
// FIXME: assumes GND is connected to 0V.
- const auto reset = m_RESET();
+ nl_double vt = clamp(m_R2.m_P(), 0.7, 1.4);
+ bool bthresh = (m_THRES() > vt);
+ bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4));
- if (!reset && m_last_reset)
+ if (!btrig)
{
- m_ff = false;
+ m_ff = true;
}
- else
+ else if (bthresh)
{
- const nl_double vt = clamp(m_R2.m_P(), 0.7, 1.4);
- const bool bthresh = (m_THRES() > vt);
- const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4));
-
- if (!btrig)
- m_ff = true;
- else if (bthresh)
- m_ff = false;
+ m_ff = false;
}
- const bool out = (!reset ? false : m_ff);
+ bool out = (!m_RESET() ? false : m_ff);
if (m_last_out && !out)
{
- m_RDIS.update();
+ m_RDIS.update_dev();
m_OUT.push(m_R3.m_N());
m_RDIS.set_R(R_ON);
}
else if (!m_last_out && out)
{
- m_RDIS.update();
+ m_RDIS.update_dev();
// FIXME: Should be delayed by 100ns
m_OUT.push(m_R1.m_P());
m_RDIS.set_R(R_OFF);
}
- m_last_reset = reset;
m_last_out = out;
}
- NETLIB_DEVICE_IMPL(NE555, "NE555", "")
- NETLIB_DEVICE_IMPL(NE555_dip, "NE555_DIP", "")
+ NETLIB_DEVICE_IMPL(NE555)
+ NETLIB_DEVICE_IMPL(NE555_dip)
- NETLIB_DEVICE_IMPL_ALIAS(MC1455P, NE555, "MC1455P", "")
- NETLIB_DEVICE_IMPL_ALIAS(MC1455P_dip, NE555_dip, "MC1455P_DIP", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_ne555.h b/src/lib/netlist/devices/nld_ne555.h
index fc575d914b7..c629253f08f 100644
--- a/src/lib/netlist/devices/nld_ne555.h
+++ b/src/lib/netlist/devices/nld_ne555.h
@@ -4,7 +4,7 @@
#ifndef NLD_NE555_H_
#define NLD_NE555_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define NE555(name) \
NET_REGISTER_DEV(NE555, name)
@@ -12,10 +12,4 @@
#define NE555_DIP(name) \
NET_REGISTER_DEV(NE555_DIP, name)
-#define MC1455P(name) \
- NET_REGISTER_DEV(MC1455P, name)
-
-#define MC1455P_DIP(name) \
- NET_REGISTER_DEV(MC1455P_DIP, name)
-
#endif /* NLD_NE555_H_ */
diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp
index 284b6673f76..4c29389d491 100644
--- a/src/lib/netlist/devices/nld_r2r_dac.cpp
+++ b/src/lib/netlist/devices/nld_r2r_dac.cpp
@@ -5,9 +5,9 @@
*
*/
-#include "netlist/nl_base.h"
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/nl_factory.h"
+#include "../nl_base.h"
+#include "../nl_factory.h"
+#include "../analog/nlid_twoterm.h"
namespace netlist
{
@@ -39,17 +39,17 @@ namespace netlist
NETLIB_UPDATE_PARAM(r2r_dac)
{
- solve_now();
+ update_dev();
double V = m_VIN() / static_cast<double>(1 << m_num())
* static_cast<double>(m_val());
- this->set_G_V_I(1.0 / m_R(), V, 0.0);
+ this->set(1.0 / m_R(), V, 0.0);
}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, r2r_dac, "R2R_DAC", "VIN,R,N")
- } // namespace devices
+ NETLIB_DEVICE_IMPL_NS(analog, r2r_dac)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_r2r_dac.h b/src/lib/netlist/devices/nld_r2r_dac.h
index 8a4257a3cbf..18e5bddc053 100644
--- a/src/lib/netlist/devices/nld_r2r_dac.h
+++ b/src/lib/netlist/devices/nld_r2r_dac.h
@@ -46,7 +46,7 @@
#ifndef NLD_R2R_DAC_H_
#define NLD_R2R_DAC_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define R2R_DAC(name, p_VIN, p_R, p_N) \
NET_REGISTER_DEV(R2R_DAC, name) \
diff --git a/src/lib/netlist/devices/nld_schmitt.cpp b/src/lib/netlist/devices/nld_schmitt.cpp
index f219d215520..4bc41075f89 100644
--- a/src/lib/netlist/devices/nld_schmitt.cpp
+++ b/src/lib/netlist/devices/nld_schmitt.cpp
@@ -7,10 +7,10 @@
#include "nld_schmitt.h"
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/nl_base.h"
-#include "netlist/nl_errstr.h"
-#include "netlist/solver/nld_solver.h"
+#include "../nl_base.h"
+#include "../nl_errstr.h"
+#include "../analog/nlid_twoterm.h"
+#include "../solver/nld_solver.h"
#include <cmath>
@@ -82,11 +82,11 @@ namespace netlist
NETLIB_RESETI()
{
m_last_state = 1;
- m_RVI.reset();
- m_RVO.reset();
+ m_RVI.do_reset();
+ m_RVO.do_reset();
m_is_timestep = m_RVO.m_P.net().solver()->has_timestep_devices();
- m_RVI.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_RI, m_model.m_VI, 0.0);
- m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROL, m_model.m_VOL, 0.0);
+ m_RVI.set(NL_FCONST(1.0) / m_model.m_RI, m_model.m_VI, 0.0);
+ m_RVO.set(NL_FCONST(1.0) / m_model.m_ROL, m_model.m_VOL, 0.0);
}
NETLIB_UPDATEI()
@@ -97,9 +97,9 @@ namespace netlist
{
m_last_state = 0;
if (m_is_timestep)
- m_RVO.update();
- m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROH, m_model.m_VOH, 0.0);
- m_RVO.solve_later();
+ m_RVO.update_dev();
+ m_RVO.set(NL_FCONST(1.0) / m_model.m_ROH, m_model.m_VOH, 0.0);
+ m_RVO.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
}
}
else
@@ -108,9 +108,9 @@ namespace netlist
{
m_last_state = 1;
if (m_is_timestep)
- m_RVO.update();
- m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROL, m_model.m_VOL, 0.0);
- m_RVO.solve_later();
+ m_RVO.update_dev();
+ m_RVO.set(NL_FCONST(1.0) / m_model.m_ROL, m_model.m_VOL, 0.0);
+ m_RVO.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
}
}
}
@@ -125,7 +125,7 @@ namespace netlist
bool m_is_timestep;
};
- NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "MODEL")
+ NETLIB_DEVICE_IMPL(schmitt_trigger)
} // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_schmitt.h b/src/lib/netlist/devices/nld_schmitt.h
index 20666b29cf7..ecce59be616 100644
--- a/src/lib/netlist/devices/nld_schmitt.h
+++ b/src/lib/netlist/devices/nld_schmitt.h
@@ -11,7 +11,7 @@
#define NLD_SCHMITT_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index 03aa5c678f1..eabc4b4fbff 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -5,8 +5,8 @@
*
*/
-#include "netlist/solver/nld_solver.h"
-#include "netlist/solver/nld_matrix_solver.h"
+#include "../solver/nld_solver.h"
+#include "../solver/nld_matrix_solver.h"
#include "nlid_system.h"
namespace netlist
@@ -40,40 +40,54 @@ namespace netlist
{
m_cnt = 0;
m_off = netlist_time::from_double(m_offset());
- m_feedback.m_delegate = NETLIB_DELEGATE(extclock, update);
-
- //m_feedback.m_delegate .set(&NETLIB_NAME(extclock)::update, this);
//m_Q.initial(0);
}
- NETLIB_HANDLER(extclock, clk2)
+ NETLIB_UPDATE(extclock)
{
- m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
+ m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
+ m_off = netlist_time::zero();
if (++m_cnt >= m_size)
m_cnt = 0;
}
- NETLIB_HANDLER(extclock, clk2_pow2)
+ // ----------------------------------------------------------------------------------------
+ // logic_input
+ // ----------------------------------------------------------------------------------------
+
+ NETLIB_RESET(logic_input)
{
- m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
- m_cnt = (++m_cnt) & (m_size-1);
+ m_Q.initial(0);
}
- NETLIB_UPDATE(extclock)
+ NETLIB_UPDATE(logic_input)
{
- m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
- m_off = netlist_time::zero();
- if (++m_cnt >= m_size)
- m_cnt = 0;
+ m_Q.push(m_IN() & 1, netlist_time::from_nsec(1));
+ }
- // continue with optimized clock handlers ....
+ NETLIB_UPDATE_PARAM(logic_input)
+ {
+ }
+
+ // ----------------------------------------------------------------------------------------
+ // analog_input
+ // ----------------------------------------------------------------------------------------
- if ((m_size & (m_size-1)) == 0) // power of 2?
- m_feedback.m_delegate.set(&NETLIB_NAME(extclock)::clk2_pow2, this);
- else
- m_feedback.m_delegate.set(&NETLIB_NAME(extclock)::clk2, this);
+ NETLIB_RESET(analog_input)
+ {
+ m_Q.initial(0.0);
}
+ NETLIB_UPDATE(analog_input)
+ {
+ m_Q.push(m_IN());
+ }
+
+ NETLIB_UPDATE_PARAM(analog_input)
+ {
+ }
+
+
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
@@ -92,10 +106,19 @@ namespace netlist
m_last_state = state;
const nl_double R = state ? m_RON() : m_ROFF();
- // FIXME: We only need to update the net first if this is a time stepping net
- m_R.update();
- m_R.set_R(R);
- m_R.solve_later();
+ // We only need to update the net first if this is a time stepping net
+ if ((0)) // m_R->m_P.net().as_analog().solver()->is_timestep())
+ {
+ m_R.update_dev();
+ m_R.set_R(R);
+ m_R.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ }
+ else
+ {
+ m_R.set_R(R);
+ m_R.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ //m_R->update_dev();
+ }
}
}
@@ -118,19 +141,17 @@ namespace netlist
}
- NETLIB_DEVICE_IMPL(dummy_input, "DUMMY_INPUT", "")
- NETLIB_DEVICE_IMPL(frontier, "FRONTIER_DEV", "+I,+G,+Q")
- NETLIB_DEVICE_IMPL(function, "AFUNC", "N,FUNC")
- NETLIB_DEVICE_IMPL(analog_input, "ANALOG_INPUT", "IN")
- NETLIB_DEVICE_IMPL(clock, "CLOCK", "FREQ")
- NETLIB_DEVICE_IMPL(extclock, "EXTCLOCK", "FREQ,PATTERN")
- NETLIB_DEVICE_IMPL(res_sw, "RES_SWITCH", "+IN,+P1,+P2")
- NETLIB_DEVICE_IMPL(mainclock, "MAINCLOCK", "FREQ")
- NETLIB_DEVICE_IMPL(gnd, "GND", "")
- NETLIB_DEVICE_IMPL(netlistparams, "PARAMETER", "")
-
- NETLIB_DEVICE_IMPL(logic_input, "LOGIC_INPUT", "IN,FAMILY")
- NETLIB_DEVICE_IMPL_ALIAS(logic_input_ttl, logic_input, "TTL_INPUT", "IN")
+ NETLIB_DEVICE_IMPL(dummy_input)
+ NETLIB_DEVICE_IMPL(frontier)
+ NETLIB_DEVICE_IMPL(function)
+ NETLIB_DEVICE_IMPL(logic_input)
+ NETLIB_DEVICE_IMPL(analog_input)
+ NETLIB_DEVICE_IMPL(clock)
+ NETLIB_DEVICE_IMPL(extclock)
+ NETLIB_DEVICE_IMPL(res_sw)
+ NETLIB_DEVICE_IMPL(mainclock)
+ NETLIB_DEVICE_IMPL(gnd)
+ NETLIB_DEVICE_IMPL(netlistparams)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_system.h b/src/lib/netlist/devices/nld_system.h
index 5158e098cfa..69a7c75dbf3 100644
--- a/src/lib/netlist/devices/nld_system.h
+++ b/src/lib/netlist/devices/nld_system.h
@@ -9,7 +9,7 @@
#ifndef NLD_SYSTEM_H_
#define NLD_SYSTEM_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_tms4800.cpp b/src/lib/netlist/devices/nld_tms4800.cpp
index 24729b10e72..29a9bd836ab 100644
--- a/src/lib/netlist/devices/nld_tms4800.cpp
+++ b/src/lib/netlist/devices/nld_tms4800.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_tms4800.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -39,9 +39,9 @@ namespace netlist
param_rom_t<uint8_t, 11, 8> m_ROM; // 16 Kbits, used as 2 Kbit x 8
};
- NETLIB_OBJECT_DERIVED(TMS4800_dip, TMS4800)
+ NETLIB_OBJECT_DERIVED(tms4800_dip, TMS4800)
{
- NETLIB_CONSTRUCTOR_DERIVED(TMS4800_dip, TMS4800)
+ NETLIB_CONSTRUCTOR_DERIVED(tms4800_dip, TMS4800)
{
register_subalias("2", m_A[0]);
register_subalias("3", m_A[1]);
@@ -97,8 +97,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(TMS4800, "ROM_TMS4800", "+AR,+OE1,+OE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
- NETLIB_DEVICE_IMPL(TMS4800_dip, "ROM_TMS4800_DIP", "")
+ NETLIB_DEVICE_IMPL(TMS4800)
+ NETLIB_DEVICE_IMPL(tms4800_dip)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_tms4800.h b/src/lib/netlist/devices/nld_tms4800.h
index c5bcd1337f0..dc72354cb03 100644
--- a/src/lib/netlist/devices/nld_tms4800.h
+++ b/src/lib/netlist/devices/nld_tms4800.h
@@ -28,7 +28,7 @@
#ifndef NLD_TMS4800_H_
#define NLD_TMS4800_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define ROM_TMS4800(name, cAR, cOE1, cOE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cA10) \
NET_REGISTER_DEV(ROM_TMS4800, name) \
diff --git a/src/lib/netlist/devices/nld_tristate.cpp b/src/lib/netlist/devices/nld_tristate.cpp
index b05d09ea71e..74fbb206feb 100644
--- a/src/lib/netlist/devices/nld_tristate.cpp
+++ b/src/lib/netlist/devices/nld_tristate.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_tristate.h"
-#include "netlist/nl_base.h"
+#include "../nl_base.h"
namespace netlist
{
@@ -70,8 +70,8 @@ namespace netlist
m_Q.push(q, NLTIME_FROM_NS(1));
}
- NETLIB_DEVICE_IMPL(tristate, "TTL_TRISTATE", "+CEQ1,+D1,+CEQ2,+D2")
- NETLIB_DEVICE_IMPL(tristate3, "TTL_TRISTATE3", "")
+ NETLIB_DEVICE_IMPL(tristate)
+ NETLIB_DEVICE_IMPL(tristate3)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_tristate.h b/src/lib/netlist/devices/nld_tristate.h
index 71f97d9812d..a5ff22fac96 100644
--- a/src/lib/netlist/devices/nld_tristate.h
+++ b/src/lib/netlist/devices/nld_tristate.h
@@ -10,7 +10,7 @@
#ifndef NLD_TRISTATE_H_
#define NLD_TRISTATE_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#define TTL_TRISTATE(name, cCEQ1, cD1, cCEQ2, cD2) \
NET_REGISTER_DEV(TTL_TRISTATE, name) \
diff --git a/src/lib/netlist/devices/nlid_cmos.h b/src/lib/netlist/devices/nlid_cmos.h
index d91d691453a..f9999aebcc0 100644
--- a/src/lib/netlist/devices/nlid_cmos.h
+++ b/src/lib/netlist/devices/nlid_cmos.h
@@ -8,8 +8,8 @@
#ifndef NLID_CMOS_H_
#define NLID_CMOS_H_
-#include "netlist/nl_base.h"
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
+#include "../nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index a2fd18e85a7..4c3ec6f67aa 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -6,7 +6,7 @@
*/
#include "nlid_proxy.h"
-#include "netlist/solver/nld_solver.h"
+#include "../solver/nld_solver.h"
//#include "plib/pstream.h"
//#include "plib/pfmtlog.h"
//#include "nld_log.h"
@@ -20,7 +20,7 @@ namespace netlist
// nld_base_proxy
// -----------------------------------------------------------------------------
- nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_proxy::nld_base_proxy(netlist_t &anetlist, const pstring &name,
logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
: device_t(anetlist, name)
{
@@ -29,23 +29,33 @@ namespace netlist
m_proxy_term = proxy_inout;
}
+ nld_base_proxy::~nld_base_proxy()
+ {
+ }
+
// ----------------------------------------------------------------------------------------
// nld_a_to_d_proxy
// ----------------------------------------------------------------------------------------
- nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_t &anetlist, const pstring &name,
logic_input_t *in_proxied, detail::core_terminal_t *in_proxy)
: nld_base_proxy(anetlist, name, in_proxied, in_proxy)
, m_Q(*this, "Q")
{
}
- nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *in_proxied)
+ nld_base_a_to_d_proxy::~nld_base_a_to_d_proxy() {}
+
+ nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied)
: nld_base_a_to_d_proxy(anetlist, name, in_proxied, &m_I)
, m_I(*this, "I")
{
}
+ nld_a_to_d_proxy::~nld_a_to_d_proxy()
+ {
+ }
+
NETLIB_RESET(a_to_d_proxy)
{
}
@@ -71,32 +81,39 @@ namespace netlist
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
- nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name,
logic_output_t *out_proxied, detail::core_terminal_t &proxy_out)
: nld_base_proxy(anetlist, name, out_proxied, &proxy_out)
, m_I(*this, "I")
{
}
- nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *out_proxied)
+ nld_base_d_to_a_proxy::~nld_base_d_to_a_proxy()
+ {
+ }
+
+ nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P)
, m_GNDHack(*this, "_Q")
, m_RV(*this, "RV")
, m_last_state(*this, "m_last_var", -1)
, m_is_timestep(false)
{
- const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
+ const pstring power_syms[3][2] ={ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
+ //register_sub(m_RV);
+ //register_term("1", m_RV.m_P);
+ //register_term("2", m_RV.m_N);
register_subalias("Q", m_RV.m_P);
connect(m_RV.m_N, m_GNDHack);
bool f = false;
- for (auto & pwr_sym : power_syms)
+ for (int i = 0; i < 3; i++)
{
pstring devname = out_proxied->device().name();
- auto tp = setup().find_terminal(devname + "." + pwr_sym.first,
+ auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
detail::terminal_type::INPUT, false);
- auto tn = setup().find_terminal(devname + "." + pwr_sym.second,
+ auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
detail::terminal_type::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
@@ -109,6 +126,11 @@ namespace netlist
log().warning(MW_1_NO_POWER_TERMINALS_ON_DEVICE_1, out_proxied->device().name());
else
log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name());
+#if (0)
+ printf("%s %s\n", out_proxied->name().c_str(), out_proxied->device().name().c_str());
+ auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::terminal_type::OUTPUT, false);
+ if (x) printf("==> %s\n", x->name().c_str());
+#endif
}
@@ -120,15 +142,15 @@ namespace netlist
//m_Q.initial(0.0);
m_last_state = -1;
- m_RV.reset();
+ m_RV.do_reset();
m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
- m_RV.set_G_V_I(plib::constants<nl_double>::one() / logic_family()->R_low(),
+ m_RV.set(NL_FCONST(1.0) / logic_family()->R_low(),
logic_family()->low_V(0.0, supply_V), 0.0);
}
NETLIB_UPDATE(d_to_a_proxy)
{
- const auto state = static_cast<int>(m_I());
+ const int state = static_cast<int>(m_I());
if (state != m_last_state)
{
// FIXME: Variable voltage
@@ -141,10 +163,10 @@ namespace netlist
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
{
- m_RV.update();
+ m_RV.update_dev();
}
- m_RV.set_G_V_I(plib::constants<nl_double>::one() / R, V, 0.0);
- m_RV.solve_later();
+ m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
+ m_RV.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
}
}
diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h
index 9543b8db234..821cfa56d9d 100644
--- a/src/lib/netlist/devices/nlid_proxy.h
+++ b/src/lib/netlist/devices/nlid_proxy.h
@@ -11,8 +11,8 @@
#ifndef NLID_PROXY_H_
#define NLID_PROXY_H_
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
+#include "../analog/nlid_twoterm.h"
namespace netlist
{
@@ -26,9 +26,11 @@ namespace netlist
NETLIB_OBJECT(base_proxy)
{
public:
- nld_base_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_proxy(netlist_t &anetlist, const pstring &name,
logic_t *inout_proxied, detail::core_terminal_t *proxy_inout);
+ virtual ~nld_base_proxy();
+
logic_t &term_proxied() const { return *m_term_proxied; }
detail::core_terminal_t &proxy_term() const { return *m_proxy_term; }
@@ -47,11 +49,13 @@ namespace netlist
{
public:
+ virtual ~nld_base_a_to_d_proxy();
+
virtual logic_output_t &out() { return m_Q; }
protected:
- nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_a_to_d_proxy(netlist_t &anetlist, const pstring &name,
logic_input_t *in_proxied, detail::core_terminal_t *in_proxy);
private:
@@ -63,7 +67,9 @@ namespace netlist
NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_a_to_d_proxy)
{
public:
- nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *in_proxied);
+ nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied);
+
+ virtual ~nld_a_to_d_proxy() override;
analog_input_t m_I;
@@ -82,20 +88,24 @@ namespace netlist
NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy)
{
public:
+ virtual ~nld_base_d_to_a_proxy();
virtual logic_input_t &in() { return m_I; }
protected:
- nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name,
+ nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name,
logic_output_t *out_proxied, detail::core_terminal_t &proxy_out);
logic_input_t m_I;
+
+ private:
};
NETLIB_OBJECT_DERIVED(d_to_a_proxy, base_d_to_a_proxy)
{
public:
- nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *out_proxied);
+ nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied);
+ virtual ~nld_d_to_a_proxy() override {}
protected:
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index f1f2af1b31e..326cd3dbf2c 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -11,10 +11,10 @@
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_
-#include "netlist/analog/nlid_twoterm.h"
-#include "netlist/nl_base.h"
-#include "netlist/nl_setup.h"
-#include "plib/putil.h"
+#include "../nl_base.h"
+#include "../nl_setup.h"
+#include "../analog/nlid_twoterm.h"
+#include "../plib/putil.h"
namespace netlist
{
@@ -27,8 +27,7 @@ namespace netlist
NETLIB_OBJECT(netlistparams)
{
NETLIB_CONSTRUCTOR(netlistparams)
- , m_use_deactivate(*this, "USE_DEACTIVATE", false)
- , m_startup_strategy(*this, "STARTUP_STRATEGY", 1)
+ , m_use_deactivate(*this, "USE_DEACTIVATE", 0)
{
}
NETLIB_UPDATEI() { }
@@ -36,7 +35,6 @@ namespace netlist
//NETLIB_UPDATE_PARAMI() { }
public:
param_logic_t m_use_deactivate;
- param_int_t m_startup_strategy;
};
// -----------------------------------------------------------------------------
@@ -54,7 +52,7 @@ namespace netlist
NETLIB_RESETI()
{
- m_Q.net().set_next_scheduled_time(netlist_time::zero());
+ m_Q.net().set_time(netlist_time::zero());
}
NETLIB_UPDATE_PARAMI()
@@ -67,14 +65,16 @@ namespace netlist
logic_net_t &net = m_Q.net();
// this is only called during setup ...
net.toggle_new_Q();
- net.set_next_scheduled_time(exec().time() + m_inc);
+ net.set_time(netlist().time() + m_inc);
}
public:
logic_output_t m_Q;
- netlist_time m_inc;
- private:
+
param_double_t m_freq;
+ netlist_time m_inc;
+
+ inline static void mc_update(logic_net_t &net);
};
// -----------------------------------------------------------------------------
@@ -96,7 +96,7 @@ namespace netlist
//NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
- private:
+ protected:
logic_input_t m_feedback;
logic_output_t m_Q;
@@ -127,35 +127,31 @@ namespace netlist
std::vector<pstring> pat(plib::psplit(m_pattern(),","));
m_off = netlist_time::from_double(m_offset());
- std::array<std::int64_t, 32> pati = { 0 };
-
+ unsigned long pati[32];
+ for (int pI = 0; pI < 32; pI++)
+ {
+ pati[pI] = 0;
+ }
m_size = static_cast<std::uint8_t>(pat.size());
- netlist_time::mult_type total = 0;
+ unsigned long total = 0;
for (unsigned i=0; i<m_size; i++)
{
- // FIXME: use pstonum_ne
- //pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]);
- pati[i] = plib::pstonum<std::int64_t>(pat[i]);
+ pati[i] = static_cast<unsigned long>(pat[i].as_long());
total += pati[i];
}
netlist_time ttotal = netlist_time::zero();
- auto sm1 = static_cast<uint8_t>(m_size - 1);
- for (unsigned i=0; i < sm1; i++)
+ for (unsigned i=0; i<m_size - 1; i++)
{
m_inc[i] = base * pati[i];
ttotal += m_inc[i];
}
- m_inc[sm1] = base * total - ttotal;
+ m_inc[m_size - 1] = base * total - ttotal;
}
}
NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
-
- NETLIB_HANDLERI(clk2);
- NETLIB_HANDLERI(clk2_pow2);
-
- private:
+ protected:
param_double_t m_freq;
param_str_t m_pattern;
@@ -166,7 +162,7 @@ namespace netlist
state_var_u8 m_cnt;
std::uint8_t m_size;
state_var<netlist_time> m_off;
- std::array<netlist_time, 32> m_inc;
+ netlist_time m_inc[32];
};
// -----------------------------------------------------------------------------
@@ -177,19 +173,20 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(logic_input)
, m_Q(*this, "Q")
- , m_IN(*this, "IN", false)
+ , m_IN(*this, "IN", 0)
/* make sure we get the family first */
, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
{
set_logic_family(setup().family_from_model(m_FAMILY()));
- m_Q.set_logic_family(this->logic_family());
}
- NETLIB_UPDATEI() { }
- NETLIB_RESETI() { m_Q.initial(0); }
- NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); }
+ NETLIB_UPDATE_AFTER_PARAM_CHANGE()
- private:
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+
+ protected:
logic_output_t m_Q;
param_logic_t m_IN;
@@ -203,12 +200,12 @@ namespace netlist
, m_IN(*this, "IN", 0.0)
{
}
+ NETLIB_UPDATE_AFTER_PARAM_CHANGE()
- NETLIB_UPDATEI() { }
- NETLIB_RESETI() { m_Q.initial(0.0); }
- NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }
-
- private:
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+ protected:
analog_output_t m_Q;
param_double_t m_IN;
};
@@ -281,8 +278,8 @@ namespace netlist
NETLIB_RESETI()
{
- m_RIN.set_G_V_I(1.0 / m_p_RIN(),0,0);
- m_ROUT.set_G_V_I(1.0 / m_p_ROUT(),0,0);
+ m_RIN.set(1.0 / m_p_RIN(),0,0);
+ m_ROUT.set(1.0 / m_p_ROUT(),0,0);
}
NETLIB_UPDATEI()
@@ -313,13 +310,13 @@ namespace netlist
, m_N(*this, "N", 1)
, m_func(*this, "FUNC", "A0")
, m_Q(*this, "Q")
- , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
+ , m_compiled(this->name() + ".FUNCC", this, this->netlist().state())
{
std::vector<pstring> inps;
for (int i=0; i < m_N(); i++)
{
pstring n = plib::pfmt("A{1}")(i);
- m_I.push_back(pool().make_poolptr<analog_input_t>(*this, n));
+ m_I.push_back(plib::make_unique<analog_input_t>(*this, n));
inps.push_back(n);
m_vals.push_back(0.0);
}
@@ -336,7 +333,7 @@ namespace netlist
param_int_t m_N;
param_str_t m_func;
analog_output_t m_Q;
- std::vector<pool_owned_ptr<analog_input_t>> m_I;
+ std::vector<std::unique_ptr<analog_input_t>> m_I;
std::vector<double> m_vals;
plib::pfunction m_compiled;
@@ -360,17 +357,16 @@ namespace netlist
register_subalias("2", m_R.m_N);
}
- NETLIB_RESETI();
- //NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATEI();
-
analog::NETLIB_SUB(R_base) m_R;
logic_input_t m_I;
param_double_t m_RON;
param_double_t m_ROFF;
- private:
+ NETLIB_RESETI();
+ //NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATEI();
+ private:
state_var<netlist_sig_t> m_last_state;
};
diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp
index 2221d855880..bf7d03fe3d7 100644
--- a/src/lib/netlist/devices/nlid_truthtable.cpp
+++ b/src/lib/netlist/devices/nlid_truthtable.cpp
@@ -6,9 +6,9 @@
*/
#include "nlid_truthtable.h"
-#include "netlist/nl_setup.h"
-#include "plib/palloc.h"
-#include "plib/plists.h"
+#include "../plib/plists.h"
+#include "../nl_setup.h"
+#include "../plib/palloc.h"
#include <bitset>
@@ -24,7 +24,7 @@ namespace netlist
template <typename T>
struct sbitset
{
- using type = T;
+ typedef T type;
sbitset() : m_bs(0) { }
/* explicit */ sbitset(T v) : m_bs(v) { }
@@ -77,8 +77,8 @@ namespace netlist
return ret;
}
- static constexpr const sbitset all_bits() noexcept { return sbitset(~static_cast<T>(0)); }
- static constexpr const sbitset no_bits() noexcept{ return sbitset(static_cast<T>(0)); }
+ static constexpr sbitset all_bits() { return sbitset(~static_cast<T>(0)); }
+ static constexpr sbitset no_bits() { return sbitset(static_cast<T>(0)); }
private:
T m_bs;
};
@@ -122,18 +122,8 @@ namespace netlist
}
}
- uint_least64_t mask() const
- {
- switch (m_size)
- {
- case 8: return static_cast<uint_least8_t>(-1);
- case 16: return static_cast<uint_least16_t>(-1);
- case 32: return static_cast<uint_least32_t>(-1);
- case 64: return static_cast<uint_least64_t>(-1);
- default:
- return 0; //should never happen
- }
- }
+ uint_least64_t mask() const { return static_cast<uint_least64_t>(-1); }
+
private:
void *m_data;
size_t m_size;
@@ -144,7 +134,7 @@ namespace netlist
truthtable_parser(unsigned NO, unsigned NI, bool *initialized,
packed_int outs, uint_least8_t *timing, netlist_time *timing_nt)
: m_NO(NO), m_NI(NI), m_initialized(initialized),
- m_out_state(outs), m_timing(timing), m_timing_nt(timing_nt),
+ m_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
m_num_bits(m_NI),
m_size(1 << (m_num_bits))
{
@@ -161,7 +151,7 @@ namespace netlist
unsigned m_NO;
unsigned m_NI;
bool *m_initialized;
- packed_int m_out_state;
+ packed_int m_outs;
uint_least8_t *m_timing;
netlist_time *m_timing_nt;
@@ -188,27 +178,51 @@ namespace netlist
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");
- std::vector<pstring> outputs(plib::psplit(io[1], ","));
- nl_assert_always(outputs.size() == m_NO, "output count wrong");
+ std::vector<pstring> out(plib::psplit(io[1], ","));
+ nl_assert_always(out.size() == m_NO, "output count wrong");
for (std::size_t i=0; i < m_NI; i++)
{
- inout[i] = plib::trim(inout[i]);
+ inout[i] = inout[i].trim();
m_I.emplace(i, *this, inout[i]);
}
for (std::size_t i=0; i < m_NO; i++)
{
- outputs[i] = plib::trim(outputs[i]);
- m_Q.emplace(i, *this, outputs[i]);
- // Connect output "Q" to input "_Q" if this exists
- // This enables timed state without having explicit state ....
- pstring tmp = "_" + outputs[i];
+ out[i] = out[i].trim();
+ m_Q.emplace(i, *this, out[i]);
+ }
+ // Connect output "Q" to input "_Q" if this exists
+ // This enables timed state without having explicit state ....
+ tt_bitset disabled_ignore = 0;
+ for (std::size_t i=0; i < m_NO; i++)
+ {
+ pstring tmp = "_" + out[i];
const std::size_t idx = plib::container::indexof(inout, tmp);
if (idx != plib::container::npos)
+ {
connect(m_Q[i], m_I[idx]);
+ // disable ignore for theses inputs altogether.
+ // FIXME: This shouldn't be necessary
+ disabled_ignore.set(idx);
+ }
}
m_ign = 0;
+
+#if 0
+ for (size_t i=0; i<m_size; i++)
+ {
+ m_ttp.m_outs[i] &= ~(disabled_ignore << m_NO);
+ }
+#endif
+#if 0
+ printf("%s\n", name().c_str());
+ for (int j=0; j < m_size; j++)
+ printf("%05x %04x %04x %04x\n", j, m_ttp->m_outs[j] & ((1 << m_NO)-1),
+ m_ttp->m_outs[j] >> m_NO, m_ttp->m_timing[j * m_NO + 0]);
+ for (int k=0; m_ttp->m_timing_nt[k] != netlist_time::zero(); k++)
+ printf("%d %f\n", k, m_ttp->m_timing_nt[k].as_double() * 1000000.0);
+#endif
}
// ----------------------------------------------------------------------------------------
@@ -224,20 +238,15 @@ namespace netlist
: netlist_base_factory_truthtable_t(name, classname, def_param, sourcefile)
{ }
- pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override
+ plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
- using tt_type = nld_truthtable_t<m_NI, m_NO>;
+ typedef nld_truthtable_t<m_NI, m_NO> tt_type;
truthtable_parser desc_s(m_NO, m_NI, &m_ttbl.m_initialized,
- packed_int(m_ttbl.m_out_state.data(), sizeof(m_ttbl.m_out_state[0]) * 8),
- m_ttbl.m_timing_index.data(), m_ttbl.m_timing_nt.data());
+ packed_int(m_ttbl.m_outs, sizeof(m_ttbl.m_outs[0]) * 8),
+ m_ttbl.m_timing, m_ttbl.m_timing_nt);
desc_s.parse(m_desc);
-
- /* update truthtable family definitions */
- if (m_family_name != "")
- m_family_desc = anetlist.setup().family_from_model(m_family_name);
-
- return pool().make_poolptr<tt_type>(anetlist, name, m_family_desc, m_ttbl, m_desc);
+ return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, m_ttbl, m_desc);
}
private:
typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
@@ -250,7 +259,7 @@ namespace netlist
for (std::size_t j=0; j<m_NI; j++)
{
// if changing the input directly doesn't change outputs we can ignore
- if (m_out_state[state] == m_out_state[tt_bitset(state).set(j)])
+ if (m_outs[state] == m_outs[tt_bitset(state).set(j)])
ignore.set(j);
}
@@ -276,7 +285,7 @@ namespace netlist
{
tt_bitset b = tign.expand_and(k);
// will any of the inputs ignored change the output if changed?
- if (m_out_state[state] != m_out_state[(state & tign.invert()) | b])
+ if (m_outs[state] != m_outs[(state & tign.invert()) | b])
{
t[j] = true;
break;
@@ -309,21 +318,21 @@ namespace netlist
void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
tt_bitset state, uint_least64_t val, std::vector<uint_least8_t> &timing_index)
{
- pstring elem = plib::trim(list[cur]);
+ pstring elem = list[cur].trim();
uint_least64_t start = 0;
uint_least64_t end = 0;
- if (elem == "0")
+ if (elem.equals("0"))
{
start = 0;
end = 0;
}
- else if (elem == "1")
+ else if (elem.equals("1"))
{
start = 1;
end = 1;
}
- else if (elem == "X")
+ else if (elem.equals("X"))
{
start = 0;
end = 1;
@@ -343,10 +352,10 @@ void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
else
{
// 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")
- .x(nstate.as_uint())(m_out_state[nstate])(val) );
- m_out_state.set(nstate, val);
+ if (m_outs[nstate] != m_outs.mask() && m_outs[nstate] != val)
+ nl_exception(plib::pfmt("Error in truthtable: State {1:04} already set, {2} != {3}\n")
+ .x(nstate.as_uint())(m_outs[nstate])(val) );
+ m_outs.set(nstate, val);
for (std::size_t j=0; j<m_NO; j++)
m_timing[nstate * m_NO + j] = timing_index[j];
}
@@ -366,12 +375,12 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
line++;
for (unsigned j=0; j < m_size; j++)
- m_out_state.set(j, tt_bitset::all_bits());
+ m_outs.set(j, tt_bitset::all_bits());
for (int j=0; j < 16; j++)
m_timing_nt[j] = netlist_time::zero();
- while (!(ttline == ""))
+ while (!ttline.equals(""))
{
std::vector<pstring> io(plib::psplit(ttline,"|"));
// checks
@@ -393,13 +402,12 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
*/
for (unsigned j=0; j<m_NO; j++)
{
- pstring outs = plib::trim(out[j]);
- if (outs == "1")
+ pstring outs = out[j].trim();
+ if (outs.equals("1"))
val.set(j);
else
- nl_assert_always(outs == "0", "Unknown value (not 0 or 1");
- // FIXME: error handling
- netlist_time t = netlist_time::from_nsec(plib::pstonum<std::int64_t>(plib::trim(times[j])));
+ nl_assert_always(outs.equals("0"), "Unknown value (not 0 or 1");
+ netlist_time t = netlist_time::from_nsec(static_cast<unsigned long>(times[j].trim().as_long()));
uint_least8_t k=0;
while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t)
k++;
@@ -442,9 +450,9 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
}
for (size_t i=0; i<m_size; i++)
{
- if (m_out_state[i] == m_out_state.mask())
+ if (m_outs[i] == m_outs.mask())
throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
- m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO));
+ m_outs.set(i, m_outs[i] | (ign[i] << m_NO));;
}
*m_initialized = true;
@@ -452,21 +460,26 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
netlist_base_factory_truthtable_t::netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
const pstring &def_param, const pstring &sourcefile)
-: factory::element_t(name, classname, def_param, sourcefile), m_family_desc(family_TTL())
+: factory::element_t(name, classname, def_param, sourcefile), m_family(family_TTL())
+{
+}
+
+netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
{
}
+
#define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
- ret = plib::make_unique<xtype>(desc.name, desc.classname, desc.def_param, s); } break
+ ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \
ENTRYY(n, 7, s); ENTRYY(n, 8, s)
-plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &desc, const pstring &sourcefile)
+void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
{
- plib::unique_ptr<netlist_base_factory_truthtable_t> ret;
+ netlist_base_factory_truthtable_t *ret;
switch (desc.ni * 100 + desc.no)
{
@@ -487,9 +500,9 @@ plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &d
nl_assert_always(false, msg);
}
ret->m_desc = desc.desc;
- ret->m_family_name = desc.family;
-
- return ret;
+ if (desc.family != "")
+ ret->m_family = setup.family_from_model(desc.family);
+ setup.factory().register_device(std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
}
} //namespace devices
diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h
index 1217d7ee873..311f5ebd8ca 100644
--- a/src/lib/netlist/devices/nlid_truthtable.h
+++ b/src/lib/netlist/devices/nlid_truthtable.h
@@ -10,9 +10,9 @@
#ifndef NLID_TRUTHTABLE_H_
#define NLID_TRUTHTABLE_H_
-#include "netlist/nl_base.h"
-#include "netlist/nl_setup.h"
-#include "plib/putil.h"
+#include "../nl_setup.h"
+#include "../nl_base.h"
+#include "../plib/putil.h"
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT> \
@@ -29,9 +29,17 @@
namespace netlist
{
-namespace devices
-{
+ namespace devices
+ {
+#if 0
+ template<unsigned bits> struct uint_for_size { typedef uint_least32_t type; };
+ template<unsigned bits>
+ struct need_bytes_for_bits
+ {
+ enum { value = 4 };
+ };
+#else
template<unsigned bits>
struct need_bytes_for_bits
{
@@ -44,35 +52,11 @@ namespace devices
};
template<unsigned bits> struct uint_for_size;
- template<> struct uint_for_size<1> { using type = uint_least8_t; };
- template<> struct uint_for_size<2> { using type = uint_least16_t; };
- template<> struct uint_for_size<4> { using type = uint_least32_t; };
- template<> struct uint_for_size<8> { using type = uint_least64_t; };
-
- template<std::size_t NUM, typename R>
- struct aa
- {
- template<typename T>
- R f(T &arr, const R ign)
- {
- R r = aa<NUM-1, R>().f(arr, ign);
- if (ign & (1 << (NUM-1)))
- arr[NUM-1].activate();
- return r | (arr[NUM-1]() << (NUM-1));
- }
- };
-
- template<typename R>
- struct aa<1, R>
- {
- template<typename T>
- R f(T &arr, const R ign)
- {
- if ((ign & 1))
- arr[0].activate();
- return arr[0]();
- }
- };
+ template<> struct uint_for_size<1> { typedef uint_least8_t type; };
+ template<> struct uint_for_size<2> { typedef uint_least16_t type; };
+ template<> struct uint_for_size<4> { typedef uint_least32_t type; };
+ template<> struct uint_for_size<8> { typedef uint_least64_t type; };
+#endif
template<std::size_t m_NI, std::size_t m_NO>
NETLIB_OBJECT(truthtable_t)
@@ -81,23 +65,22 @@ namespace devices
detail::family_setter_t m_fam;
public:
- using type_t = typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type;
+ typedef typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type type_t;
static constexpr const std::size_t m_num_bits = m_NI;
static constexpr const std::size_t m_size = (1 << (m_num_bits));
static constexpr const type_t m_outmask = ((1 << m_NO) - 1);
+ static constexpr const std::size_t m_min_devices_for_deactivate = 2;
struct truthtable_t
{
truthtable_t()
- : m_timing_index{0}
- , m_initialized(false)
+ : m_initialized(false)
{}
-
- std::array<type_t, m_size> m_out_state;
- std::array<uint_least8_t, m_size * m_NO> m_timing_index;
- std::array<netlist_time, 16> m_timing_nt;
bool m_initialized;
+ type_t m_outs[m_size];
+ uint_least8_t m_timing[m_size * m_NO];
+ netlist_time m_timing_nt[16];
};
template <class C>
@@ -107,6 +90,7 @@ namespace devices
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
+ , m_active(*this, "m_active", 1)
, m_ttp(ttp)
{
init(desc);
@@ -116,14 +100,13 @@ namespace devices
NETLIB_RESETI()
{
- int active_outputs = 0;
+ m_active = 0;
m_ign = 0;
for (auto &i : m_I)
i.activate();
for (auto &q : m_Q)
if (q.has_net() && q.net().num_cons() > 0)
- active_outputs++;
- set_active_outputs(active_outputs);
+ m_active++;
}
NETLIB_UPDATEI()
@@ -133,14 +116,28 @@ namespace devices
void inc_active() NL_NOEXCEPT override
{
- process<false>();
+ if (m_NI >= m_min_devices_for_deactivate)
+ if (++m_active == 1)
+ {
+ process<false>();
+ }
}
void dec_active() NL_NOEXCEPT override
{
- for (std::size_t i = 0; i< m_NI; i++)
- m_I[i].inactivate();
- m_ign = (1<<m_NI)-1;
+ /* FIXME:
+ * Based on current measurements there is no point to disable
+ * 1 input devices. This should actually be a parameter so that we
+ * can decide for each individual gate whether it is beneficial to
+ * ignore deactivation.
+ */
+ if (m_NI >= m_min_devices_for_deactivate)
+ if (--m_active == 0)
+ {
+ for (std::size_t i = 0; i< m_NI; i++)
+ m_I[i].inactivate();
+ m_ign = (1<<m_NI)-1;
+ }
}
plib::uninitialised_array_t<logic_input_t, m_NI> m_I;
@@ -156,44 +153,46 @@ namespace devices
netlist_time mt(netlist_time::zero());
type_t nstate(0);
- type_t ign(m_ign);
-#if 1
- if (!doOUT)
- for (std::size_t i = 0; i < m_NI; i++)
- {
- m_I[i].activate();
- //nstate |= (m_I[i]() ? (1 << i) : 0);
- nstate |= (m_I[i]() << i);
- mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
- }
- else
- for (std::size_t i = 0; i < m_NI; i++)
- {
- if ((ign & 1))
- m_I[i].activate();
- //nstate |= (m_I[i]() ? (1 << i) : 0);
- nstate |= (m_I[i]() << i);
- ign >>= 1;
- }
-#else
- if (!doOUT)
+ if (m_NI >= m_min_devices_for_deactivate)
{
- nstate = aa<m_NI, type_t>().f(m_I, ~0);
- for (std::size_t i = 0; i < m_NI; i++)
- mt = std::max(this->m_I[i].net().time(), mt);
+ type_t ign(m_ign);
+ if (!doOUT)
+ for (std::size_t i = 0; i < m_NI; i++)
+ {
+ m_I[i].activate();
+ nstate |= (m_I[i]() ? (1 << i) : 0);
+ mt = std::max(this->m_I[i].net().time(), mt);
+ }
+ else
+ for (std::size_t i = 0; i < m_NI; i++)
+ {
+ if ((ign & 1))
+ m_I[i].activate();
+ nstate |= (m_I[i]() ? (1 << i) : 0);
+ ign >>= 1;
+ }
}
else
- nstate = aa<m_NI, type_t>().f(m_I, ign);
-#endif
+ {
+ if (!doOUT)
+ for (std::size_t i = 0; i < m_NI; i++)
+ {
+ nstate |= (m_I[i]() ? (1 << i) : 0);
+ mt = std::max(this->m_I[i].net().time(), mt);
+ }
+ else
+ for (std::size_t i = 0; i < m_NI; i++)
+ nstate |= (m_I[i]() ? (1 << i) : 0);
+ }
- const type_t outstate(m_ttp.m_out_state[nstate]);
+ const type_t outstate(m_ttp.m_outs[nstate]);
type_t out(outstate & m_outmask);
m_ign = outstate >> m_NO;
const std::size_t timebase(nstate * m_NO);
- const auto *t(&m_ttp.m_timing_index[timebase]);
- const auto *tim = m_ttp.m_timing_nt.data();
+ const auto *t(&m_ttp.m_timing[timebase]);
+ const auto *tim = m_ttp.m_timing_nt;
if (doOUT)
for (std::size_t i = 0; i < m_NO; out >>= 1, ++i)
@@ -202,14 +201,18 @@ namespace devices
for (std::size_t i = 0; i < m_NO; out >>= 1, ++i)
m_Q[i].set_Q_time(out & 1, mt + tim[t[i]]);
- ign = m_ign;
- for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
- if (ign & 1)
- I->inactivate();
+ if (m_NI >= m_min_devices_for_deactivate)
+ {
+ type_t ign(m_ign);
+ for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
+ if (ign & 1)
+ I->inactivate();
+ }
}
/* FIXME: check width */
state_var<type_t> m_ign;
+ state_var_s32 m_active;
const truthtable_t &m_ttp;
};
@@ -219,15 +222,15 @@ namespace devices
netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
const pstring &def_param, const pstring &sourcefile);
+ virtual ~netlist_base_factory_truthtable_t();
+
std::vector<pstring> m_desc;
- pstring m_family_name;
- const logic_family_desc_t *m_family_desc;
+ const logic_family_desc_t *m_family;
};
- /* the returned element is still missing a pointer to the family ... */
- plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &desc, const pstring &sourcefile);
+ void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile);
-} //namespace devices
+ } //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/macro/nlm_base.cpp b/src/lib/netlist/macro/nlm_base.cpp
index 86f2450d301..8ea6f148864 100644
--- a/src/lib/netlist/macro/nlm_base.cpp
+++ b/src/lib/netlist/macro/nlm_base.cpp
@@ -1,7 +1,7 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include "netlist/nl_setup.h"
-#include "netlist/devices/net_lib.h"
+#include "../nl_setup.h"
+#include "../devices/net_lib.h"
#include "nlm_base.h"
/* ----------------------------------------------------------------------------
@@ -12,14 +12,9 @@ static NETLIST_START(diode_models)
NET_MODEL("D _(IS=1e-15 N=1)")
NET_MODEL("1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
- // FIXME: 1N916 currently only a copy of 1N914!
- NET_MODEL("1N916 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
NET_MODEL("1N4001 D(Is=14.11n N=1.984 Rs=33.89m Ikf=94.81 Xti=3 Eg=1.11 Cjo=25.89p M=.44 Vj=.3245 Fc=.5 Bv=75 Ibv=10u Tt=5.7u Iave=1 Vpk=50 mfg=GI type=silicon)")
NET_MODEL("1N4148 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
NET_MODEL("1S1588 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75)")
-
- NET_MODEL("1N34A D( Bv=75 Cjo=0.5e-12 Eg=0.67 Ibv=18e-3 Is=2e-7 Rs=7 N=1.3 Vj=0.1 M=0.27 type=germanium)")
-
NET_MODEL("LedRed D(IS=93.2p RS=42M N=3.73 BV=4 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=4 type=LED)")
NET_MODEL("LedGreen D(IS=93.2p RS=42M N=4.61 BV=4 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=4 type=LED)")
NET_MODEL("LedBlue D(IS=93.2p RS=42M N=7.47 BV=5 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=5 type=LED)")
@@ -31,16 +26,9 @@ NETLIST_END()
* BJT Models
* ---------------------------------------------------------------------------*/
-static NETLIST_START(mosfet_models)
- //NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
- //NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
- NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
- NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
-NETLIST_END()
-
static NETLIST_START(bjt_models)
- NET_MODEL("NPN _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)")
- NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)")
+ NET_MODEL("NPN _(IS=1e-15 BF=100 NF=1 BR=1 NR=1)")
+ NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1)")
NET_MODEL("2SA1015 PNP(Is=295.1E-18 Xti=3 Eg=1.11 Vaf=100 Bf=110 Xtb=1.5 Br=10.45 Rc=15 Cjc=66.2p Mjc=1.054 Vjc=.75 Fc=.5 Cje=5p Mje=.3333 Vje=.75 Tr=10n Tf=1.661n VCEO=45V ICrating=150M MFG=Toshiba)")
NET_MODEL("2SC1815 NPN(Is=2.04f Xti=3 Eg=1.11 Vaf=6 Bf=400 Ikf=20m Xtb=1.5 Br=3.377 Rc=1 Cjc=1p Mjc=.3333 Vjc=.75 Fc=.5 Cje=25p Mje=.3333 Vje=.75 Tr=450n Tf=20n Itf=0 Vtf=0 Xtf=0 VCEO=45V ICrating=150M MFG=Toshiba)")
@@ -58,8 +46,6 @@ static NETLIST_START(bjt_models)
NET_MODEL("BC556B PNP(IS=3.83E-14 NF=1.008 ISE=1.22E-14 NE=1.528 BF=344.4 IKF=0.08039 VAF=21.11 NR=1.005 ISC=2.85E-13 NC=1.28 BR=14.84 IKR=0.047 VAR=32.02 RB=1 IRB=1.00E-06 RBM=1 RE=0.6202 RC=0.5713 XTB=0 EG=1.11 XTI=3 CJE=1.23E-11 VJE=0.6106 MJE=0.378 TF=5.60E-10 XTF=3.414 VTF=5.23 ITF=0.1483 PTF=0 CJC=1.08E-11 VJC=0.1022 MJC=0.3563 XCJC=0.6288 TR=1.00E-32 CJS=0 VJS=0.75 MJS=0.333 FC=0.8027 Vceo=65 Icrating=100m mfg=Philips)")
NET_MODEL("BC548C NPN(IS=1.95E-14 ISE=1.31E-15 ISC=1.0E-13 XTI=3 BF=466 BR=2.42 IKF=0.18 IKR=1 XTB=1.5 VAF=91.7 VAR=24.7 VJE=0.632 VJC=0.339 RE=1 RC=1.73 RB=26.5 RBM=10 IRB=10 CJE=1.33E-11 CJC=5.17E-12 XCJC=1 FC=0.9 NF=0.993 NR=1.2 NE=1.32 NC=2.00 MJE=0.326 MJC=0.319 TF=6.52E-10 TR=0 PTF=0 ITF=1.03 VTF=1.65 XTF=100 EG=1.11 KF=1E-9 AF=1 VCEO=40 ICrating=800M MFG=Siemens)")
NET_MODEL("BC817-25 NPN(IS=9.198E-14 NF=1.003 ISE=4.468E-16 NE=1.65 BF=338.8 IKF=0.4913 VAF=107.9 NR=1.002 ISC=5.109E-15 NC=1.071 BR=29.48 IKR=0.193 VAR=25 RB=1 IRB=1000 RBM=1 RE=0.2126 RC=0.143 XTB=0 EG=1.11 XTI=3 CJE=3.825E-11 VJE=0.7004 MJE=0.364 TF=5.229E-10 XTF=219.7 VTF=3.502 ITF=7.257 PTF=0 CJC=1.27E-11 VJC=0.4431 MJC=0.3983 XCJC=0.4555 TR=7E-11 CJS=0 VJS=0.75 MJS=0.333 FC=0.905 Vceo=45 Icrating=500m mfg=Philips)")
-
- NET_MODEL("9013 NPN(IS=3.40675E-14 BF=166 VAF=67 IKF=1.164 ISE=12.37e-15 NE=2 BR=15.17 VAR=40.84 IKR=0.261352 ISC=1.905E-15 NC=1.066 RB=63.2 IRB=5.62E-6 RBM=22.1 RE=0.02 RC=0.7426 CJE=3.53E-11 VJE=0.808 MJE=0.372 CJC=1.74E-11 VJC=0.614 MJC=0.388 XCJC=0.349 XTB=1.4025 EG=1.0999 XTI=3 VC=0.5 VCEO=20)")
NETLIST_END()
/* ----------------------------------------------------------------------------
@@ -88,22 +74,19 @@ NETLIST_START(base)
LOCAL_SOURCE(diode_models)
LOCAL_SOURCE(bjt_models)
- LOCAL_SOURCE(mosfet_models)
LOCAL_SOURCE(family_models)
-
LOCAL_SOURCE(TTL74XX_lib)
LOCAL_SOURCE(CD4XXX_lib)
LOCAL_SOURCE(OPAMP_lib)
LOCAL_SOURCE(otheric_lib)
- INCLUDE(diode_models)
- INCLUDE(bjt_models)
- INCLUDE(mosfet_models)
- INCLUDE(family_models)
- INCLUDE(TTL74XX_lib)
- INCLUDE(CD4XXX_lib)
- INCLUDE(OPAMP_lib)
- INCLUDE(otheric_lib)
+ INCLUDE(diode_models);
+ INCLUDE(bjt_models);
+ INCLUDE(family_models);
+ INCLUDE(TTL74XX_lib);
+ INCLUDE(CD4XXX_lib);
+ INCLUDE(OPAMP_lib);
+ INCLUDE(otheric_lib);
NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_base.h b/src/lib/netlist/macro/nlm_base.h
index 6a88ad5a1be..5ecf8071e98 100644
--- a/src/lib/netlist/macro/nlm_base.h
+++ b/src/lib/netlist/macro/nlm_base.h
@@ -10,7 +10,7 @@
#ifndef __PLIB_PREPROCESSOR__
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
/* ----------------------------------------------------------------------------
* Netlist Macros
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index 5ebd5593123..9ce786ca85e 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.cpp
+++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp
@@ -2,10 +2,10 @@
// copyright-holders:Couriersud
#include "nlm_cd4xxx.h"
-#include "netlist/devices/nld_4020.h"
-#include "netlist/devices/nld_4066.h"
-#include "netlist/devices/nld_4316.h"
-#include "netlist/devices/nld_system.h"
+#include "../devices/nld_system.h"
+#include "../devices/nld_4020.h"
+#include "../devices/nld_4066.h"
+#include "../devices/nld_4316.h"
/*
* CD4001BC: Quad 2-Input NOR Buffered B Series Gate
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.h b/src/lib/netlist/macro/nlm_cd4xxx.h
index d4d9c97fdc2..527336c1e8e 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.h
+++ b/src/lib/netlist/macro/nlm_cd4xxx.h
@@ -3,7 +3,7 @@
#ifndef NLD_CD4XXX_H_
#define NLD_CD4XXX_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
/*
* Devices:
diff --git a/src/lib/netlist/macro/nlm_opamp.cpp b/src/lib/netlist/macro/nlm_opamp.cpp
index 849f7820046..122b324f777 100644
--- a/src/lib/netlist/macro/nlm_opamp.cpp
+++ b/src/lib/netlist/macro/nlm_opamp.cpp
@@ -1,7 +1,7 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#include "nlm_opamp.h"
-#include "netlist/devices/net_lib.h"
+#include "../devices/net_lib.h"
/*
* Generic layout with 4 opamps, VCC on pin 4 and GND on pin 11
diff --git a/src/lib/netlist/macro/nlm_opamp.h b/src/lib/netlist/macro/nlm_opamp.h
index fbd7547c976..9cffbb29c87 100644
--- a/src/lib/netlist/macro/nlm_opamp.h
+++ b/src/lib/netlist/macro/nlm_opamp.h
@@ -3,7 +3,7 @@
#ifndef NLM_OPAMP_H_
#define NLM_OPAMP_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#ifndef __PLIB_PREPROCESSOR__
diff --git a/src/lib/netlist/macro/nlm_other.cpp b/src/lib/netlist/macro/nlm_other.cpp
index ea0eb1539a8..7e31ae27bb4 100644
--- a/src/lib/netlist/macro/nlm_other.cpp
+++ b/src/lib/netlist/macro/nlm_other.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Couriersud
#include "nlm_other.h"
-#include "netlist/devices/nld_system.h"
+#include "../devices/nld_system.h"
/*
* MC14584B: Hex Schmitt Trigger
diff --git a/src/lib/netlist/macro/nlm_other.h b/src/lib/netlist/macro/nlm_other.h
index ee231fbd6db..7c38d8ad363 100644
--- a/src/lib/netlist/macro/nlm_other.h
+++ b/src/lib/netlist/macro/nlm_other.h
@@ -3,7 +3,7 @@
#ifndef NLM_OTHER_H_
#define NLM_OTHER_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#ifndef __PLIB_PREPROCESSOR__
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index 58cab049ae7..df1b873a468 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -2,8 +2,8 @@
// copyright-holders:Couriersud
#include "nlm_ttl74xx.h"
-#include "netlist/devices/nld_schmitt.h"
-#include "netlist/devices/nld_system.h"
+#include "../devices/nld_schmitt.h"
+#include "../devices/nld_system.h"
/*
@@ -825,9 +825,8 @@ NETLIST_END()
NETLIST_START(TTL74XX_lib)
- NET_MODEL("DM7414 SCHMITT_TRIGGER(VTP=1.7 VTM=0.9 VI=4.35 RI=6.15k VOH=3.5 ROH=120 VOL=0.1 ROL=37.5 TPLH=15 TPHL=15)")
- NET_MODEL("TTL_7414_GATE SCHMITT_TRIGGER(VTP=1.7 VTM=0.9 VI=4.35 RI=6.15k VOH=3.5 ROH=120 VOL=0.1 ROL=37.5 TPLH=15 TPHL=15)")
- NET_MODEL("DM74LS14 SCHMITT_TRIGGER(VTP=1.6 VTM=0.8 VI=4.4 RI=19.3k VOH=3.45 ROH=130 VOL=0.1 ROL=31.2 TPLH=15 TPHL=15)")
+ NET_MODEL("DM7414 SCHMITT_TRIGGER(VTP=1.7 VTM=0.9 VI=4.35 RI=6.15k VOH=3.5 ROH=120 VOL=0.1 ROL=37.5 TPLH=15 TPHL=15)")
+ NET_MODEL("DM74LS14 SCHMITT_TRIGGER(VTP=1.6 VTM=0.8 VI=4.4 RI=19.3k VOH=3.45 ROH=130 VOL=0.1 ROL=31.2 TPLH=15 TPHL=15)")
//NET_MODEL("DM7414 FAMILY(FV=5 IVL=0.16 IVH=0.4 OVL=0.1 OVH=0.05 ORL=10.0 ORH=1.0e8)")
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.h b/src/lib/netlist/macro/nlm_ttl74xx.h
index 21ff99f2efe..c8868e45f7f 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.h
+++ b/src/lib/netlist/macro/nlm_ttl74xx.h
@@ -3,7 +3,7 @@
#ifndef NLD_TTL74XX_H_
#define NLD_TTL74XX_H_
-#include "netlist/nl_setup.h"
+#include "../nl_setup.h"
#ifndef __PLIB_PREPROCESSOR__
diff --git a/src/lib/netlist/netlist_types.h b/src/lib/netlist/netlist_types.h
new file mode 100644
index 00000000000..0bd32be21be
--- /dev/null
+++ b/src/lib/netlist/netlist_types.h
@@ -0,0 +1,54 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*!
+ *
+ * \file netlist_types.h
+ *
+ */
+
+#ifndef NETLIST_TYPES_H_
+#define NETLIST_TYPES_H_
+
+#include "nl_config.h"
+#include "plib/pchrono.h"
+#include "plib/pstring.h"
+
+#include <cstdint>
+#include <unordered_map>
+
+namespace netlist
+{
+ //============================================================
+ // Performance tracking
+ //============================================================
+
+#if NL_KEEP_STATISTICS
+ using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, true>;
+ using nperfcount_t = plib::chrono::counter<true>;
+#else
+ using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
+ using nperfcount_t = plib::chrono::counter<false>;
+#endif
+
+ //============================================================
+ // Types needed by various includes
+ //============================================================
+
+ namespace detail {
+
+ /*! Enum specifying the type of object */
+ enum terminal_type {
+ TERMINAL = 0, /*!< object is an analog terminal */
+ INPUT = 1, /*!< object is an input */
+ OUTPUT = 2, /*!< object is an output */
+ };
+
+ /*! Type of the model map used.
+ * This is used to hold all #Models in an unordered map
+ */
+ using model_map_t = std::unordered_map<pstring, pstring>;
+
+ }
+}
+
+#endif /* NETLIST_TYPES_H_ */
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index ad048e899bf..9a513c00804 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -8,19 +8,18 @@
#include "solver/nld_matrix_solver.h"
#include "solver/nld_solver.h"
-#include "plib/palloc.h"
-#include "plib/pmempool.h"
#include "plib/putil.h"
+#include "plib/palloc.h"
-#include "devices/nlid_proxy.h"
+#include "nl_base.h"
#include "devices/nlid_system.h"
+#include "devices/nlid_proxy.h"
#include "macro/nlm_base.h"
-#include "nl_base.h"
#include "nl_errstr.h"
-#include <cmath>
#include <cstring>
+#include <cmath>
#include <limits>
namespace netlist
@@ -28,13 +27,14 @@ namespace netlist
namespace detail
{
- //static plib::mempool *pool()
- //{
- // static plib::mempool s_pool(655360, 32);
- // return &s_pool;
- //}
+ static plib::mempool *pool()
+ {
+ static plib::mempool *s_pool = nullptr;
+ if (s_pool == nullptr)
+ s_pool = new plib::mempool(65536, 16);
+ return s_pool;
+ }
-#if 0
void * object_t::operator new (size_t size)
{
void *ret = nullptr;
@@ -44,30 +44,38 @@ namespace detail
ret = ::operator new(size);
return ret;
}
+
void object_t::operator delete (void * mem)
{
if (mem)
{
- //if ((USE_MEMPOOL))
- // pool()->free(mem);
- //else
+ if ((USE_MEMPOOL))
+ pool()->free(mem);
+ else
::operator delete(mem);
}
}
-#endif
-} // namespace detail
+}
+
+nl_exception::~nl_exception()
+{
+}
// ----------------------------------------------------------------------------------------
// logic_family_ttl_t
// ----------------------------------------------------------------------------------------
-// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default)
logic_family_desc_t::logic_family_desc_t()
{
}
+logic_family_desc_t::~logic_family_desc_t()
+{
+}
+
+
class logic_family_ttl_t : public logic_family_desc_t
{
public:
@@ -82,17 +90,17 @@ public:
m_R_low = 1.0;
m_R_high = 130.0;
}
- pool_owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
- pool_owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
};
-pool_owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_ttl_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const
+plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_ttl_t::create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const
{
- return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-pool_owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_ttl_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const
+plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_ttl_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
{
- return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
class logic_family_cd4xxx_t : public logic_family_desc_t
@@ -109,18 +117,17 @@ public:
m_R_low = 10.0;
m_R_high = 10.0;
}
- pool_owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
- pool_owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
};
-pool_owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_cd4xxx_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const
+plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_cd4xxx_t::create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const
{
- return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-
-pool_owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_cd4xxx_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const
+plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_cd4xxx_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
{
- return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
const logic_family_desc_t *family_TTL()
@@ -139,10 +146,10 @@ const logic_family_desc_t *family_CD4XXX()
// queue_t
// ----------------------------------------------------------------------------------------
-detail::queue_t::queue_t(netlist_state_t &nl)
- : timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>(512)
+detail::queue_t::queue_t(netlist_t &nl)
+ : timed_queue<pqentry_t<net_t *, netlist_time>, false>(512)
, netlist_ref(nl)
-// , plib::state_manager_t::callback_t()
+ , plib::state_manager_t::callback_t()
, m_qsize(0)
, m_times(512)
, m_net_ids(512)
@@ -151,56 +158,52 @@ detail::queue_t::queue_t(netlist_state_t &nl)
void detail::queue_t::register_state(plib::state_manager_t &manager, const pstring &module)
{
- //state().log().debug("register_state\n");
+ netlist().log().debug("register_state\n");
manager.save_item(this, m_qsize, module + "." + "qsize");
manager.save_item(this, &m_times[0], module + "." + "times", m_times.size());
manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size());
}
-void detail::queue_t::on_pre_save(plib::state_manager_t &manager)
+void detail::queue_t::on_pre_save()
{
- plib::unused_var(manager);
+ netlist().log().debug("on_pre_save\n");
m_qsize = this->size();
+ netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
for (std::size_t i = 0; i < m_qsize; i++ )
{
m_times[i] = this->listptr()[i].m_exec_time.as_raw();
- m_net_ids[i] = state().find_net_id(this->listptr()[i].m_object);
+ m_net_ids[i] = netlist().find_net_id(this->listptr()[i].m_object);
}
}
-void detail::queue_t::on_post_load(plib::state_manager_t &manager)
+void detail::queue_t::on_post_load()
{
- plib::unused_var(manager);
this->clear();
+ netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
for (std::size_t i = 0; i < m_qsize; i++ )
{
- detail::net_t *n = state().nets()[m_net_ids[i]].get();
+ detail::net_t *n = netlist().m_nets[m_net_ids[i]].get();
this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
// ----------------------------------------------------------------------------------------
-// netlist_ref_t
-// ----------------------------------------------------------------------------------------
-
-detail::netlist_ref::netlist_ref(netlist_state_t &nl)
-: m_netlist(nl.exec()) { }
-
-// ----------------------------------------------------------------------------------------
// object_t
// ----------------------------------------------------------------------------------------
detail::object_t::object_t(const pstring &aname)
-// : m_name(aname)
+ : m_name(plib::make_unique<pstring>(aname))
{
- name_hash().insert({this, aname});
}
-pstring detail::object_t::name() const
+detail::object_t::~object_t()
{
- return name_hash().find(this)->second;
- //return m_name;
+}
+
+const pstring &detail::object_t::name() const
+{
+ return *m_name;
}
// ----------------------------------------------------------------------------------------
@@ -227,7 +230,7 @@ detail::terminal_type detail::core_terminal_t::type() const
return terminal_type::OUTPUT;
else
{
- state().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
+ netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
return terminal_type::TERMINAL; // please compiler
}
}
@@ -236,37 +239,158 @@ detail::terminal_type detail::core_terminal_t::type() const
// netlist_t
// ----------------------------------------------------------------------------------------
-netlist_t::netlist_t(const pstring &aname, plib::unique_ptr<callbacks_t> callbacks)
- : m_state(plib::make_unique<netlist_state_t>(aname, *this, std::move(callbacks)))
- , m_solver(nullptr)
- , m_time(netlist_time::zero())
+netlist_t::netlist_t(const pstring &aname)
+ : m_time(netlist_time::zero())
+ , m_queue(*this)
, m_mainclock(nullptr)
- , m_queue(*m_state)
+ , m_solver(nullptr)
+ , m_params(nullptr)
+ , m_name(aname)
+ , m_log(*this)
+ , m_lib(nullptr)
+ , m_state()
{
- devices::initialize_factory(nlstate().setup().factory());
- NETLIST_NAME(base)(nlstate().setup());
- run_state_manager().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
- run_state_manager().save_item(this, m_time, "m_time");
+ state().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
+ state().save_item(this, m_time, "m_time");
+ m_setup = plib::make_unique<setup_t>(*this);
+ /* FIXME: doesn't really belong here */
+ NETLIST_NAME(base)(*m_setup);
}
-// ----------------------------------------------------------------------------------------
-// netlist_t
-// ----------------------------------------------------------------------------------------
+netlist_t::~netlist_t()
+{
+ m_nets.clear();
+ m_devices.clear();
+}
-netlist_state_t::netlist_state_t(const pstring &aname,
- netlist_t & anetlist,
- plib::unique_ptr<callbacks_t> &&callbacks)
-: m_name(aname)
-, m_netlist(anetlist)
-, m_state()
-, m_callbacks(std::move(callbacks)) // Order is important here
-, m_log(*m_callbacks)
-, m_setup(plib::make_unique<setup_t>(*this))
+nl_double netlist_t::gmin() const NL_NOEXCEPT
{
+ return solver()->gmin();
+}
+
+void netlist_t::register_dev(plib::owned_ptr<core_device_t> dev)
+{
+ for (auto & d : m_devices)
+ if (d->name() == dev->name())
+ log().fatal(MF_1_DUPLICATE_NAME_DEVICE_LIST, d->name());
+ m_devices.push_back(std::move(dev));
+}
+
+void netlist_t::remove_dev(core_device_t *dev)
+{
+ m_devices.erase(
+ std::remove_if(
+ m_devices.begin(),
+ m_devices.end(),
+ [&] (plib::owned_ptr<core_device_t> const& p)
+ {
+ return p.get() == dev;
+ }),
+ m_devices.end()
+ );
+}
+
+
+
+void netlist_t::start()
+{
+ setup().start_devices();
+
+ /* load the library ... */
+
+ /* make sure the solver and parameters are started first! */
+
+ for (auto & e : setup().m_device_factory)
+ {
+ if ( setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ || setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
+ register_dev(std::move(dev));
+ }
+ }
+
+ log().debug("Searching for mainclock and solver ...\n");
+
+ m_solver = get_single_device<devices::NETLIB_NAME(solver)>("solver");
+ m_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
+
+ /* create devices */
+
+ log().debug("Creating devices ...\n");
+ for (auto & e : setup().m_device_factory)
+ {
+ if ( !setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ && !setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
+ register_dev(std::move(dev));
+ }
+ }
+
+ log().debug("Searching for mainclock\n");
+ m_mainclock = get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
+
+ bool use_deactivate = (m_params->m_use_deactivate() ? true : false);
+
+ for (auto &d : m_devices)
+ {
+ if (use_deactivate)
+ {
+ auto p = setup().m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
+ if (p != setup().m_param_values.end())
+ {
+ //FIXME: turn this into a proper function
+ bool error;
+ auto v = p->second.as_double(&error);
+ if (error || std::abs(v - std::floor(v)) > 1e-6 )
+ log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
+ d->set_hint_deactivate(v == 0.0);
+ }
+ }
+ else
+ d->set_hint_deactivate(false);
+ }
+
pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
m_lib = plib::make_unique<plib::dynlib>(libpath);
-}
+ /* resolve inputs */
+ setup().resolve_inputs();
+
+ log().verbose("looking for two terms connected to rail nets ...");
+ for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
+ {
+ if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
+ {
+ log().warning(MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3,
+ t->name(), t->m_N.net().name(), t->m_P.net().name());
+ t->m_N.net().remove_terminal(t->m_N);
+ t->m_P.net().remove_terminal(t->m_P);
+ remove_dev(t);
+ }
+ }
+
+ log().verbose("initialize solver ...\n");
+
+ if (m_solver == nullptr)
+ {
+ for (auto &p : m_nets)
+ if (p->is_analog())
+ log().fatal(MF_0_NO_SOLVER);
+ }
+ else
+ m_solver->post_start();
+
+ for (auto &n : m_nets)
+ for (auto & term : n->m_core_terms)
+ {
+ //core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ core_device_t *dev = &term->device();
+ dev->set_default_delegate(*term);
+ }
+
+}
void netlist_t::stop()
{
@@ -277,7 +401,7 @@ void netlist_t::stop()
m_solver->stop();
}
-detail::net_t *netlist_state_t::find_net(const pstring &name) const
+detail::net_t *netlist_t::find_net(const pstring &name) const
{
for (auto & net : m_nets)
if (net->name() == name)
@@ -286,7 +410,7 @@ detail::net_t *netlist_state_t::find_net(const pstring &name) const
return nullptr;
}
-std::size_t netlist_state_t::find_net_id(const detail::net_t *net) const
+std::size_t netlist_t::find_net_id(const detail::net_t *net) const
{
for (std::size_t i = 0; i < m_nets.size(); i++)
if (m_nets[i].get() == net)
@@ -296,7 +420,7 @@ std::size_t netlist_state_t::find_net_id(const detail::net_t *net) const
-void netlist_state_t::rebuild_lists()
+void netlist_t::rebuild_lists()
{
for (auto & net : m_nets)
net->rebuild_list();
@@ -305,44 +429,32 @@ void netlist_state_t::rebuild_lists()
void netlist_t::reset()
{
- log().debug("Searching for mainclock\n");
- m_mainclock = 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");
-
m_time = netlist_time::zero();
m_queue.clear();
if (m_mainclock != nullptr)
- m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time::zero());
+ m_mainclock->m_Q.net().set_time(netlist_time::zero());
//if (m_solver != nullptr)
- // m_solver->reset();
-
- m_state->reset();
-}
+ // m_solver->do_reset();
-void netlist_state_t::reset()
-{
- //FIXME: never used ???
std::unordered_map<core_device_t *, bool> m;
+ for (auto &d : m_devices)
+ {
+ m[d.get()] = d->get_hint_deactivate();
+ }
+
+
// Reset all nets once !
- log().verbose("Call reset on all nets:");
- for (auto & n : nets())
+ for (auto & n : m_nets)
n->reset();
// Reset all devices once !
- log().verbose("Call reset on all devices:");
for (auto & dev : m_devices)
- dev.second->reset();
+ dev->do_reset();
// Make sure everything depending on parameters is set
- // Currently analog input and logic input also
- // push their outputs to queue.
-
- log().verbose("Call update_param on all devices:");
for (auto & dev : m_devices)
- dev.second->update_param();
+ dev->update_param();
// Step all devices once !
/*
@@ -350,9 +462,9 @@ void netlist_state_t::reset()
* variations are explicitly stated in the breakout manual.
*/
- auto *netlist_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
+ const unsigned startup_strategy = 1; //! \note make this a parameter
- switch (netlist_params->m_startup_strategy())
+ switch (startup_strategy)
{
case 0:
{
@@ -360,7 +472,7 @@ void netlist_state_t::reset()
std::vector<nldelegate *> t;
log().verbose("Using default startup strategy");
for (auto &n : m_nets)
- for (auto & term : n->core_terms())
+ for (auto & term : n->m_core_terms)
if (term->m_delegate.has_object())
{
if (!plib::container::contains(t, &term->m_delegate))
@@ -368,68 +480,70 @@ void netlist_state_t::reset()
t.push_back(&term->m_delegate);
term->m_delegate();
}
- auto *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
if (!plib::container::contains(d, dev))
d.push_back(dev);
}
- log().verbose("Devices not yet updated:");
- for (auto &dev : m_devices)
- if (!plib::container::contains(d, dev.second.get()))
+ log().verbose("Call update on devices which need parameter update:");
+ for (auto & dev : m_devices)
+ if (dev->needs_update_after_param_change())
{
- log().verbose("\t ...{1}", dev.second->name());
- dev.second->update();
+ if (!plib::container::contains(d, dev.get()))
+ {
+ d.push_back(dev.get());
+ log().verbose("\t ...{1}", dev->name());
+ dev->update_dev();
+ }
}
+ log().verbose("Devices not yet updated:");
+ for (auto &dev : m_devices)
+ if (!plib::container::contains(d, dev.get()))
+ log().verbose("\t ...{1}", dev->name());
+ //x->update_dev();
}
break;
case 1: // brute force backward
{
- log().verbose("Using brute force backward startup strategy");
-
- for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
- n->update_inputs();
-
std::size_t i = m_devices.size();
while (i>0)
- m_devices[--i].second->update();
-
- for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
- n->update_inputs();
-
+ m_devices[--i]->update_dev();
}
break;
case 2: // brute force forward
{
- log().verbose("Using brute force forward startup strategy");
for (auto &d : m_devices)
- d.second->update();
+ d->update_dev();
}
break;
}
#if 1
/* the above may screw up m_active and the list */
- rebuild_lists();
+ for (auto &n : m_nets)
+ n->rebuild_list();
#endif
}
-void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT
+void netlist_t::process_queue(const netlist_time &delta) NL_NOEXCEPT
{
- auto sm_guard(m_stat_mainloop.guard());
netlist_time stop(m_time + delta);
m_queue.push(detail::queue_t::entry_t(stop, nullptr));
+ m_stat_mainloop.start();
if (m_mainclock == nullptr)
{
- detail::queue_t::entry_t e(m_queue.pop());
+ detail::queue_t::entry_t e(m_queue.top());
+ m_queue.pop();
m_time = e.m_exec_time;
while (e.m_object != nullptr)
{
e.m_object->update_devs();
m_perf_out_processed.inc();
- e = m_queue.pop();
+ e = m_queue.top();
+ m_queue.pop();
m_time = e.m_exec_time;
}
}
@@ -437,7 +551,9 @@ void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT
{
logic_net_t &mc_net(m_mainclock->m_Q.net());
const netlist_time inc(m_mainclock->m_inc);
- netlist_time mc_time(mc_net.next_scheduled_time());
+ netlist_time mc_time(mc_net.time());
+
+ detail::queue_t::entry_t e;
do
{
@@ -449,37 +565,37 @@ void netlist_t::process_queue(const netlist_time delta) NL_NOEXCEPT
mc_time += inc;
}
- detail::queue_t::entry_t e(m_queue.pop());
+ e = m_queue.top();
+ m_queue.pop();
m_time = e.m_exec_time;
if (e.m_object != nullptr)
{
e.m_object->update_devs();
m_perf_out_processed.inc();
}
- else
- break;
- } while (true); //while (e.m_object != nullptr);
- mc_net.set_next_scheduled_time(mc_time);
+ } while (e.m_object != nullptr);
+ mc_net.set_time(mc_time);
}
+ m_stat_mainloop.stop();
}
void netlist_t::print_stats() const
{
- if (nperftime_t<NL_KEEP_STATISTICS>::enabled)
+ if (nperftime_t::enabled)
{
std::vector<size_t> index;
- for (size_t i=0; i < m_state->m_devices.size(); i++)
+ for (size_t i=0; i<m_devices.size(); i++)
index.push_back(i);
std::sort(index.begin(), index.end(),
- [&](size_t i1, size_t i2) { return m_state->m_devices[i1].second->m_stat_total_time.total() < m_state->m_devices[i2].second->m_stat_total_time.total(); });
+ [&](size_t i1, size_t i2) { return m_devices[i1]->m_stat_total_time.total() < m_devices[i2]->m_stat_total_time.total(); });
- nperftime_t<NL_KEEP_STATISTICS>::type total_time(0);
- nperftime_t<NL_KEEP_STATISTICS>::ctype total_count(0);
+ nperftime_t::type total_time(0);
+ uint_least64_t total_count(0);
for (auto & j : index)
{
- auto entry = m_state->m_devices[j].second.get();
+ auto entry = m_devices[j].get();
log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(),
entry->m_stat_call_count(), entry->m_stat_total_time.count(),
entry->m_stat_total_time.total(), entry->m_stat_inc_active());
@@ -487,27 +603,22 @@ void netlist_t::print_stats() const
total_count += entry->m_stat_total_time.count();
}
- log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count,
- total_time, total_time / static_cast<decltype(total_time)>(total_count));
-
- nperftime_t<NL_KEEP_STATISTICS> overhead;
- nperftime_t<NL_KEEP_STATISTICS> test;
+ nperftime_t overhead;
+ nperftime_t test;
+ overhead.start();
+ for (int j=0; j<100000;j++)
{
- auto overhead_guard(overhead.guard());
- for (int j=0; j<100000;j++)
- {
- auto test_guard(test.guard());
- }
+ test.start();
+ test.stop();
}
+ overhead.stop();
- nperftime_t<NL_KEEP_STATISTICS>::type total_overhead = overhead()
- * static_cast<nperftime_t<NL_KEEP_STATISTICS>::type>(total_count)
- / static_cast<nperftime_t<NL_KEEP_STATISTICS>::type>(200000);
+ nperftime_t::type total_overhead = overhead()
+ * static_cast<nperftime_t::type>(total_count)
+ / static_cast<nperftime_t::type>(200000);
- log().verbose("Queue Pushes {1:15}", m_queue.m_prof_call());
- log().verbose("Queue Moves {1:15}", m_queue.m_prof_sortmove());
- log().verbose("Queue Removes {1:15}", m_queue.m_prof_remove());
- log().verbose("Queue Retimes {1:15}", m_queue.m_prof_retime());
+ log().verbose("Queue Pushes {1:15}", queue().m_prof_call());
+ log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove());
log().verbose("Total loop {1:15}", m_stat_mainloop());
/* Only one serialization should be counted in total time */
@@ -516,36 +627,29 @@ void netlist_t::print_stats() const
log().verbose("");
log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
log().verbose("Total overhead {1:15}", total_overhead);
- nperftime_t<NL_KEEP_STATISTICS>::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
- / static_cast<nperftime_t<NL_KEEP_STATISTICS>::type>(m_queue.m_prof_call());
+ nperftime_t::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
+ / static_cast<nperftime_t::type>(queue().m_prof_call());
log().verbose("Overhead per pop {1:11}", overhead_per_pop );
log().verbose("");
-
- auto trigger = total_count * 200 / 1000000; // 200 ppm
- for (auto &entry : m_state->m_devices)
+ for (auto &entry : m_devices)
{
- auto ep = entry.second.get();
- // Factor of 3 offers best performace increase
- if (ep->m_stat_inc_active() > 3 * ep->m_stat_total_time.count()
- && ep->m_stat_inc_active() > trigger)
- log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(),
- static_cast<double>(ep->m_stat_inc_active()) / static_cast<double>(ep->m_stat_total_time.count()),
- ep->m_stat_inc_active(), ep->m_stat_total_time.count());
+ if (entry->m_stat_inc_active() > 3 * entry->m_stat_total_time.count())
+ log().verbose("HINT({}, NO_DEACTIVATE)", entry->name());
}
}
}
-core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const
+core_device_t *netlist_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const
{
core_device_t *ret = nullptr;
for (auto &d : m_devices)
{
- if (cc(d.second.get()))
+ if (cc(d.get()))
{
if (ret != nullptr)
- m_log.fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
+ this->log().fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
else
- ret = d.second.get();
+ ret = d.get();
}
}
return ret;
@@ -556,12 +660,11 @@ core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool
// core_device_t
// ----------------------------------------------------------------------------------------
-core_device_t::core_device_t(netlist_state_t &owner, const pstring &name)
+core_device_t::core_device_t(netlist_t &owner, const pstring &name)
: object_t(name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
- , m_active_outputs(*this, "m_active_outputs", 1)
{
if (logic_family() == nullptr)
set_logic_family(family_TTL());
@@ -570,14 +673,17 @@ core_device_t::core_device_t(netlist_state_t &owner, const pstring &name)
core_device_t::core_device_t(core_device_t &owner, const pstring &name)
: object_t(owner.name() + "." + name)
, logic_family_t()
- , netlist_ref(owner.state())
+ , netlist_ref(owner.netlist())
, m_hint_deactivate(false)
- , m_active_outputs(*this, "m_active_outputs", 1)
{
set_logic_family(owner.logic_family());
if (logic_family() == nullptr)
set_logic_family(family_TTL());
- state().add_dev(this->name(), pool_owned_ptr<core_device_t>(this, false));
+ owner.netlist().register_dev(plib::owned_ptr<core_device_t>(this, false));
+}
+
+core_device_t::~core_device_t()
+{
}
void core_device_t::set_default_delegate(detail::core_terminal_t &term)
@@ -586,16 +692,16 @@ void core_device_t::set_default_delegate(detail::core_terminal_t &term)
term.m_delegate.set(&core_device_t::update, this);
}
-log_type & core_device_t::log()
+plib::plog_base<netlist_t, NL_DEBUG> &core_device_t::log()
{
- return state().log();
+ return netlist().log();
}
// ----------------------------------------------------------------------------------------
// device_t
// ----------------------------------------------------------------------------------------
-device_t::device_t(netlist_state_t &owner, const pstring &name)
+device_t::device_t(netlist_t &owner, const pstring &name)
: core_device_t(owner, name)
{
}
@@ -605,14 +711,14 @@ device_t::device_t(core_device_t &owner, const pstring &name)
{
}
-setup_t &device_t::setup()
+device_t::~device_t()
{
- return state().setup();
+ //log().debug("~net_device_t\n");
}
-const setup_t &device_t::setup() const
+setup_t &device_t::setup()
{
- return state().setup();
+ return netlist().setup();
}
void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term)
@@ -656,14 +762,9 @@ void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_term
// family_setter_t
// -----------------------------------------------------------------------------
-// NOLINTNEXTLINE(modernize-use-equals-default)
-detail::family_setter_t::family_setter_t()
-{
-}
-
detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring &desc)
{
- dev.set_logic_family(dev.setup().family_from_model(desc));
+ dev.set_logic_family(dev.netlist().setup().family_from_model(desc));
}
detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc)
@@ -675,45 +776,81 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr)
+detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
: object_t(aname)
, netlist_ref(nl)
, m_new_Q(*this, "m_new_Q", 0)
, m_cur_Q (*this, "m_cur_Q", 0)
- , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED)
- , m_next_scheduled_time(*this, "m_time", netlist_time::zero())
+ , m_in_queue(*this, "m_in_queue", QS_DELIVERED)
+ , m_active(*this, "m_active", 0)
+ , m_time(*this, "m_time", netlist_time::zero())
, m_railterminal(mr)
{
}
+detail::net_t::~net_t()
+{
+ netlist().state().remove_save_items(this);
+}
+
+void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
+{
+ m_list_active.push_front(&term);
+ ++m_active;
+ nl_assert(m_active <= static_cast<int>(num_cons()));
+ if (m_active == 1)
+ {
+ railterminal().device().do_inc_active();
+ if (m_in_queue == QS_DELAYED_DUE_TO_INACTIVE)
+ {
+ if (m_time > netlist().time())
+ {
+ m_in_queue = QS_QUEUED; /* pending */
+ netlist().queue().push({m_time, this});
+ }
+ else
+ {
+ m_in_queue = QS_DELIVERED;
+ m_cur_Q = m_new_Q;
+ }
+ }
+ }
+}
+
+void detail::net_t::dec_active(core_terminal_t &term) NL_NOEXCEPT
+{
+ --m_active;
+ nl_assert(m_active >= 0);
+ m_list_active.remove(&term);
+ if (m_active == 0)
+ railterminal().device().do_dec_active();
+}
+
void detail::net_t::rebuild_list()
{
/* rebuild m_list */
+ int cnt = 0;
m_list_active.clear();
for (auto & term : m_core_terms)
- if (term->terminal_state() != logic_t::STATE_INP_PASSIVE)
+ if (term->state() != logic_t::STATE_INP_PASSIVE)
{
m_list_active.push_back(term);
- term->set_copied_input(m_cur_Q);
+ cnt++;
}
+ m_active = cnt;
}
-template <typename T>
-void detail::net_t::process(const T mask, netlist_sig_t sig)
-{
- m_cur_Q = sig;
+void detail::net_t::process(unsigned Mask)
+{
for (auto & p : m_list_active)
{
- p.set_copied_input(sig);
-
p.device().m_stat_call_count.inc();
- if ((p.terminal_state() & mask))
+ if ((p.state() & Mask) != 0)
{
- auto g(p.device().m_stat_total_time.guard());
- //p.device().m_stat_total_time.start();
+ p.device().m_stat_total_time.start();
p.m_delegate();
- //p.device().m_stat_total_time.stop();
+ p.device().m_stat_total_time.stop();
}
}
}
@@ -722,59 +859,67 @@ void detail::net_t::update_devs() NL_NOEXCEPT
{
nl_assert(this->isRailNet());
- const auto new_Q(m_new_Q);
+ const unsigned mask((m_new_Q << core_terminal_t::INP_LH_SHIFT)
+ | (m_cur_Q<<core_terminal_t::INP_HL_SHIFT));
- const auto mask((new_Q << core_terminal_t::INP_LH_SHIFT)
- | (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
+ m_in_queue = QS_DELIVERED; /* mark as taken ... */
- m_in_queue = queue_status::DELIVERED; /* mark as taken ... */
switch (mask)
{
case core_terminal_t::STATE_INP_HL:
+ m_cur_Q = m_new_Q;
+ process(core_terminal_t::STATE_INP_HL | core_terminal_t::STATE_INP_ACTIVE);
+ break;
case core_terminal_t::STATE_INP_LH:
- process(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q);
+ m_cur_Q = m_new_Q;
+ process(core_terminal_t::STATE_INP_LH | core_terminal_t::STATE_INP_ACTIVE);
break;
default:
- /* do nothing */
break;
}
}
void detail::net_t::reset()
{
- m_next_scheduled_time = netlist_time::zero();
- m_in_queue = queue_status::DELIVERED;
+ m_time = netlist_time::zero();
+ m_active = 0;
+ m_in_queue = QS_DELIVERED;
m_new_Q = 0;
m_cur_Q = 0;
- auto *p = dynamic_cast<analog_net_t *>(this);
+ analog_net_t *p = dynamic_cast<analog_net_t *>(this);
if (p != nullptr)
p->m_cur_Analog = 0.0;
- /* rebuild m_list and reset terminals to active or analog out state */
+ /* rebuild m_list */
m_list_active.clear();
for (core_terminal_t *ct : m_core_terms)
- {
+ m_list_active.push_back(ct);
+
+ for (core_terminal_t *ct : m_core_terms)
ct->reset();
- if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE)
- m_list_active.push_back(ct);
- ct->set_copied_input(m_cur_Q);
- }
+
+ for (core_terminal_t *ct : m_core_terms)
+ if (ct->state() != logic_t::STATE_INP_PASSIVE)
+ m_active++;
}
void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
{
for (auto &t : m_core_terms)
if (t == &terminal)
- state().log().fatal(MF_2_NET_1_DUPLICATE_TERMINAL_2, name(),
+ netlist().log().fatal(MF_2_NET_1_DUPLICATE_TERMINAL_2, name(),
t->name());
terminal.set_net(this);
m_core_terms.push_back(&terminal);
+
+ if (terminal.state() != logic_t::STATE_INP_PASSIVE)
+ m_active++;
}
void detail::net_t::remove_terminal(detail::core_terminal_t &terminal)
@@ -785,8 +930,10 @@ void detail::net_t::remove_terminal(detail::core_terminal_t &terminal)
plib::container::remove(m_core_terms, &terminal);
}
else
- state().log().fatal(MF_2_REMOVE_TERMINAL_1_FROM_NET_2, terminal.name(),
+ netlist().log().fatal(MF_2_REMOVE_TERMINAL_1_FROM_NET_2, terminal.name(),
this->name());
+ if (terminal.state() != logic_t::STATE_INP_PASSIVE)
+ m_active--;
}
void detail::net_t::move_connections(detail::net_t &dest_net)
@@ -794,28 +941,37 @@ void detail::net_t::move_connections(detail::net_t &dest_net)
for (auto &ct : m_core_terms)
dest_net.add_terminal(*ct);
m_core_terms.clear();
+ m_active = 0;
}
// ----------------------------------------------------------------------------------------
// logic_net_t
// ----------------------------------------------------------------------------------------
-logic_net_t::logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr)
+logic_net_t::logic_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr)
: net_t(nl, aname, mr)
{
}
+logic_net_t::~logic_net_t()
+{
+}
+
// ----------------------------------------------------------------------------------------
// analog_net_t
// ----------------------------------------------------------------------------------------
-analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr)
+analog_net_t::analog_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr)
: net_t(nl, aname, mr)
, m_cur_Analog(*this, "m_cur_Analog", 0.0)
, m_solver(nullptr)
{
}
+analog_net_t::~analog_net_t()
+{
+}
+
// ----------------------------------------------------------------------------------------
// core_terminal_t
// ----------------------------------------------------------------------------------------
@@ -825,19 +981,42 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam
: device_object_t(dev, dev.name() + "." + aname)
, plib::linkedlist_t<core_terminal_t>::element_t()
, m_delegate(delegate)
-#if USE_COPY_INSTEAD_OF_REFERENCE
-, m_Q(*this, "m_Q", 0)
-#endif
, m_net(nullptr)
, m_state(*this, "m_state", state)
{
}
+detail::core_terminal_t::~core_terminal_t()
+{
+}
+
+void detail::core_terminal_t::reset()
+{
+ if (is_type(OUTPUT))
+ set_state(STATE_OUT);
+ else
+ set_state(STATE_INP_ACTIVE);
+}
+
+void detail::core_terminal_t::set_net(net_t *anet)
+{
+ m_net = anet;
+}
+
+void detail::core_terminal_t::clear_net()
+{
+ m_net = nullptr;
+}
+
analog_t::analog_t(core_device_t &dev, const pstring &aname, const state_e state)
: core_terminal_t(dev, aname, state)
{
}
+analog_t::~analog_t()
+{
+}
+
logic_t::logic_t(core_device_t &dev, const pstring &aname, const state_e state,
nldelegate delegate)
: core_terminal_t(dev, aname, state, delegate)
@@ -846,18 +1025,26 @@ logic_t::logic_t(core_device_t &dev, const pstring &aname, const state_e state,
{
}
+logic_t::~logic_t()
+{
+}
+
// ----------------------------------------------------------------------------------------
// terminal_t
// ----------------------------------------------------------------------------------------
-terminal_t::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm)
+terminal_t::terminal_t(core_device_t &dev, const pstring &aname)
: analog_t(dev, aname, STATE_BIDIR)
+, m_otherterm(nullptr)
, m_Idr1(nullptr)
, m_go1(nullptr)
, m_gt1(nullptr)
-, m_connected_terminal(otherterm)
{
- state().setup().register_term(*this);
+ netlist().setup().register_term(*this);
+}
+
+terminal_t::~terminal_t()
+{
}
void terminal_t::solve_now()
@@ -868,7 +1055,7 @@ void terminal_t::solve_now()
net().solver()->update_forced();
}
-void terminal_t::schedule_solve_after(const netlist_time after)
+void terminal_t::schedule_solve_after(const netlist_time &after)
{
// Nets may belong to railnets which do not have a solver attached
if (this->has_net())
@@ -890,12 +1077,16 @@ void terminal_t::schedule_solve_after(const netlist_time after)
logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname)
: logic_t(dev, aname, STATE_OUT)
- , m_my_net(dev.state(), name() + ".net", this)
+ , m_my_net(dev.netlist(), name() + ".net", this)
{
this->set_net(&m_my_net);
- state().register_net(pool_owned_ptr<logic_net_t>(&m_my_net, false));
+ netlist().m_nets.push_back(plib::owned_ptr<logic_net_t>(&m_my_net, false));
set_logic_family(dev.logic_family());
- state().setup().register_term(*this);
+ netlist().setup().register_term(*this);
+}
+
+logic_output_t::~logic_output_t()
+{
}
void logic_output_t::initial(const netlist_sig_t val)
@@ -911,7 +1102,11 @@ void logic_output_t::initial(const netlist_sig_t val)
analog_input_t::analog_input_t(core_device_t &dev, const pstring &aname)
: analog_t(dev, aname, STATE_INP_ACTIVE)
{
- state().setup().register_term(*this);
+ netlist().setup().register_term(*this);
+}
+
+analog_input_t::~analog_input_t()
+{
}
// ----------------------------------------------------------------------------------------
@@ -920,13 +1115,17 @@ analog_input_t::analog_input_t(core_device_t &dev, const pstring &aname)
analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
: analog_t(dev, aname, STATE_OUT)
- , m_my_net(dev.state(), name() + ".net", this)
+ , m_my_net(dev.netlist(), name() + ".net", this)
{
- state().register_net(pool_owned_ptr<analog_net_t>(&m_my_net, false));
+ netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(&m_my_net, false));
this->set_net(&m_my_net);
//net().m_cur_Analog = NL_FCONST(0.0);
- state().setup().register_term(*this);
+ netlist().setup().register_term(*this);
+}
+
+analog_output_t::~analog_output_t()
+{
}
void analog_output_t::initial(const nl_double val)
@@ -943,7 +1142,11 @@ logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname,
: logic_t(dev, aname, STATE_INP_ACTIVE, delegate)
{
set_logic_family(dev.logic_family());
- state().setup().register_term(*this);
+ netlist().setup().register_term(*this);
+}
+
+logic_input_t::~logic_input_t()
+{
}
// ----------------------------------------------------------------------------------------
@@ -953,7 +1156,11 @@ logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname,
param_t::param_t(device_t &device, const pstring &name)
: device_object_t(device, device.name() + "." + name)
{
- device.setup().register_param_t(this->name(), *this);
+ device.setup().register_param(this->name(), *this);
+}
+
+param_t::~param_t()
+{
}
param_t::param_type_t param_t::param_type() const
@@ -970,7 +1177,7 @@ param_t::param_type_t param_t::param_type() const
return POINTER;
else
{
- state().log().fatal(MF_1_UNKNOWN_PARAM_TYPE, name());
+ netlist().log().fatal(MF_1_UNKNOWN_PARAM_TYPE, name());
return POINTER; /* Please compiler */
}
}
@@ -979,18 +1186,15 @@ param_t::param_type_t param_t::param_type() const
void param_t::update_param()
{
device().update_param();
-}
-
-pstring param_t::get_initial(const device_t &dev, bool *found)
-{
- pstring res = dev.setup().get_initial_param_val(this->name(), "");
- *found = (res != "");
- return res;
+ if (device().needs_update_after_param_change())
+ device().update_dev();
}
const pstring param_model_t::model_type()
{
- return state().setup().models().model_type(value());
+ if (m_map.size() == 0)
+ netlist().setup().model_parse(this->Value(), m_map);
+ return m_map["COREMODEL"];
}
param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val)
@@ -999,10 +1203,35 @@ param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &v
m_param = device.setup().get_initial_param_val(this->name(),val);
}
+param_str_t::~param_str_t()
+{
+}
+
void param_str_t::changed()
{
}
+param_double_t::param_double_t(device_t &device, const pstring &name, const double val)
+: param_t(device, name)
+{
+ m_param = device.setup().get_initial_param_val(this->name(),val);
+ netlist().save(*this, m_param, "m_param");
+}
+
+param_int_t::param_int_t(device_t &device, const pstring &name, const int val)
+: param_t(device, name)
+{
+ m_param = device.setup().get_initial_param_val(this->name(),val);
+ netlist().save(*this, m_param, "m_param");
+}
+
+param_logic_t::param_logic_t(device_t &device, const pstring &name, const bool val)
+: param_t(device, name)
+{
+ m_param = device.setup().get_initial_param_val(this->name(),val);
+ netlist().save(*this, m_param, "m_param");
+}
+
param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val)
: param_t(device, name)
{
@@ -1012,25 +1241,53 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val)
void param_model_t::changed()
{
- state().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
+ netlist().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
+ m_map.clear();
}
const pstring param_model_t::model_value_str(const pstring &entity)
{
- return state().setup().models().model_value_str(value(), entity);
+ if (m_map.size() == 0)
+ netlist().setup().model_parse(this->Value(), m_map);
+ return netlist().setup().model_value_str(m_map, entity);
}
nl_double param_model_t::model_value(const pstring &entity)
{
- return state().setup().models().model_value(value(), entity);
+ if (m_map.size() == 0)
+ netlist().setup().model_parse(this->Value(), m_map);
+ return netlist().setup().model_value(m_map, entity);
}
+param_data_t::param_data_t(device_t &device, const pstring &name)
+: param_str_t(device, name, "")
+{
+}
+
+void param_data_t::changed()
+{
+}
-plib::unique_ptr<plib::pistream> param_data_t::stream()
+std::unique_ptr<plib::pistream> param_data_t::stream()
{
- return device().setup().get_data_stream(value());
+ return device().netlist().setup().get_data_stream(Value());
}
+ namespace devices
+ {
+ // ----------------------------------------------------------------------------------------
+ // mainclock
+ // ----------------------------------------------------------------------------------------
+
+ void NETLIB_NAME(mainclock)::mc_update(logic_net_t &net)
+ {
+ net.toggle_new_Q();
+ net.update_devs();
+ }
+
+
+ } //namespace devices
+
bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT
{
return dynamic_cast<const logic_t *>(this) != nullptr;
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 9d0eed869e0..e56fde89f88 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -9,25 +9,27 @@
#ifndef NLBASE_H_
#define NLBASE_H_
-#ifdef NL_PROHIBIT_BASEH_INCLUDE
-#error "nl_base.h included. Please correct."
-#endif
-
+#include "nl_lists.h"
+#include "nl_time.h"
#include "plib/palloc.h" // owned_ptr
#include "plib/pdynlib.h"
-#include "plib/pfmtlog.h"
-#include "plib/pmempool.h"
-#include "plib/ppmf.h"
#include "plib/pstate.h"
+#include "plib/pfmtlog.h"
#include "plib/pstream.h"
-
-#include "nl_errstr.h"
-#include "nl_lists.h"
-#include "nltypes.h"
-#include "plib/ptime.h"
+#include "plib/ppmf.h"
#include <unordered_map>
-#include <vector>
+
+#ifdef NL_PROHIBIT_BASEH_INCLUDE
+#error "nl_base.h included. Please correct."
+#endif
+
+// ----------------------------------------------------------------------------------------
+// Type definitions
+// ----------------------------------------------------------------------------------------
+
+/*! netlist_sig_t is the type used for logic signals. */
+using netlist_sig_t = std::uint32_t;
//============================================================
// MACROS / New Syntax
@@ -71,7 +73,7 @@ class NETLIB_NAME(name) : public device_t
/*! Used to define the destructor of a netlist device.
* The use of a destructor for netlist device should normally not be necessary.
*/
-#define NETLIB_DESTRUCTOR(name) public: virtual ~NETLIB_NAME(name)() noexcept
+#define NETLIB_DESTRUCTOR(name) public: virtual ~NETLIB_NAME(name)()
/*! Define an extended constructor and add further parameters to it.
* The macro allows to add further parameters to a device constructor. This is
@@ -83,15 +85,14 @@ class NETLIB_NAME(name) : public device_t
: device_t(owner, name)
/*! Add this to a device definition to mark the device as dynamic.
- *
- * If NETLIB_IS_DYNAMIC(true) is added to the device definition the device
- * is treated as an analog dynamic device, i.e. #NETLIB_UPDATE_TERMINALSI
- * is called on a each step of the Newton-Raphson step
- * of solving the linear equations.
- *
- * You may also use e.g. NETLIB_IS_DYNAMIC(m_func() != "") to only make the
- * device a dynamic device if parameter m_func is set.
- */
+ * If NETLIB_IS_DYNAMIC(true) is added to the device definition the device
+ * is treated as an analog dynamic device, i.e. #NETLIB_UPDATE_TERMINALSI
+ * is called on a each step of the Newton-Raphson step
+ * of solving the linear equations.
+ *
+ * You may also use e.g. NETLIB_IS_DYNAMIC(m_func() != "") to only make the
+ * device a dynamic device if parameter m_func is set.
+ */
#define NETLIB_IS_DYNAMIC(expr) \
public: virtual bool is_dynamic() const override { return expr; }
@@ -126,30 +127,36 @@ class NETLIB_NAME(name) : public device_t
#define NETLIB_TIMESTEPI() \
public: virtual void timestep(const nl_double step) override
+#define NETLIB_UPDATE_AFTER_PARAM_CHANGE() \
+ public: virtual bool needs_update_after_param_change() const override { return true; }
+
#define NETLIB_FAMILY(family) , m_famsetter(*this, family)
#define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this)
-#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() override
-#define NETLIB_HANDLERI(name) virtual void name() NL_NOEXCEPT
-#define NETLIB_UPDATEI() virtual void update() NL_NOEXCEPT override
-#define NETLIB_UPDATE_PARAMI() virtual void update_param() override
-#define NETLIB_RESETI() virtual void reset() override
+#define NETLIB_UPDATE_TERMINALSI() public: virtual void update_terminals() override
+#define NETLIB_HANDLERI(name) private: virtual void name() NL_NOEXCEPT
+#define NETLIB_UPDATEI() protected: virtual void update() NL_NOEXCEPT override
+#define NETLIB_UPDATE_PARAMI() public: virtual void update_param() override
+#define NETLIB_RESETI() protected: virtual void reset() override
#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step)
#define NETLIB_SUB(chip) nld_ ## chip
-#define NETLIB_SUBXX(ns, chip) pool_owned_ptr< ns :: nld_ ## chip >
+#define NETLIB_SUBXX(ns, chip) std::unique_ptr< ns :: nld_ ## chip >
-#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() NL_NOEXCEPT
+#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name(void) NL_NOEXCEPT
#define NETLIB_UPDATE(chip) NETLIB_HANDLER(chip, update)
+// FIXME: NETLIB_PARENT_UPDATE should disappear
+#define NETLIB_PARENT_UPDATE(chip) NETLIB_NAME(chip) :: update();
+
#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
-#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param()
+#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param(void)
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params
-#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals()
+#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals(void)
//============================================================
// Asserts
@@ -162,7 +169,7 @@ class NETLIB_NAME(name) : public device_t
#define nl_assert(x) do { if (0) if (!(x)) { /*throw nl_exception(plib::pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); */} } while (0)
#define NL_NOEXCEPT noexcept
#endif
-#define nl_assert_always(x, msg) do { if (!(x)) throw nl_exception("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}", msg, __FILE__, __LINE__, #x); } while (0)
+#define nl_assert_always(x, msg) do { if (!(x)) throw nl_exception(plib::pfmt("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}")(msg)(__FILE__)(__LINE__)(#x)); } while (0)
//============================================================
// Namespace starts
@@ -170,11 +177,6 @@ class NETLIB_NAME(name) : public device_t
namespace netlist
{
- /*! Delegate type for device notification.
- *
- */
- using nldelegate = plib::pmfp<void>;
-
// -----------------------------------------------------------------------------
// forward definitions
// -----------------------------------------------------------------------------
@@ -189,23 +191,27 @@ namespace netlist
class NETLIB_NAME(base_proxy);
class NETLIB_NAME(base_d_to_a_proxy);
class NETLIB_NAME(base_a_to_d_proxy);
- } // namespace devices
+ }
namespace detail {
+ class object_t;
+ class device_object_t;
+ struct netlist_ref;
+ class core_terminal_t;
struct family_setter_t;
class queue_t;
- } // namespace detail
+ class net_t;
+ }
class logic_output_t;
class logic_input_t;
class analog_net_t;
class logic_net_t;
+ class net_t;
class setup_t;
class netlist_t;
- class netlist_state_t;
class core_device_t;
class device_t;
- class callbacks_t;
//============================================================
// Exceptions
@@ -223,12 +229,9 @@ namespace netlist
explicit nl_exception(const pstring &text //!< text to be passed
)
: plib::pexception(text) { }
-
- template<typename... Args>
- explicit nl_exception(const pstring &fmt //!< format to be used
- , Args&&... args //!< arguments to be passed
- )
- : plib::pexception(plib::pfmt(fmt)(std::forward<Args>(args)...)) { }
+ /*! Copy constructor. */
+ nl_exception(const nl_exception &e) : plib::pexception(e) { }
+ virtual ~nl_exception();
};
/*! Logic families descriptors are used to create proxy devices.
@@ -239,21 +242,18 @@ namespace netlist
{
public:
logic_family_desc_t();
+ virtual ~logic_family_desc_t();
- COPYASSIGNMOVE(logic_family_desc_t, delete)
-
- virtual ~logic_family_desc_t() noexcept = default;
-
- virtual pool_owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name,
+ virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist, const pstring &name,
logic_output_t *proxied) const = 0;
- virtual pool_owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name,
+ virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name,
logic_input_t *proxied) const = 0;
double fixed_V() const { return m_fixed_V; }
double low_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_low_thresh_PCNT; }
double high_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_high_thresh_PCNT; }
- double low_V(const double VN, const double VP) const { plib::unused_var(VP); return VN + m_low_VO; }
- double high_V(const double VN, const double VP) const { plib::unused_var(VN); return VP - m_high_VO; }
+ double low_V(const double VN, const double VP) const { return VN + m_low_VO; }
+ double high_V(const double VN, const double VP) const { return VP - m_high_VO; }
double R_low() const { return m_R_low; }
double R_high() const { return m_R_high; }
@@ -282,14 +282,12 @@ namespace netlist
public:
logic_family_t() : m_logic_family(nullptr) {}
- COPYASSIGNMOVE(logic_family_t, delete)
-
const logic_family_desc_t *logic_family() const { return m_logic_family; }
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
protected:
- ~logic_family_t() noexcept = default; // prohibit polymorphic destruction
+ ~logic_family_t() { } // prohibit polymorphic destruction
const logic_family_desc_t *m_logic_family;
};
@@ -319,15 +317,12 @@ namespace netlist
const pstring &name, //!< identifier/name for this state variable
const T &value //!< Initial value after construction
);
-
- //! Destructor.
- ~state_var() noexcept = default;
//! Copy Constructor.
- constexpr state_var(const state_var &rhs) = default;
+ constexpr state_var(const state_var &rhs) noexcept = default;
//! Move Constructor.
constexpr state_var(state_var &&rhs) noexcept = default;
//! Assignment operator to assign value of a state var.
- C14CONSTEXPR state_var &operator=(const state_var &rhs) = default;
+ C14CONSTEXPR state_var &operator=(const state_var &rhs) noexcept = default;
//! Assignment move operator to assign value of a state var.
C14CONSTEXPR state_var &operator=(state_var &&rhs) noexcept = default;
//! Assignment operator to assign value of type T.
@@ -350,29 +345,25 @@ namespace netlist
* Please refer to \ref state_var.
*/
template <typename T, std::size_t N>
- struct state_array
+ struct state_var<T[N]>
{
public:
//! Constructor.
template <typename O>
- state_array(O &owner, //!< owner must have a netlist() method.
+ state_var(O &owner, //!< owner must have a netlist() method.
const pstring &name, //!< identifier/name for this state variable
const T &value //!< Initial value after construction
);
//! Copy Constructor.
- state_array(const state_array &rhs) noexcept = default;
- //! Destructor.
- ~state_array() noexcept = default;
+ state_var(const state_var &rhs) NL_NOEXCEPT = default;
//! Move Constructor.
- state_array(state_array &&rhs) noexcept = default;
- state_array &operator=(const state_array &rhs) noexcept = default;
- state_array &operator=(state_array &&rhs) noexcept = default;
-
- state_array &operator=(const T &rhs) noexcept { m_value = rhs; return *this; }
- T & operator[](const std::size_t i) noexcept { return m_value[i]; }
- constexpr const T & operator[](const std::size_t i) const noexcept { return m_value[i]; }
+ state_var(state_var &&rhs) NL_NOEXCEPT = default;
+ state_var &operator=(const state_var &rhs) NL_NOEXCEPT = default;
+ state_var &operator=(const T &rhs) NL_NOEXCEPT { m_value = rhs; return *this; }
+ T & operator[](const std::size_t i) NL_NOEXCEPT { return m_value[i]; }
+ constexpr T & operator[](const std::size_t i) const NL_NOEXCEPT { return m_value[i]; }
private:
- std::array<T, N> m_value;
+ T m_value[N];
};
// -----------------------------------------------------------------------------
@@ -391,324 +382,164 @@ namespace netlist
/*! predefined state variable type for sig_t */
using state_var_sig = state_var<netlist_sig_t>;
- namespace detail {
+ // -----------------------------------------------------------------------------
+ // object_t
+ // -----------------------------------------------------------------------------
- // -----------------------------------------------------------------------------
- // object_t
- // -----------------------------------------------------------------------------
+ /*! The base class for netlist devices, terminals and parameters.
+ *
+ * This class serves as the base class for all device, terminal and
+ * objects. It provides new and delete operators to support e.g. pooled
+ * memory allocation to enhance locality. Please refer to \ref USE_MEMPOOL as
+ * well.
+ */
+ class detail::object_t
+ {
+ public:
- /*! The base class for netlist devices, terminals and parameters.
+ /*! Constructor.
*
- * This class serves as the base class for all device, terminal and
- * objects. It provides new and delete operators to support e.g. pooled
- * memory allocation to enhance locality. Please refer to \ref USE_MEMPOOL as
- * well.
+ * Every class derived from the object_t class must have a name.
*/
- class object_t
- {
- public:
-
- /*! Constructor.
- *
- * Every class derived from the object_t class must have a name.
- */
- explicit object_t(const pstring &aname /*!< string containing name of the object */);
-
- COPYASSIGNMOVE(object_t, delete)
- /*! return name of the object
- *
- * \returns name of the object.
- */
- pstring name() const;
-
- #if 0
- void * operator new (size_t size, void *ptr) { plib::unused_var(size); return ptr; }
- void operator delete (void *ptr, void *) { plib::unused_var(ptr); }
- void * operator new (size_t size) = delete;
- void operator delete (void * mem) = delete;
- #endif
- protected:
- ~object_t() noexcept = default; // only childs should be destructible
+ explicit object_t(const pstring &aname /*!< string containing name of the object */);
- private:
- //pstring m_name;
- static std::unordered_map<const object_t *, pstring> &name_hash()
- {
- static std::unordered_map<const object_t *, pstring> lhash;
- return lhash;
- }
- };
-
- struct netlist_ref
- {
- explicit netlist_ref(netlist_state_t &nl);
+ /*! return name of the object
+ *
+ * \returns name of the object.
+ */
+ const pstring &name() const;
- COPYASSIGNMOVE(netlist_ref, delete)
+ void * operator new (size_t size, void *ptr) { return ptr; }
+ void operator delete (void *ptr, void *) { }
+ void * operator new (size_t size);
+ void operator delete (void * mem);
+ protected:
+ ~object_t(); // only childs should be destructible
- netlist_state_t & state() noexcept;
- const netlist_state_t & state() const noexcept;
+ private:
+ std::unique_ptr<pstring> m_name;
+ };
- setup_t & setup() noexcept;
- const setup_t & setup() const noexcept;
+ struct detail::netlist_ref
+ {
+ explicit constexpr netlist_ref(netlist_t &nl) : m_netlist(nl) { }
- netlist_t & exec() noexcept { return m_netlist; }
- const netlist_t & exec() const noexcept { return m_netlist; }
+ C14CONSTEXPR netlist_t & netlist() NL_NOEXCEPT { return m_netlist; }
+ constexpr const netlist_t & netlist() const NL_NOEXCEPT { return m_netlist; }
- protected:
- ~netlist_ref() noexcept = default; // prohibit polymorphic destruction
+ protected:
+ ~netlist_ref() = default; // prohibit polymorphic destruction
- private:
- netlist_t & m_netlist;
+ private:
+ netlist_t & m_netlist;
- };
+ };
- // -----------------------------------------------------------------------------
- // device_object_t
- // -----------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------
+ // device_object_t
+ // -----------------------------------------------------------------------------
- /*! Base class for all objects being owned by a device.
- *
- * Serves as the base class of all objects being owned by a device.
+ /*! Base class for all objects being owned by a device.
+ *
+ * Serves as the base class of all objects being owned by a device.
+ *
+ */
+ class detail::device_object_t : public detail::object_t
+ {
+ public:
+ /*! Constructor.
*
+ * \param dev device owning the object.
+ * \param name string holding the name of the device
*/
- class device_object_t : public object_t
- {
- public:
- /*! Constructor.
- *
- * \param dev device owning the object.
- * \param name string holding the name of the device
- */
- device_object_t(core_device_t &dev, const pstring &name);
-
- /*! returns reference to owning device.
- * \returns reference to owning device.
- */
- core_device_t &device() noexcept { return m_device; }
- const core_device_t &device() const noexcept { return m_device; }
-
- /*! The netlist owning the owner of this object.
- * \returns reference to netlist object.
- */
- netlist_state_t &state() NL_NOEXCEPT;
- const netlist_state_t &state() const NL_NOEXCEPT;
-
- netlist_t &exec() NL_NOEXCEPT;
- const netlist_t &exec() const NL_NOEXCEPT;
+ device_object_t(core_device_t &dev, const pstring &name);
- private:
- core_device_t & m_device;
- };
-
- // -----------------------------------------------------------------------------
- // core_terminal_t
- // -----------------------------------------------------------------------------
-
- /*! Base class for all terminals.
- *
- * All terminals are derived from this class.
- *
+ /*! returns reference to owning device.
+ * \returns reference to owning device.
*/
+ core_device_t &device() NL_NOEXCEPT { return m_device; }
+ const core_device_t &device() const NL_NOEXCEPT { return m_device; }
- class net_t;
-
- class core_terminal_t : public device_object_t,
- public plib::linkedlist_t<core_terminal_t>::element_t
- {
- public:
-
- using list_t = std::vector<core_terminal_t *>;
-
- static constexpr const auto INP_HL_SHIFT = 0;
- static constexpr const auto INP_LH_SHIFT = 1;
- static constexpr const auto INP_ACTIVE_SHIFT = 2;
-
- enum state_e {
- STATE_INP_PASSIVE = 0,
- STATE_INP_HL = (1 << INP_HL_SHIFT),
- STATE_INP_LH = (1 << INP_LH_SHIFT),
- STATE_INP_ACTIVE = (1 << INP_ACTIVE_SHIFT),
- STATE_OUT = 128,
- STATE_BIDIR = 256
- };
-
- core_terminal_t(core_device_t &dev, const pstring &aname,
- const state_e state, nldelegate delegate = nldelegate());
- virtual ~core_terminal_t() noexcept = default;
-
- COPYASSIGNMOVE(core_terminal_t, delete)
-
- /*! The object type.
- * \returns type of the object
- */
- terminal_type type() const;
- /*! Checks if object is of specified type.
- * \param atype type to check object against.
- * \returns true if object is of specified type else false.
- */
- bool is_type(const terminal_type atype) const noexcept { return (type() == atype); }
-
- void set_net(net_t *anet) noexcept { m_net = anet; }
- void clear_net() noexcept { m_net = nullptr; }
- bool has_net() const noexcept { return (m_net != nullptr); }
+ /*! The netlist owning the owner of this object.
+ * \returns reference to netlist object.
+ */
+ netlist_t &netlist() NL_NOEXCEPT;
+ const netlist_t &netlist() const NL_NOEXCEPT;
- const net_t & net() const noexcept { return *m_net;}
- net_t & net() noexcept { return *m_net;}
+ private:
+ core_device_t & m_device;
+};
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
+ /*! Delegate type for device notification.
+ *
+ */
+ typedef plib::pmfp<void> nldelegate;
- bool is_state(state_e astate) const noexcept { return (m_state == astate); }
- state_e terminal_state() const noexcept { return m_state; }
- void set_state(state_e astate) noexcept { m_state = astate; }
+ // -----------------------------------------------------------------------------
+ // core_terminal_t
+ // -----------------------------------------------------------------------------
- void reset() noexcept { set_state(is_type(OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); }
+ /*! Base class for all terminals.
+ *
+ * All terminals are derived from this class.
+ *
+ */
+ class detail::core_terminal_t : public device_object_t,
+ public plib::linkedlist_t<core_terminal_t>::element_t
+ {
+ public:
- nldelegate m_delegate;
- #if USE_COPY_INSTEAD_OF_REFERENCE
- void set_copied_input(netlist_sig_t val)
- {
- m_Q = val;
- }
+ using list_t = std::vector<core_terminal_t *>;
- state_var_sig m_Q;
- #else
- void set_copied_input(netlist_sig_t val) const { plib::unused_var(val); }
- #endif
+ static constexpr const unsigned INP_HL_SHIFT = 0;
+ static constexpr const unsigned INP_LH_SHIFT = 1;
+ static constexpr const unsigned INP_ACTIVE_SHIFT = 2;
- private:
- net_t * m_net;
- state_var<state_e> m_state;
+ enum state_e {
+ STATE_INP_PASSIVE = 0,
+ STATE_INP_HL = (1 << INP_HL_SHIFT),
+ STATE_INP_LH = (1 << INP_LH_SHIFT),
+ STATE_INP_ACTIVE = (1 << INP_ACTIVE_SHIFT),
+ STATE_OUT = 128,
+ STATE_BIDIR = 256
};
- // -----------------------------------------------------------------------------
- // net_t
- // -----------------------------------------------------------------------------
-
- class net_t :
- public object_t,
- public netlist_ref
- {
- public:
-
- enum class queue_status
- {
- DELAYED_DUE_TO_INACTIVE = 0,
- QUEUED,
- DELIVERED
- };
-
- net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr = nullptr);
-
- COPYASSIGNMOVE(net_t, delete)
-
- virtual ~net_t() noexcept = default;
-
- void reset();
-
- void toggle_new_Q() noexcept { m_new_Q = (m_cur_Q ^ 1); }
-
- void toggle_and_push_to_queue(netlist_time delay) NL_NOEXCEPT
- {
- toggle_new_Q();
- push_to_queue(delay);
- }
-
- void push_to_queue(netlist_time delay) NL_NOEXCEPT;
- bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; }
-
- void update_devs() NL_NOEXCEPT;
-
- netlist_time next_scheduled_time() const noexcept { return m_next_scheduled_time; }
- void set_next_scheduled_time(netlist_time ntime) noexcept { m_next_scheduled_time = ntime; }
-
- bool isRailNet() const noexcept { return !(m_railterminal == nullptr); }
- core_terminal_t & railterminal() const noexcept { return *m_railterminal; }
-
- std::size_t num_cons() const noexcept { return m_core_terms.size(); }
-
- void add_to_active_list(core_terminal_t &term) NL_NOEXCEPT;
- void remove_from_active_list(core_terminal_t &term) NL_NOEXCEPT;
-
- /* setup stuff */
-
- void add_terminal(core_terminal_t &terminal);
- void remove_terminal(core_terminal_t &terminal);
-
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
-
- void rebuild_list(); /* rebuild m_list after a load */
- void move_connections(net_t &dest_net);
-
- std::vector<core_terminal_t *> &core_terms() { return m_core_terms; }
- #if USE_COPY_INSTEAD_OF_REFERENCE
- void update_inputs()
- {
- for (auto & term : m_core_terms)
- term->m_Q = m_cur_Q;
- }
- #else
- void update_inputs() const
- {
- /* nothing needs to be done */
- }
- #endif
-
- protected:
+ core_terminal_t(core_device_t &dev, const pstring &aname,
+ const state_e state, nldelegate delegate = nldelegate());
+ virtual ~core_terminal_t();
- /* only used for logic nets */
- netlist_sig_t Q() const noexcept { return m_cur_Q; }
+ /*! The object type.
+ * \returns type of the object
+ */
+ terminal_type type() const;
+ /*! Checks if object is of specified type.
+ * \param atype type to check object against.
+ * \returns true if object is of specified type else false.
+ */
+ bool is_type(const terminal_type atype) const { return (type() == atype); }
- /* only used for logic nets */
- void initial(const netlist_sig_t val) noexcept
- {
- m_cur_Q = m_new_Q = val;
- update_inputs();
- }
+ void set_net(net_t *anet);
+ void clear_net();
+ bool has_net() const NL_NOEXCEPT { return (m_net != nullptr); }
- /* only used for logic nets */
- void set_Q_and_push(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
- {
- if (newQ != m_new_Q)
- {
- m_new_Q = newQ;
- push_to_queue(delay);
- }
- }
+ const net_t & net() const NL_NOEXCEPT { return *m_net;}
+ net_t & net() NL_NOEXCEPT { return *m_net;}
- /* only used for logic nets */
- void set_Q_time(const netlist_sig_t newQ, const netlist_time at) NL_NOEXCEPT
- {
- if (newQ != m_new_Q)
- {
- m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE;
- m_next_scheduled_time = at;
- }
- m_cur_Q = m_new_Q = newQ;
- update_inputs();
- }
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
- /* internal state support
- * FIXME: get rid of this and implement export/import in MAME
- */
- /* only used for logic nets */
- netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
+ bool is_state(const state_e &astate) const NL_NOEXCEPT { return (m_state == astate); }
+ const state_e &state() const NL_NOEXCEPT { return m_state; }
+ void set_state(const state_e &astate) NL_NOEXCEPT { m_state = astate; }
- private:
- state_var<netlist_sig_t> m_new_Q;
- state_var<netlist_sig_t> m_cur_Q;
- state_var<queue_status> m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
- state_var<netlist_time> m_next_scheduled_time;
+ void reset();
- core_terminal_t * m_railterminal;
- plib::linkedlist_t<core_terminal_t> m_list_active;
- std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
+ nldelegate m_delegate;
- template <typename T>
- void process(const T mask, netlist_sig_t sig);
- };
- } // namespace detail
+ private:
+ net_t * m_net;
+ state_var<state_e> m_state;
+ };
// -----------------------------------------------------------------------------
// analog_t
@@ -719,6 +550,7 @@ namespace netlist
public:
analog_t(core_device_t &dev, const pstring &aname, const state_e state);
+ virtual ~analog_t();
const analog_net_t & net() const NL_NOEXCEPT;
analog_net_t & net() NL_NOEXCEPT;
@@ -732,44 +564,53 @@ namespace netlist
{
public:
- terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm);
+ terminal_t(core_device_t &dev, const pstring &aname);
+ virtual ~terminal_t();
nl_double operator ()() const NL_NOEXCEPT;
- void set_conductivity(const nl_double G) noexcept
+ void set(const nl_double &G) NL_NOEXCEPT
{
- set_go_gt_I(-G, G, 0.0);
+ set(G,G, 0.0);
}
- void set_go_gt(const nl_double GO, const nl_double GT) noexcept
+ void set(const nl_double &GO, const nl_double &GT) NL_NOEXCEPT
{
- set_go_gt_I(GO, GT, 0.0);
+ set(GO, GT, 0.0);
}
- void set_go_gt_I(const nl_double GO, const nl_double GT, const nl_double I) noexcept
+ void set(const nl_double &GO, const nl_double &GT, const nl_double &I) NL_NOEXCEPT
{
- if (m_go1 != nullptr)
- {
- if (*m_Idr1 != I) *m_Idr1 = I;
- if (*m_go1 != GO) *m_go1 = GO;
- if (*m_gt1 != GT) *m_gt1 = GT;
- }
+ set_ptr(m_Idr1, I);
+ set_ptr(m_go1, GO);
+ set_ptr(m_gt1, GT);
}
void solve_now();
- void schedule_solve_after(const netlist_time after);
+ void schedule_solve_after(const netlist_time &after);
- void set_ptrs(nl_double *gt, nl_double *go, nl_double *Idr) noexcept;
+ void set_ptrs(nl_double *gt, nl_double *go, nl_double *Idr) NL_NOEXCEPT
+ {
+ m_gt1 = gt;
+ m_go1 = go;
+ m_Idr1 = Idr;
+ }
+
+ terminal_t *m_otherterm;
- terminal_t *connected_terminal() const noexcept { return m_connected_terminal; }
private:
+ void set_ptr(nl_double *ptr, const nl_double &val) NL_NOEXCEPT
+ {
+ if (ptr != nullptr && *ptr != val)
+ {
+ *ptr = val;
+ }
+ }
nl_double *m_Idr1; // drive current
nl_double *m_go1; // conductance for Voltage from other term
nl_double *m_gt1; // conductance for total conductance
- terminal_t *m_connected_terminal;
-
};
@@ -782,6 +623,7 @@ namespace netlist
public:
logic_t(core_device_t &dev, const pstring &aname,
const state_e state, nldelegate delegate = nldelegate());
+ virtual ~logic_t();
bool has_proxy() const { return (m_proxy != nullptr); }
devices::nld_base_proxy *get_proxy() const { return m_proxy; }
@@ -805,6 +647,7 @@ namespace netlist
public:
logic_input_t(core_device_t &dev, const pstring &aname,
nldelegate delegate = nldelegate());
+ virtual ~logic_input_t();
netlist_sig_t operator()() const NL_NOEXCEPT
{
@@ -836,6 +679,9 @@ namespace netlist
const pstring &aname /*!< name of terminal */
);
+ /*! Destructor */
+ virtual ~analog_input_t();
+
/*! returns voltage at terminal.
* \returns voltage at terminal.
*/
@@ -848,18 +694,124 @@ namespace netlist
};
+ // -----------------------------------------------------------------------------
+ // net_t
+ // -----------------------------------------------------------------------------
+
+ class detail::net_t :
+ public detail::object_t,
+ public detail::netlist_ref
+ {
+ public:
+
+ enum queue_status
+ {
+ QS_DELAYED_DUE_TO_INACTIVE = 0,
+ QS_QUEUED,
+ QS_DELIVERED
+ };
+
+ net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr = nullptr);
+ virtual ~net_t();
+
+ void reset();
+
+ void toggle_new_Q() NL_NOEXCEPT { m_new_Q = (m_cur_Q ^ 1); }
+
+ void toggle_and_push_to_queue(const netlist_time &delay) NL_NOEXCEPT
+ {
+ toggle_new_Q();
+ push_to_queue(delay);
+ }
+
+ void push_to_queue(const netlist_time &delay) NL_NOEXCEPT;
+ bool is_queued() const NL_NOEXCEPT { return m_in_queue == QS_QUEUED; }
+
+ void update_devs() NL_NOEXCEPT;
+
+ const netlist_time &time() const NL_NOEXCEPT { return m_time; }
+ void set_time(const netlist_time &ntime) NL_NOEXCEPT { m_time = ntime; }
+
+ bool isRailNet() const NL_NOEXCEPT { return !(m_railterminal == nullptr); }
+ core_terminal_t & railterminal() const NL_NOEXCEPT { return *m_railterminal; }
+
+ std::size_t num_cons() const NL_NOEXCEPT { return m_core_terms.size(); }
+
+ void inc_active(core_terminal_t &term) NL_NOEXCEPT;
+ void dec_active(core_terminal_t &term) NL_NOEXCEPT;
+
+ /* setup stuff */
+
+ void add_terminal(core_terminal_t &terminal);
+ void remove_terminal(core_terminal_t &terminal);
+
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
+
+ void rebuild_list(); /* rebuild m_list after a load */
+ void move_connections(net_t &dest_net);
+
+ std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
+
+ protected:
+ state_var<netlist_sig_t> m_new_Q;
+ state_var<netlist_sig_t> m_cur_Q;
+ state_var<queue_status> m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
+ state_var_s32 m_active;
+
+ state_var<netlist_time> m_time;
+
+ private:
+ plib::linkedlist_t<core_terminal_t> m_list_active;
+ core_terminal_t * m_railterminal;
+
+ void process(unsigned Mask);
+ };
class logic_net_t : public detail::net_t
{
public:
- logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
+ logic_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
+ virtual ~logic_net_t();
+
+ netlist_sig_t Q() const NL_NOEXCEPT { return m_cur_Q; }
+ void initial(const netlist_sig_t val) NL_NOEXCEPT { m_cur_Q = m_new_Q = val; }
+
+ void set_Q_and_push(const netlist_sig_t newQ, const netlist_time &delay) NL_NOEXCEPT
+ {
+ if (newQ != m_new_Q )
+ {
+ m_new_Q = newQ;
+ push_to_queue(delay);
+ }
+ }
+ void set_Q_and_push_force(const netlist_sig_t newQ, const netlist_time &delay) NL_NOEXCEPT
+ {
+ if (newQ != m_new_Q || is_queued())
+ {
+ m_new_Q = newQ;
+ push_to_queue(delay);
+ }
+ }
+
+ void set_Q_time(const netlist_sig_t newQ, const netlist_time &at) NL_NOEXCEPT
+ {
+ if (newQ != m_new_Q)
+ {
+ m_in_queue = QS_DELAYED_DUE_TO_INACTIVE;
+ m_time = at;
+ }
+ m_cur_Q = m_new_Q = newQ;
+ }
+
+ /* internal state support
+ * FIXME: get rid of this and implement export/import in MAME
+ */
+ netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
- using detail::net_t::Q;
- using detail::net_t::initial;
- using detail::net_t::set_Q_and_push;
- using detail::net_t::set_Q_time;
- using detail::net_t::Q_state_ptr;
+ protected:
+ private:
};
@@ -871,7 +823,9 @@ namespace netlist
friend class detail::net_t;
- analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
+ analog_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
+
+ virtual ~analog_net_t();
nl_double Q_Analog() const NL_NOEXCEPT { return m_cur_Analog; }
void set_Q_Analog(const nl_double v) NL_NOEXCEPT { m_cur_Analog = v; }
@@ -895,15 +849,21 @@ namespace netlist
public:
logic_output_t(core_device_t &dev, const pstring &aname);
+ virtual ~logic_output_t();
void initial(const netlist_sig_t val);
- void push(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
+ void push(const netlist_sig_t newQ, const netlist_time &delay) NL_NOEXCEPT
{
m_my_net.set_Q_and_push(newQ, delay); // take the shortcut
}
- void set_Q_time(const netlist_sig_t newQ, const netlist_time at) NL_NOEXCEPT
+ void push_force(const netlist_sig_t newQ, const netlist_time &delay) NL_NOEXCEPT
+ {
+ m_my_net.set_Q_and_push_force(newQ, delay); // take the shortcut
+ }
+
+ void set_Q_time(const netlist_sig_t newQ, const netlist_time &at) NL_NOEXCEPT
{
m_my_net.set_Q_time(newQ, at); // take the shortcut
}
@@ -916,6 +876,7 @@ namespace netlist
{
public:
analog_output_t(core_device_t &dev, const pstring &aname);
+ virtual ~analog_output_t();
void push(const nl_double val) NL_NOEXCEPT { set_Q(val); }
void initial(const nl_double val);
@@ -943,17 +904,13 @@ namespace netlist
param_t(device_t &device, const pstring &name);
- COPYASSIGNMOVE(param_t, delete)
-
param_type_t param_type() const;
protected:
- virtual ~param_t() noexcept = default; /* not intended to be destroyed */
+ virtual ~param_t(); /* not intended to be destroyed */
void update_param();
- pstring get_initial(const device_t &dev, bool *found);
-
template<typename C>
void set(C &p, const C v)
{
@@ -966,51 +923,53 @@ namespace netlist
};
- // -----------------------------------------------------------------------------
- // numeric parameter template
- // -----------------------------------------------------------------------------
-
- template <typename T>
- class param_num_t final: public param_t
+ class param_ptr_t final: public param_t
{
public:
- param_num_t(device_t &device, const pstring &name, const T val);
-
- const T operator()() const NL_NOEXCEPT { return m_param; }
- void setTo(const T &param) { set(m_param, param); }
+ param_ptr_t(device_t &device, const pstring &name, std::uint8_t* val);
+ std::uint8_t * operator()() const NL_NOEXCEPT { return m_param; }
+ void setTo(std::uint8_t *param) { set(m_param, param); }
private:
- T m_param;
+ std::uint8_t* m_param;
};
- /* FIXME: these should go as well */
- using param_logic_t = param_num_t<bool>;
- using param_int_t = param_num_t<int>;
- using param_double_t = param_num_t<double>;
-
- // -----------------------------------------------------------------------------
- // pointer parameter
- // -----------------------------------------------------------------------------
+ class param_logic_t final: public param_t
+ {
+ public:
+ param_logic_t(device_t &device, const pstring &name, const bool val);
+ const bool &operator()() const NL_NOEXCEPT { return m_param; }
+ void setTo(const bool &param) { set(m_param, param); }
+ private:
+ bool m_param;
+ };
- class param_ptr_t final: public param_t
+ class param_int_t final: public param_t
{
public:
- param_ptr_t(device_t &device, const pstring &name, std::uint8_t* val);
- std::uint8_t * operator()() const NL_NOEXCEPT { return m_param; }
- void setTo(std::uint8_t *param) { set(m_param, param); }
+ param_int_t(device_t &device, const pstring &name, const int val);
+ const int &operator()() const NL_NOEXCEPT { return m_param; }
+ void setTo(const int &param) { set(m_param, param); }
private:
- std::uint8_t* m_param;
+ int m_param;
};
- // -----------------------------------------------------------------------------
- // string parameter
- // -----------------------------------------------------------------------------
+ class param_double_t final: public param_t
+ {
+ public:
+ param_double_t(device_t &device, const pstring &name, const double val);
+ const double &operator()() const NL_NOEXCEPT { return m_param; }
+ void setTo(const double &param) { set(m_param, param); }
+ private:
+ double m_param;
+ };
class param_str_t : public param_t
{
public:
param_str_t(device_t &device, const pstring &name, const pstring &val);
+ virtual ~param_str_t();
- const pstring &operator()() const NL_NOEXCEPT { return value(); }
+ const pstring &operator()() const NL_NOEXCEPT { return Value(); }
void setTo(const pstring &param) NL_NOEXCEPT
{
if (m_param != param)
@@ -1022,16 +981,11 @@ namespace netlist
}
protected:
virtual void changed();
- const pstring &value() const NL_NOEXCEPT { return m_param; }
+ const pstring &Value() const NL_NOEXCEPT { return m_param; }
private:
- PALIGNAS_CACHELINE()
pstring m_param;
};
- // -----------------------------------------------------------------------------
- // model parameter
- // -----------------------------------------------------------------------------
-
class param_model_t : public param_str_t
{
public:
@@ -1043,8 +997,8 @@ namespace netlist
: m_value(param.model_value(name))
{
}
- double operator()() const noexcept { return m_value; }
- operator double() const noexcept { return m_value; }
+ const double &operator()() const NL_NOEXCEPT { return m_value; }
+ operator const double&() const NL_NOEXCEPT { return m_value; }
private:
const double m_value;
};
@@ -1056,29 +1010,24 @@ namespace netlist
const pstring model_value_str(const pstring &entity) /*const*/;
const pstring model_type() /*const*/;
- /* hide this */
- void setTo(const pstring &param) = delete;
protected:
- void changed() override;
+ virtual void changed() override;
nl_double model_value(const pstring &entity) /*const*/;
private:
+ /* hide this */
+ void setTo(const pstring &param) = delete;
+ detail::model_map_t m_map;
};
- // -----------------------------------------------------------------------------
- // data parameter
- // -----------------------------------------------------------------------------
class param_data_t : public param_str_t
{
public:
- param_data_t(device_t &device, const pstring &name)
- : param_str_t(device, name, "")
- {
- }
+ param_data_t(device_t &device, const pstring &name);
- plib::unique_ptr<plib::pistream> stream();
+ std::unique_ptr<plib::pistream> stream();
protected:
- void changed() override { }
+ virtual void changed() override;
};
// -----------------------------------------------------------------------------
@@ -1092,15 +1041,15 @@ namespace netlist
param_rom_t(device_t &device, const pstring &name);
- ST operator[] (std::size_t n) const NL_NOEXCEPT { return m_data[n]; }
+ const ST & operator[] (std::size_t n) NL_NOEXCEPT { return m_data[n]; }
protected:
- void changed() override
+ virtual void changed() override
{
- stream()->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW);
+ stream()->read(&m_data[0],1<<AW);
}
private:
- std::array<ST, 1 << AW> m_data;
+ ST m_data[1 << AW];
};
// -----------------------------------------------------------------------------
@@ -1113,67 +1062,68 @@ namespace netlist
public detail::netlist_ref
{
public:
- core_device_t(netlist_state_t &owner, const pstring &name);
+ core_device_t(netlist_t &owner, const pstring &name);
core_device_t(core_device_t &owner, const pstring &name);
- COPYASSIGNMOVE(core_device_t, delete)
+ virtual ~core_device_t();
- virtual ~core_device_t() noexcept = default;
+ void update_dev() NL_NOEXCEPT
+ {
+ do_update();
+ }
void do_inc_active() NL_NOEXCEPT
{
if (m_hint_deactivate)
{
- if (++m_active_outputs == 1)
- {
- m_stat_inc_active.inc();
- inc_active();
- }
+ m_stat_inc_active.inc();
+ inc_active();
}
}
void do_dec_active() NL_NOEXCEPT
{
if (m_hint_deactivate)
- if (--m_active_outputs == 0)
- {
- dec_active();
- }
+ dec_active();
}
+ void do_reset() { reset(); }
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
bool get_hint_deactivate() { return m_hint_deactivate; }
- /* Has to be set in device reset */
- void set_active_outputs(int n) { m_active_outputs = n; }
void set_default_delegate(detail::core_terminal_t &term);
/* stats */
- nperftime_t<NL_KEEP_STATISTICS> m_stat_total_time;
- nperfcount_t<NL_KEEP_STATISTICS> m_stat_call_count;
- nperfcount_t<NL_KEEP_STATISTICS> m_stat_inc_active;
+ nperftime_t m_stat_total_time;
+ nperfcount_t m_stat_call_count;
+ nperfcount_t m_stat_inc_active;
- virtual void update() NL_NOEXCEPT { }
- virtual void reset() { }
protected:
+ virtual void update() NL_NOEXCEPT { }
virtual void inc_active() NL_NOEXCEPT { }
virtual void dec_active() NL_NOEXCEPT { }
+ virtual void reset() { }
- log_type & log();
+ void do_update() NL_NOEXCEPT
+ {
+ update();
+ }
+
+ plib::plog_base<netlist_t, NL_DEBUG> &log();
public:
- virtual void timestep(const nl_double st) { plib::unused_var(st); }
+ virtual void timestep(ATTR_UNUSED const nl_double st) { }
virtual void update_terminals() { }
virtual void update_param() {}
virtual bool is_dynamic() const { return false; }
virtual bool is_timestep() const { return false; }
+ virtual bool needs_update_after_param_change() const { return false; }
private:
- bool m_hint_deactivate;
- state_var_s32 m_active_outputs;
+ bool m_hint_deactivate;
};
// -----------------------------------------------------------------------------
@@ -1184,20 +1134,17 @@ namespace netlist
{
public:
- device_t(netlist_state_t &owner, const pstring &name);
+ device_t(netlist_t &owner, const pstring &name);
device_t(core_device_t &owner, const pstring &name);
- COPYASSIGNMOVE(device_t, delete)
-
- ~device_t() noexcept override = default;
+ virtual ~device_t() override;
setup_t &setup();
- const setup_t &setup() const;
template<class C, typename... Args>
- void create_and_register_subdevice(const pstring &name, pool_owned_ptr<C> &dev, Args&&... args)
+ void register_sub(const pstring &name, std::unique_ptr<C> &dev, const Args&... args)
{
- dev = pool().make_poolptr<C>(*this, name, std::forward<Args>(args)...);
+ dev.reset(plib::palloc<C>(*this, name, args...));
}
void register_subalias(const pstring &name, detail::core_terminal_t &term);
@@ -1220,18 +1167,13 @@ namespace netlist
struct detail::family_setter_t
{
- /* clang will complain about an unused private field if
- * a defaulted constructor is used
- */
- // NOLINTNEXTLINE(modernize-use-equals-default)
- family_setter_t();
+ family_setter_t() { }
family_setter_t(core_device_t &dev, const pstring &desc);
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
};
// -----------------------------------------------------------------------------
// nld_base_dummy : basis for dummy devices
- // FIXME: this is not the right place to define this
// -----------------------------------------------------------------------------
NETLIB_OBJECT(base_dummy)
@@ -1248,25 +1190,19 @@ namespace netlist
* solvers will update inputs after parallel processing.
*/
class detail::queue_t :
- public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
+ public timed_queue<pqentry_t<net_t *, netlist_time>, false>,
public detail::netlist_ref,
public plib::state_manager_t::callback_t
{
public:
- using entry_t = pqentry_t<net_t *, netlist_time>;
- explicit queue_t(netlist_state_t &nl);
- virtual ~queue_t() noexcept = default;
-
- queue_t(const queue_t &) = delete;
- queue_t(queue_t &&) = delete;
- queue_t &operator=(const queue_t &) = delete;
- queue_t &operator=(queue_t &&) = delete;
+ typedef pqentry_t<net_t *, netlist_time> entry_t;
+ explicit queue_t(netlist_t &nl);
protected:
void register_state(plib::state_manager_t &manager, const pstring &module) override;
- void on_pre_save(plib::state_manager_t &manager) override;
- void on_post_load(plib::state_manager_t &manager) override;
+ void on_pre_save() override;
+ void on_post_load() override;
private:
std::size_t m_qsize;
@@ -1275,214 +1211,139 @@ namespace netlist
};
// -----------------------------------------------------------------------------
- // netlist_state__t
+ // netlist_t
// -----------------------------------------------------------------------------
- class netlist_state_t
+
+ class netlist_t : private plib::nocopyassignmove
{
public:
- using nets_collection_type = std::vector<pool_owned_ptr<detail::net_t>>;
-
- /* need to preserve order of device creation ... */
- using devices_collection_type = std::vector<std::pair<pstring, pool_owned_ptr<core_device_t>>>;
- netlist_state_t(const pstring &aname,
- netlist_t & anetlist,
- plib::unique_ptr<callbacks_t> &&callbacks);
-
- COPYASSIGNMOVE(netlist_state_t, delete)
-
- ~netlist_state_t() noexcept = default;
-
- friend class netlist_t; // allow access to private members
+ explicit netlist_t(const pstring &aname);
+ virtual ~netlist_t();
- template<class C>
- static bool check_class(core_device_t *p)
- {
- return dynamic_cast<C *>(p) != nullptr;
- }
+ /* run functions */
- template<class C>
- C *get_single_device(const pstring &classname) const
- {
- return dynamic_cast<C *>(get_single_device(classname, check_class<C>));
- }
+ const netlist_time &time() const NL_NOEXCEPT { return m_time; }
+ devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; }
- /* logging and name */
+ /* never use this in constructors! */
+ nl_double gmin() const NL_NOEXCEPT;
- pstring name() const { return m_name; }
+ void process_queue(const netlist_time &delta) NL_NOEXCEPT;
+ void abort_current_queue_slice() NL_NOEXCEPT { m_queue.retime(detail::queue_t::entry_t(m_time, nullptr)); }
- log_type & log() { return m_log; }
- const log_type &log() const { return m_log; }
+ /* Control functions */
- plib::dynlib &lib() { return *m_lib; }
+ void start();
+ void stop();
+ void reset();
- netlist_t &exec() { return m_netlist; }
- const netlist_t &exec() const { return m_netlist; }
+ const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
+ detail::queue_t &queue() NL_NOEXCEPT { return m_queue; }
- /* state handling */
- plib::state_manager_t &run_state_manager() { return m_state; }
+ /* netlist build functions */
- template<typename O, typename C>
- void save(O &owner, C &state, const pstring &module, const pstring &stname)
- {
- this->run_state_manager().save_item(static_cast<void *>(&owner), state, module + pstring(".") + stname);
- }
- template<typename O, typename C>
- void save(O &owner, C *state, const pstring &module, const pstring &stname, const std::size_t count)
- {
- this->run_state_manager().save_state_ptr(static_cast<void *>(&owner), module + pstring(".") + stname, plib::state_manager_t::dtype<C>(), count, state);
- }
+ setup_t &setup() NL_NOEXCEPT { return *m_setup; }
- core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const;
+ void register_dev(plib::owned_ptr<core_device_t> dev);
+ void remove_dev(core_device_t *dev);
detail::net_t *find_net(const pstring &name) const;
std::size_t find_net_id(const detail::net_t *net) const;
- template <typename T>
- void register_net(pool_owned_ptr<T> &&net) { m_nets.push_back(std::move(net)); }
-
template<class device_class>
- inline std::vector<device_class *> get_device_list()
+ std::vector<device_class *> get_device_list() const
{
std::vector<device_class *> tmp;
for (auto &d : m_devices)
{
- auto dev = dynamic_cast<device_class *>(d.second.get());
+ device_class *dev = dynamic_cast<device_class *>(d.get());
if (dev != nullptr)
tmp.push_back(dev);
}
return tmp;
}
- template <typename T>
- void add_dev(const pstring &name, pool_owned_ptr<T> &&dev)
+ template<class C>
+ static bool check_class(core_device_t *p)
{
- for (auto & d : m_devices)
- if (d.first == name)
- log().fatal(MF_1_DUPLICATE_NAME_DEVICE_LIST, d.first);
- //m_devices.push_back(std::move(dev));
- m_devices.insert(m_devices.end(), { name, std::move(dev) });
+ return dynamic_cast<C *>(p) != nullptr;
}
- /**
- * @brief Remove device
- *
- * Care needs to be applied if this is called to remove devices with
- * sub-devices which may have registered state.
- *
- * @param dev Device to be removed
- */
- void remove_dev(core_device_t *dev)
+ template<class C>
+ C *get_single_device(const pstring &classname) const
{
- for (auto it = m_devices.begin(); it != m_devices.end(); it++)
- if (it->second.get() == dev)
- {
- m_state.remove_save_items(dev);
- m_devices.erase(it);
- return;
- }
+ return dynamic_cast<C *>(get_single_device(classname, check_class<C>));
}
- /* sole use is to manage lifetime of family objects */
- std::vector<std::pair<pstring, plib::unique_ptr<logic_family_desc_t>>> m_family_cache;
-
- setup_t &setup() NL_NOEXCEPT { return *m_setup; }
- const setup_t &setup() const NL_NOEXCEPT { return *m_setup; }
+ /* logging and name */
- nets_collection_type & nets() { return m_nets; }
- devices_collection_type & devices() { return m_devices; }
+ pstring name() const { return m_name; }
+ plib::plog_base<netlist_t, NL_DEBUG> &log() { return m_log; }
+ const plib::plog_base<netlist_t, NL_DEBUG> &log() const { return m_log; }
- // FIXME: make a postload member and include code there
- void rebuild_lists(); /* must be called after post_load ! */
+ /* state related */
- private:
+ plib::state_manager_t &state() { return m_state; }
- void reset();
+ template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
+ {
+ this->state().save_item(static_cast<void *>(&owner), state, from_utf8(owner.name()) + pstring(".") + stname);
+ }
+ template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
+ {
+ this->state().save_state_ptr(static_cast<void *>(&owner), from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
+ }
- pstring m_name;
- netlist_t &m_netlist;
- plib::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists
- plib::state_manager_t m_state;
- plib::unique_ptr<callbacks_t> m_callbacks;
- log_type m_log;
- plib::unique_ptr<setup_t> m_setup;
+ plib::dynlib &lib() { return *m_lib; }
- nets_collection_type m_nets;
+ // FIXME: find something better
/* sole use is to manage lifetime of net objects */
- devices_collection_type m_devices;
-
-
-
- };
-
- // -----------------------------------------------------------------------------
- // netlist_t
- // -----------------------------------------------------------------------------
-
- class netlist_t
- {
- public:
-
- explicit netlist_t(const pstring &aname, plib::unique_ptr<callbacks_t> callbacks);
-
- COPYASSIGNMOVE(netlist_t, delete)
-
- ~netlist_t() noexcept = default;
-
- /* run functions */
-
- netlist_time time() const NL_NOEXCEPT { return m_time; }
-
- void process_queue(const netlist_time delta) NL_NOEXCEPT;
- void abort_current_queue_slice() NL_NOEXCEPT { m_queue.retime(detail::queue_t::entry_t(m_time, nullptr)); }
-
- const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
- detail::queue_t &queue() NL_NOEXCEPT { return m_queue; }
+ std::vector<plib::owned_ptr<detail::net_t>> m_nets;
+ /* sole use is to manage lifetime of family objects */
+ std::vector<std::pair<pstring, std::unique_ptr<logic_family_desc_t>>> m_family_cache;
- /* Control functions */
+ // FIXME: sort rebuild_lists out
+ void rebuild_lists(); /* must be called after post_load ! */
- void stop();
- void reset();
+ /* logging callback */
+ virtual void vlog(const plib::plog_level &l, const pstring &ls) const = 0;
- /* state handling */
+ protected:
- plib::state_manager_t &run_state_manager() { return m_state->run_state_manager(); }
+ void print_stats() const;
- /* only used by nltool to create static c-code */
- devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; }
+ private:
- /* force late type resolution */
- template <typename X = devices::NETLIB_NAME(solver)>
- nl_double gmin(X *solv = nullptr) const NL_NOEXCEPT
- {
- plib::unused_var(solv);
- return static_cast<X *>(m_solver)->gmin();
- }
+ /* helper for save above */
+ static pstring from_utf8(const char *c) { return pstring(c, pstring::UTF8); }
+ static pstring from_utf8(const pstring &c) { return c; }
- netlist_state_t &nlstate() NL_NOEXCEPT { return *m_state; }
- const netlist_state_t &nlstate() const { return *m_state; }
+ core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const;
- log_type & log() { return m_state->log(); }
- const log_type &log() const { return m_state->log(); }
+ /* mostly rw */
+ netlist_time m_time;
+ detail::queue_t m_queue;
- void print_stats() const;
+ /* mostly ro */
- private:
- plib::unique_ptr<netlist_state_t> m_state;
- devices::NETLIB_NAME(solver) * m_solver;
+ devices::NETLIB_NAME(mainclock) * m_mainclock;
+ devices::NETLIB_NAME(solver) * m_solver;
+ devices::NETLIB_NAME(netlistparams) *m_params;
- /* mostly rw */
- PALIGNAS_CACHELINE()
- netlist_time m_time;
- devices::NETLIB_NAME(mainclock) * m_mainclock;
+ pstring m_name;
+ std::unique_ptr<setup_t> m_setup;
+ plib::plog_base<netlist_t, NL_DEBUG> m_log;
+ std::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists
- PALIGNAS_CACHELINE()
- detail::queue_t m_queue;
+ plib::state_manager_t m_state;
// performance
- nperftime_t<NL_KEEP_STATISTICS> m_stat_mainloop;
- nperfcount_t<NL_KEEP_STATISTICS> m_perf_out_processed;
+ nperftime_t m_stat_mainloop;
+ nperfcount_t m_perf_out_processed;
+
+ std::vector<plib::owned_ptr<core_device_t>> m_devices;
};
// -----------------------------------------------------------------------------
@@ -1495,13 +1356,12 @@ namespace netlist
public:
struct init
{
- std::array<const char *, N> p;
+ const char *p[N];
};
- template<typename... Args>
- object_array_t(core_device_t &dev, init names, Args&&... args)
+ object_array_t(core_device_t &dev, init names)
{
for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, pstring(names.p[i]), std::forward<Args>(args)...);
+ this->emplace(i, dev, pstring(names.p[i], pstring::UTF8));
}
};
@@ -1509,56 +1369,15 @@ namespace netlist
// inline implementations
// -----------------------------------------------------------------------------
- inline netlist_state_t & detail::netlist_ref::state() noexcept
- {
- return m_netlist.nlstate();
- }
-
- inline const netlist_state_t & detail::netlist_ref::state() const noexcept
- {
- return m_netlist.nlstate();
- }
-
- inline setup_t & detail::netlist_ref::setup() noexcept
- {
- return m_netlist.nlstate().setup();
- }
-
- inline const setup_t & detail::netlist_ref::setup() const noexcept
- {
- return m_netlist.nlstate().setup();
- }
-
- template <typename T>
- param_num_t<T>::param_num_t(device_t &device, const pstring &name, const T val)
- : param_t(device, name)
- {
- //m_param = device.setup().get_initial_param_val(this->name(),val);
- bool found = false;
- pstring p = this->get_initial(device, &found);
- if (found)
- {
- bool err = false;
- auto vald = plib::pstonum_ne<T>(p, err);
- if (err)
- device.state().log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, p);
- m_param = vald;
- }
- else
- m_param = val;
-
- device.state().save(*this, m_param, this->name(), "m_param");
- }
-
template <typename ST, std::size_t AW, std::size_t DW>
- param_rom_t<ST, AW, DW>::param_rom_t(device_t &device, const pstring &name)
+ inline param_rom_t<ST, AW, DW>::param_rom_t(device_t &device, const pstring &name)
: param_data_t(device, name)
{
auto f = stream();
if (f != nullptr)
- f->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW);
+ f->read(&m_data[0],1<<AW);
else
- device.state().log().warning("Rom {1} not found", value());
+ device.netlist().log().warning("Rom {1} not found", Value());
}
inline void logic_input_t::inactivate() NL_NOEXCEPT
@@ -1566,7 +1385,7 @@ namespace netlist
if (!is_state(STATE_INP_PASSIVE))
{
set_state(STATE_INP_PASSIVE);
- net().remove_from_active_list(*this);
+ net().dec_active(*this);
}
}
@@ -1574,7 +1393,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().add_to_active_list(*this);
+ net().inc_active(*this);
set_state(STATE_INP_ACTIVE);
}
}
@@ -1583,7 +1402,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().add_to_active_list(*this);
+ net().inc_active(*this);
set_state(STATE_INP_HL);
}
}
@@ -1592,68 +1411,24 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().add_to_active_list(*this);
+ net().inc_active(*this);
set_state(STATE_INP_LH);
}
}
- inline void detail::net_t::push_to_queue(const netlist_time delay) NL_NOEXCEPT
+ inline void detail::net_t::push_to_queue(const netlist_time &delay) NL_NOEXCEPT
{
if ((num_cons() != 0))
{
- auto &lexec(exec());
- auto &q(lexec.queue());
- auto nst(lexec.time() + delay);
-
if (is_queued())
- q.remove(this);
- m_in_queue = (!m_list_active.empty()) ?
- queue_status::QUEUED : queue_status::DELAYED_DUE_TO_INACTIVE; /* queued ? */
- if (m_in_queue == queue_status::QUEUED)
- q.push(queue_t::entry_t(nst, this));
- else
- update_inputs();
- m_next_scheduled_time = nst;
- }
- }
-
- inline void detail::net_t::add_to_active_list(core_terminal_t &term) NL_NOEXCEPT
- {
- if (m_list_active.empty())
- {
- m_list_active.push_front(&term);
- railterminal().device().do_inc_active();
- if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE)
- {
- if (m_next_scheduled_time > exec().time())
- {
- m_in_queue = queue_status::QUEUED; /* pending */
- exec().queue().push({m_next_scheduled_time, this});
- }
- else
- {
- m_in_queue = queue_status::DELIVERED;
- m_cur_Q = m_new_Q;
- }
- update_inputs();
- }
- else
- term.set_copied_input(m_cur_Q);
- }
- else
- {
- term.set_copied_input(m_cur_Q);
- m_list_active.push_front(&term);
+ netlist().queue().remove(this);
+ m_time = netlist().time() + delay;
+ m_in_queue = (m_active > 0) ? QS_QUEUED : QS_DELAYED_DUE_TO_INACTIVE; /* queued ? */
+ if (m_in_queue == QS_QUEUED)
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
}
- inline void detail::net_t::remove_from_active_list(core_terminal_t &term) NL_NOEXCEPT
- {
- m_list_active.remove(&term);
- if (m_list_active.empty())
- railterminal().device().do_dec_active();
- }
-
inline const analog_net_t & analog_t::net() const NL_NOEXCEPT
{
return static_cast<const analog_net_t &>(core_terminal_t::net());
@@ -1666,18 +1441,6 @@ namespace netlist
inline nl_double terminal_t::operator ()() const NL_NOEXCEPT { return net().Q_Analog(); }
- inline void terminal_t::set_ptrs(nl_double *gt, nl_double *go, nl_double *Idr) noexcept
- {
- if (!(gt && go && Idr) && (gt || go || Idr))
- state().log().fatal("Inconsistent nullptrs for terminal {}", name());
- else
- {
- m_gt1 = gt;
- m_go1 = go;
- m_Idr1 = Idr;
- }
- }
-
inline logic_net_t & logic_t::net() NL_NOEXCEPT
{
return static_cast<logic_net_t &>(core_terminal_t::net());
@@ -1690,14 +1453,8 @@ namespace netlist
inline netlist_sig_t logic_input_t::Q() const NL_NOEXCEPT
{
- nl_assert(terminal_state() != STATE_INP_PASSIVE);
- //if (net().Q() != m_Q)
- // printf("term: %s, %d %d TS %d\n", this->name().c_str(), net().Q(), m_Q, terminal_state());
-#if USE_COPY_INSTEAD_OF_REFERENCE
- return m_Q;
-#else
+ nl_assert(state() != STATE_INP_PASSIVE);
return net().Q();
-#endif
}
inline nl_double analog_input_t::Q_Analog() const NL_NOEXCEPT
@@ -1714,24 +1471,14 @@ namespace netlist
}
}
- inline netlist_state_t &detail::device_object_t::state() NL_NOEXCEPT
- {
- return m_device.state();
- }
-
- inline const netlist_state_t &detail::device_object_t::state() const NL_NOEXCEPT
- {
- return m_device.state();
- }
-
- inline netlist_t &detail::device_object_t::exec() NL_NOEXCEPT
+ inline netlist_t &detail::device_object_t::netlist() NL_NOEXCEPT
{
- return m_device.exec();
+ return m_device.netlist();
}
- inline const netlist_t &detail::device_object_t::exec() const NL_NOEXCEPT
+ inline const netlist_t &detail::device_object_t::netlist() const NL_NOEXCEPT
{
- return m_device.exec();
+ return m_device.netlist();
}
template <typename T>
@@ -1739,18 +1486,18 @@ namespace netlist
state_var<T>::state_var(O &owner, const pstring &name, const T &value)
: m_value(value)
{
- owner.state().save(owner, m_value, owner.name(), name);
+ owner.netlist().save(owner, m_value, name);
}
template <typename T, std::size_t N>
template <typename O>
- state_array<T,N>::state_array(O &owner, const pstring &name, const T & value)
+ state_var<T[N]>::state_var(O &owner, const pstring &name, const T & value)
{
- owner.state().save(owner, m_value, owner.name(), name);
+ owner.netlist().save(owner, m_value, name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
}
-} // namespace netlist
+}
namespace plib
{
@@ -1758,7 +1505,7 @@ namespace plib
struct ptype_traits<netlist::state_var<X>> : ptype_traits<X>
{
};
-} // namespace plib
+}
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index faa5008ff56..6a65abac40a 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -26,21 +26,10 @@
* linear memory pool. This is based of the assumption that
* due to enhanced locality there will be less cache misses.
* Your mileage may vary.
+ * This will cause crashes on OSX and thus is ignored on OSX.
*
*/
-#define USE_MEMPOOL (1)
-
-/*! Store input values in logic_terminal_t.
- *
- * Set to 1 to store values in logic_terminal_t instead of
- * accessing them indirectly by pointer from logic_net_t.
- * This approach is stricter and should identify bugs in
- * the netlist core faster.
- * By default it is disabled since it is not as fast as
- * the default approach. It is up to 5% slower.
- *
- */
-#define USE_COPY_INSTEAD_OF_REFERENCE (0)
+#define USE_MEMPOOL (0)
/*
* FIXME: Using truthtable is a lot slower than the explicit device
@@ -54,13 +43,23 @@
#define NL_MAX_LINK_RESOLVE_LOOPS (100)
//============================================================
+// Solver defines
+//============================================================
+
+#define USE_GABS (1)
+// savings are eaten up by effort
+// FIXME: Convert into solver parameter
+#define USE_LINEAR_PREDICTION (0)
+#define NETLIST_GMIN_DEFAULT (1e-9)
+
+
+
+//============================================================
// DEBUGGING
//============================================================
#define NL_DEBUG (false)
#define NL_KEEP_STATISTICS (0)
-//#define NL_DEBUG (true)
-//#define NL_KEEP_STATISTICS (1)
//============================================================
// General Macros
@@ -87,19 +86,24 @@
#endif // !defined(USE_OPENMP)
// Use nano-second resolution - Sufficient for now
-
-static constexpr const auto NETLIST_INTERNAL_RES = 1000000000;
-static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES;
-
-//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000))
-//#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
+#define NETLIST_INTERNAL_RES (UINT64_C(1000000000))
+#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000000))
//#define NETLIST_CLOCK (UINT64_C(1000000000))
//#define nl_double float
+//#define NL_FCONST(x) (x ## f)
+
+//#define nl_double double
+#define NL_FCONST(x) x
using nl_double = double;
+/* The following option determines how object::update is called.
+ * If set to 1, a virtual call is used. If it is left undefined, the best
+ * approach will be automatically selected.
+ */
+
//============================================================
// WARNINGS
//============================================================
diff --git a/src/lib/netlist/nl_dice_compat.h b/src/lib/netlist/nl_dice_compat.h
index 48695e393ec..b0ebdb2e371 100644
--- a/src/lib/netlist/nl_dice_compat.h
+++ b/src/lib/netlist/nl_dice_compat.h
@@ -29,7 +29,6 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
#include "analog/nld_twoterm.h"
#include <cmath>
-
#endif
@@ -112,8 +111,8 @@ public:
#define CHIP(n, t) TTL_ ## t ## _DIP(n)
#define OHM(x) x
-#define K_OHM(x) RES_K(x)
-#define M_OHM(x) RES_M(x)
+#define K_OHM(x) RES_K(X)
+#define M_OHM(x) RES_M(X)
#define U_FARAD(x) CAP_U(x)
#define N_FARAD(x) CAP_N(x)
#define P_FARAD(x) CAP_P(x)
@@ -132,9 +131,9 @@ public:
NET_C(name.6, name ## _R.1) \
NET_C(name.6, name ## _C.1) \
NET_C(name ## _R.2, V5) \
- NET_C(name ## _C.2, GND) \
+ NET_CSTR(# name "_C.2", "GND") \
NET_C(name.8, V5) \
- NET_C(name.1, GND)
+ NET_CSTR(# name ".1", "GND")
#define CHIP_555_Astable(name, pdesc) \
NE555_DIP(name) \
@@ -147,9 +146,9 @@ public:
NET_C(name.6, name ## _C.1) \
NET_C(name.2, name ## _C.1) \
NET_C(name ## _R1.2, V5) \
- NET_C(name ## _C.2, GND) \
+ NET_CSTR(# name "_C.2", "GND") \
NET_C(name.8, V5) \
- NET_C(name.1, GND)
+ NET_CSTR(# name ".1", "GND")
#define CHIP_9602_Mono(name, pdesc) \
CHIP(# name, 9602) \
@@ -179,13 +178,13 @@ public:
#define CHIP_INPUT_ACTIVE_LOW(name) \
SWITCH2(name ## _SW) \
NET_C(name ## _SW.1, V5) \
- NET_C(name ## _SW.2, GND) \
+ NET_CSTR(# name "_SW.2", "GND") \
ALIAS(name.1, name ## _SW.Q)
#define CHIP_INPUT_ACTIVE_HIGH(name) \
SWITCH2(name ## _SW) \
NET_C(name ## _SW.2, V5) \
- NET_C(name ## _SW.1, GND) \
+ NET_CSTR(# name "_SW.1", "GND") \
ALIAS(name.1, name ## _SW.Q)
#define CHIP_LATCH(name) \
diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h
index ee3c47f3339..35b1e4f6c60 100644
--- a/src/lib/netlist/nl_errstr.h
+++ b/src/lib/netlist/nl_errstr.h
@@ -58,8 +58,7 @@
//#define MF_1_CLASS_1_NOT_FOUND "Class {1} not found!"
#define MF_1_UNABLE_TO_PARSE_MODEL_1 "Unable to parse model: {1}"
#define MF_1_MODEL_ALREADY_EXISTS_1 "Model already exists: {1}"
-#define MF_1_DEVICE_ALREADY_EXISTS_1 "Device already exists: {1}"
-#define MF_1_ADDING_ALI1_TO_ALIAS_LIST "Error adding alias {1} to alias list"
+#define MF_1_ADDING_ALI1_TO_ALIAS_LIST "Error adding alias {1} to alias list"
#define MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1 "You must pass an equal number of pins to DIPPINS {1}"
#define MF_1_UNKNOWN_OBJECT_TYPE_1 "Unknown object type {1}"
#define MF_2_INVALID_NUMBER_CONVERSION_1_2 "Invalid number conversion {1} : {2}"
diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp
index 1f0ac35c6c4..2bb49590c4b 100644
--- a/src/lib/netlist/nl_factory.cpp
+++ b/src/lib/netlist/nl_factory.cpp
@@ -10,84 +10,102 @@
#include "nl_factory.h"
#include "nl_base.h"
-#include "nl_errstr.h"
#include "nl_setup.h"
#include "plib/putil.h"
+#include "nl_errstr.h"
namespace netlist { namespace factory
{
- class NETLIB_NAME(wrapper) : public device_t
- {
- public:
- NETLIB_NAME(wrapper)(netlist_state_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
- {
- }
- protected:
- NETLIB_RESETI() { }
- NETLIB_UPDATEI() { }
- };
-
- element_t::element_t(const pstring &name, const pstring &classname,
- const pstring &def_param, const pstring &sourcefile)
- : m_name(name), m_classname(classname), m_def_param(def_param),
- m_sourcefile(sourcefile)
+class NETLIB_NAME(wrapper) : public device_t
+{
+public:
+ NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
+ : device_t(anetlist, name)
{
}
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+};
- element_t::element_t(const pstring &name, const pstring &classname,
- const pstring &def_param)
- : m_name(name), m_classname(classname), m_def_param(def_param),
- m_sourcefile("<unknown>")
- {
- }
- // ----------------------------------------------------------------------------------------
- // net_device_t_base_factory
- // ----------------------------------------------------------------------------------------
- list_t::list_t(log_type &alog)
- : m_log(alog)
- {
- }
+element_t::element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile)
+ : m_name(name), m_classname(classname), m_def_param(def_param),
+ m_sourcefile(sourcefile)
+{
+}
- void list_t::register_device(plib::unique_ptr<element_t> &&factory)
- {
- for (auto & e : *this)
- if (e->name() == factory->name())
- m_log.fatal(MF_1_FACTORY_ALREADY_CONTAINS_1, factory->name());
- push_back(std::move(factory));
- }
+element_t::element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param)
+ : m_name(name), m_classname(classname), m_def_param(def_param),
+ m_sourcefile("<unknown>")
+{
+}
- factory::element_t * list_t::factory_by_name(const pstring &devname)
- {
- for (auto & e : *this)
- {
- if (e->name() == devname)
- return e.get();
- }
-
- m_log.fatal(MF_1_CLASS_1_NOT_FOUND, devname);
- return nullptr; // appease code analysis
- }
+element_t::~element_t()
+{
+}
- // -----------------------------------------------------------------------------
- // factory_lib_entry_t: factory class to wrap macro based chips/elements
- // -----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// net_device_t_base_factory
+// ----------------------------------------------------------------------------------------
- pool_owned_ptr<device_t> library_element_t::Create(netlist_state_t &anetlist, const pstring &name)
- {
- return pool().make_poolptr<NETLIB_NAME(wrapper)>(anetlist, name);
- }
+list_t::list_t( setup_t &setup)
+: m_setup(setup)
+{
+}
+
+list_t::~list_t()
+{
+ clear();
+}
+
+void list_t::register_device(std::unique_ptr<element_t> &&factory)
+{
+ for (auto & e : *this)
+ if (e->name() == factory->name())
+ m_setup.log().fatal(MF_1_FACTORY_ALREADY_CONTAINS_1, factory->name());
+ push_back(std::move(factory));
+}
- void library_element_t::macro_actions(nlparse_t &nparser, const pstring &name)
+factory::element_t * list_t::factory_by_name(const pstring &devname)
+{
+ for (auto & e : *this)
{
- nparser.namespace_push(name);
- nparser.include(this->name());
- nparser.namespace_pop();
+ if (e->name() == devname)
+ return e.get();
}
+ m_setup.log().fatal(MF_1_CLASS_1_NOT_FOUND, devname);
+ return nullptr; // appease code analysis
+}
+
+// -----------------------------------------------------------------------------
+// factory_lib_entry_t: factory class to wrap macro based chips/elements
+// -----------------------------------------------------------------------------
+
+plib::owned_ptr<device_t> library_element_t::Create(netlist_t &anetlist, const pstring &name)
+{
+ return plib::owned_ptr<device_t>::Create<NETLIB_NAME(wrapper)>(anetlist, name);
+}
+
+void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name)
+{
+ anetlist.setup().namespace_push(name);
+ anetlist.setup().include(this->name());
+ anetlist.setup().namespace_pop();
+}
+
+NETLIB_RESET(wrapper)
+{
+}
+
+NETLIB_UPDATE(wrapper)
+{
+}
+
-} // namespace factory
- } // namespace netlist
+} }
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 271bf72bf90..6dad6c5e171 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -9,58 +9,46 @@
#ifndef NLFACTORY_H_
#define NLFACTORY_H_
-#include "nltypes.h"
#include "plib/palloc.h"
#include "plib/ptypes.h"
-#include <vector>
-
-#define NETLIB_DEVICE_IMPL_ALIAS(p_alias, chip, p_name, p_def_param) \
- NETLIB_DEVICE_IMPL_BASE(devices, p_alias, chip, p_name, p_def_param) \
-
-#define NETLIB_DEVICE_IMPL(chip, p_name, p_def_param) \
- NETLIB_DEVICE_IMPL_NS(devices, chip, p_name, p_def_param)
-
-#define NETLIB_DEVICE_IMPL_NS(ns, chip, p_name, p_def_param) \
- NETLIB_DEVICE_IMPL_BASE(ns, chip, chip, p_name, p_def_param) \
+#define NETLIB_DEVICE_IMPL(chip) \
+ static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
+ const pstring &name, const pstring &classname, const pstring &def_param) \
+ { \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
+ } \
+ factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
-#define NETLIB_DEVICE_IMPL_BASE(ns, p_alias, chip, p_name, p_def_param) \
- static plib::unique_ptr<factory::element_t> NETLIB_NAME(p_alias ## _c) \
- (const pstring &classname) \
+#define NETLIB_DEVICE_IMPL_NS(ns, chip) \
+ static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
+ const pstring &name, const pstring &classname, const pstring &def_param) \
{ \
- return plib::make_unique<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(p_name, classname, p_def_param, pstring(__FILE__)); \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
} \
- \
- factory::constructor_ptr_t decl_ ## p_alias = NETLIB_NAME(p_alias ## _c);
+ factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
namespace netlist {
+ class netlist_t;
class device_t;
- class nlparse_t;
class setup_t;
- class netlist_state_t;
namespace factory {
// -----------------------------------------------------------------------------
// net_dev class factory
// -----------------------------------------------------------------------------
- class element_t
+ class element_t : plib::nocopyassignmove
{
public:
element_t(const pstring &name, const pstring &classname,
const pstring &def_param);
element_t(const pstring &name, const pstring &classname,
const pstring &def_param, const pstring &sourcefile);
- virtual ~element_t() = default;
+ virtual ~element_t();
- COPYASSIGNMOVE(element_t, default)
-
- virtual pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) = 0;
- virtual void macro_actions(nlparse_t &nparser, const pstring &name)
- {
- plib::unused_var(nparser);
- plib::unused_var(name);
- }
+ virtual plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) = 0;
+ virtual void macro_actions(netlist_t &anetlist, const pstring &name) {}
const pstring &name() const { return m_name; }
const pstring &classname() const { return m_classname; }
@@ -85,28 +73,26 @@ namespace factory {
const pstring &def_param, const pstring &sourcefile)
: element_t(name, classname, def_param, sourcefile) { }
- pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override
+ plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
- return pool().make_poolptr<C>(anetlist, name);
+ return plib::owned_ptr<device_t>::Create<C>(anetlist, name);
}
};
- class list_t : public std::vector<plib::unique_ptr<element_t>>
+ class list_t : public std::vector<std::unique_ptr<element_t>>
{
public:
- explicit list_t(log_type &alog);
- ~list_t() = default;
-
- COPYASSIGNMOVE(list_t, delete)
+ explicit list_t(setup_t &m_setup);
+ ~list_t();
template<class device_class>
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(plib::make_unique<device_element_t<device_class>>(name, classname, def_param));
+ register_device(std::unique_ptr<element_t>(plib::palloc<device_element_t<device_class>>(name, classname, def_param)));
}
- void register_device(plib::unique_ptr<element_t> &&factory);
+ void register_device(std::unique_ptr<element_t> &&factory);
element_t * factory_by_name(const pstring &devname);
@@ -117,20 +103,21 @@ namespace factory {
}
private:
- log_type &m_log;
+ setup_t &m_setup;
};
// -----------------------------------------------------------------------------
// factory_creator_ptr_t
// -----------------------------------------------------------------------------
- using constructor_ptr_t = plib::unique_ptr<element_t> (*)(const pstring &classname);
+ using constructor_ptr_t = std::unique_ptr<element_t> (*)(const pstring &name, const pstring &classname,
+ const pstring &def_param);
template <typename T>
- plib::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
+ std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return plib::make_unique<device_element_t<T>>(name, classname, def_param);
+ return std::unique_ptr<element_t>(plib::palloc<device_element_t<T>>(name, classname, def_param));
}
// -----------------------------------------------------------------------------
@@ -141,24 +128,22 @@ namespace factory {
{
public:
- library_element_t(const pstring &name, const pstring &classname,
+ library_element_t(setup_t &setup, const pstring &name, const pstring &classname,
const pstring &def_param, const pstring &source)
- : element_t(name, classname, def_param, source)
- {
- }
+ : element_t(name, classname, def_param, source) { }
- pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override;
+ plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override;
- void macro_actions(nlparse_t &nparser, const pstring &name) override;
+ void macro_actions(netlist_t &anetlist, const pstring &name) override;
private:
};
- } // namespace factory
+ }
namespace devices {
void initialize_factory(factory::list_t &factory);
- } // namespace devices
-} // namespace netlist
+ }
+}
#endif /* NLFACTORY_H_ */
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index 325f8a67c72..1eae38b25fb 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -10,24 +10,32 @@
#ifndef NLLISTS_H_
#define NLLISTS_H_
-#include "plib/pchrono.h"
+#include "nl_config.h"
+#include "netlist_types.h"
#include "plib/plists.h"
+#include "plib/pchrono.h"
#include "plib/ptypes.h"
-#include "nl_config.h"
-#include "nltypes.h"
-
-#include <algorithm>
#include <atomic>
-#include <mutex>
#include <thread>
+#include <mutex>
+#include <algorithm>
#include <utility>
-
// ----------------------------------------------------------------------------------------
// timed queue
// ----------------------------------------------------------------------------------------
+/*
+ * Use -DUSE_HEAP=1 to use stdc++ heap functions instead of linear processing.
+ *
+ * This slows down processing by about 25% on a Kaby Lake.
+ */
+
+#ifndef USE_HEAP
+#define USE_HEAP (0)
+#endif
+
namespace netlist
{
//FIXME: move to an appropriate place
@@ -35,11 +43,10 @@ namespace netlist
class pspin_mutex
{
public:
- pspin_mutex() noexcept = default;
+ pspin_mutex() noexcept { }
void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
void unlock() noexcept { m_lock.clear(std::memory_order_release); }
private:
- PALIGNAS_CACHELINE()
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
@@ -55,11 +62,10 @@ namespace netlist
struct pqentry_t final
{
constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { }
- constexpr pqentry_t(const Time t, const Element o) noexcept : m_exec_time(t), m_object(o) { }
-#if 0
+ constexpr pqentry_t(const Time &t, const Element &o) noexcept : m_exec_time(t), m_object(o) { }
~pqentry_t() = default;
constexpr pqentry_t(const pqentry_t &e) noexcept = default;
- constexpr pqentry_t(pqentry_t &&e) noexcept = default;
+ constexpr pqentry_t(pqentry_t &&e) = default;
pqentry_t& operator=(pqentry_t && other) noexcept = default;
pqentry_t& operator=(const pqentry_t &other) noexcept = default;
@@ -68,97 +74,91 @@ namespace netlist
std::swap(m_exec_time, other.m_exec_time);
std::swap(m_object, other.m_object);
}
-#endif
+
struct QueueOp
{
- inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
+ static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time < rhs.m_exec_time);
}
- inline static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
- {
- return (lhs.m_exec_time <= rhs.m_exec_time);
- }
-
- inline static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
+ static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return lhs.m_object == rhs.m_object;
}
- inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
+ static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
{
return lhs.m_object == rhs;
}
- inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
+ static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
};
Time m_exec_time;
Element m_object;
};
+#if !USE_HEAP
/* Use TS = true for a threadsafe queue */
- template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
- class timed_queue_linear : plib::nocopyassignmove
+ template <class T, bool TS, class QueueOp = typename T::QueueOp>
+ class timed_queue : plib::nocopyassignmove
{
public:
- explicit timed_queue_linear(const std::size_t list_size)
+ explicit timed_queue(const std::size_t list_size)
: m_list(list_size)
{
clear();
}
- std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
- bool empty() const noexcept { return (m_end == &m_list[1]); }
+ constexpr std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
+ constexpr bool empty() const noexcept { return (m_end == &m_list[1]); }
- void push(T && e) noexcept
+ void push(T &&e) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
- T * i(m_end-1);
- for (; QueueOp::less(*(i), e); --i)
+ tqlock lck(m_lock);
+ T * i(m_end);
+ for (; QueueOp::less(*(i - 1), e); --i)
{
- *(i+1) = *(i);
+ *(i) = std::move(*(i-1));
m_prof_sortmove.inc();
}
- *(i+1) = std::move(e);
+ *i = std::move(e);
++m_end;
m_prof_call.inc();
}
- T pop() noexcept { return *(--m_end); }
+ void pop() noexcept { --m_end; }
const T &top() const noexcept { return *(m_end-1); }
template <class R>
void remove(const R &elem) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
- m_prof_remove.inc();
-
+ tqlock lck(m_lock);
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem))
{
- std::copy(i+1, m_end--, i);
+ --m_end;
+ for (;i < m_end; ++i)
+ *i = std::move(*(i+1));
return;
}
}
}
- void retime(T && elem) noexcept
+ void retime(const T &elem) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
- m_prof_retime.inc();
-
+ tqlock lck(m_lock);
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem)) // partial equal!
{
- *i = std::move(elem);
+ *i = elem;
while (QueueOp::less(*(i-1), *i))
{
std::swap(*(i-1), *i);
@@ -174,9 +174,9 @@ namespace netlist
}
}
- void clear() noexcept
+ void clear()
{
- lock_guard_type lck(m_lock);
+ tqlock lck(m_lock);
m_end = &m_list[0];
/* put an empty element with maximum time into the queue.
* the insert algo above will run into this element and doesn't
@@ -188,61 +188,55 @@ namespace netlist
// save state support & mame disasm
- const T *listptr() const noexcept { return &m_list[1]; }
- std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); }
- const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; }
+ constexpr const T *listptr() const noexcept { return &m_list[1]; }
+ constexpr std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); }
+ constexpr const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; }
private:
- using mutex_type = pspin_mutex<TS>;
- using lock_guard_type = std::lock_guard<mutex_type>;
+ using tqmutex = pspin_mutex<TS>;
+ using tqlock = std::lock_guard<tqmutex>;
- mutex_type m_lock;
- PALIGNAS_CACHELINE()
- T * m_end;
- //std::vector<T> m_list;
- plib::aligned_vector<T> m_list;
+ tqmutex m_lock;
+ T * m_end;
+ std::vector<T> m_list;
public:
// profiling
- nperfcount_t<KEEPSTAT> m_prof_sortmove;
- nperfcount_t<KEEPSTAT> m_prof_call;
- nperfcount_t<KEEPSTAT> m_prof_remove;
- nperfcount_t<KEEPSTAT> m_prof_retime;
+ nperfcount_t m_prof_sortmove;
+ nperfcount_t m_prof_call;
};
-
- template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
- class timed_queue_heap : plib::nocopyassignmove
+#else
+ template <class T, bool TS, class QueueOp = typename T::QueueOp>
+ class timed_queue : plib::nocopyassignmove
{
public:
struct compare
{
- constexpr bool operator()(const T &a, const T &b) const { return QueueOp::lessequal(b,a); }
+ constexpr bool operator()(const T &a, const T &b) const { return QueueOp::less(b,a); }
};
- explicit timed_queue_heap(const std::size_t list_size)
+ explicit timed_queue(const std::size_t list_size)
: m_list(list_size)
{
clear();
}
- std::size_t capacity() const noexcept { return m_list.capacity(); }
- bool empty() const noexcept { return &m_list[0] == m_end; }
+ constexpr std::size_t capacity() const noexcept { return m_list.capacity(); }
+ constexpr bool empty() const noexcept { return &m_list[0] == m_end; }
void push(T &&e) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
+ tqlock lck(m_lock);
*m_end++ = e;
std::push_heap(&m_list[0], m_end, compare());
m_prof_call.inc();
}
- T pop() noexcept
+ void pop() noexcept
{
- T ret(m_list[0]);
std::pop_heap(&m_list[0], m_end, compare());
m_end--;
- return ret;
}
const T &top() const noexcept { return m_list[0]; }
@@ -251,7 +245,7 @@ namespace netlist
void remove(const R &elem) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
+ tqlock lck(m_lock);
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem))
@@ -268,7 +262,7 @@ namespace netlist
void retime(const T &elem) noexcept
{
/* Lock */
- lock_guard_type lck(m_lock);
+ tqlock lck(m_lock);
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem)) // partial equal!
@@ -282,7 +276,7 @@ namespace netlist
void clear()
{
- lock_guard_type lck(m_lock);
+ tqlock lck(m_lock);
m_list.clear();
m_end = &m_list[0];
}
@@ -293,28 +287,19 @@ namespace netlist
constexpr std::size_t size() const noexcept { return m_list.size(); }
constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; }
private:
- using mutex_type = pspin_mutex<TS>;
- using lock_guard_type = std::lock_guard<mutex_type>;
+ using tqmutex = pspin_mutex<TS>;
+ using tqlock = std::lock_guard<tqmutex>;
- mutex_type m_lock;
+ tqmutex m_lock;
std::vector<T> m_list;
T *m_end;
public:
// profiling
- nperfcount_t<KEEPSTAT> m_prof_sortmove;
- nperfcount_t<KEEPSTAT> m_prof_call;
+ nperfcount_t m_prof_sortmove;
+ nperfcount_t m_prof_call;
};
-
- /*
- * Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
- *
- * This slows down processing by about 25% on a Kaby Lake.
- */
-
- template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
- using timed_queue = timed_queue_linear<T, TS, KEEPSTAT, QueueOp>;
-
-} // namespace netlist
+#endif
+}
#endif /* NLLISTS_H_ */
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index cecfbe862bf..4685a13c354 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -6,9 +6,9 @@
*/
#include "nl_parser.h"
-#include "nl_base.h"
-#include "nl_errstr.h"
#include "nl_factory.h"
+#include "nl_errstr.h"
+#include "nl_base.h"
namespace netlist
{
@@ -24,13 +24,13 @@ void parser_t::verror(const pstring &msg, int line_num, const pstring &line)
//throw error;
}
+
bool parser_t::parse(const pstring &nlname)
{
- this->identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-")
- .number_chars(".0123456789", "0123456789eE-.") //FIXME: processing of numbers
- //set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
- .whitespace(pstring("") + ' ' + static_cast<char>(9) + static_cast<char>(10) + static_cast<char>(13))
- .comment("/*", "*/", "//");
+ set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
+ set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
+ set_comment("/*", "*/", "//");
m_tok_param_left = register_token("(");
m_tok_param_right = register_token(")");
m_tok_comma = register_token(",");
@@ -357,10 +357,10 @@ void parser_t::device(const pstring &dev_type)
m_setup.register_dev(dev_type, devname);
m_setup.log().debug("Parser: IC: {1}\n", devname);
- for (const pstring &tp : paramlist)
+ for (pstring tp : paramlist)
{
require_token(m_tok_comma);
- if (plib::startsWith(tp, "+"))
+ if (tp.startsWith("+"))
{
pstring output_name = get_identifier();
m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
@@ -395,15 +395,18 @@ void parser_t::device(const pstring &dev_type)
// ----------------------------------------------------------------------------------------
-nl_double parser_t::eval_param(const token_t &tok)
+nl_double parser_t::eval_param(const token_t tok)
{
- static std::array<pstring, 6> macs = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
- static std::array<nl_double, 6> facs = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
- std::size_t f=0;
+ static pstring macs[6] = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
+ static nl_double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
+ int i;
+ int f=0;
+ bool e;
nl_double ret;
+ pstring val;
- for (std::size_t i=1; i<macs.size();i++)
- if (tok.str() == macs[i])
+ for (i=1; i<6;i++)
+ if (tok.str().equals(macs[i]))
f = i;
if (f>0)
{
@@ -413,13 +416,13 @@ nl_double parser_t::eval_param(const token_t &tok)
}
else
{
- bool err;
- ret = plib::pstonum_ne<nl_double>(tok.str(), err);
- if (err)
- error(plib::pfmt("Parameter value <{1}> not double \n")(tok.str()));
+ val = tok.str();
+ ret = val.as_double(&e);
+ if (e)
+ error(plib::pfmt("Parameter value <{1}> not double \n")(val));
}
return ret * facs[f];
}
-} // namespace netlist
+}
diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h
index 92459c4b87b..a813629faa0 100644
--- a/src/lib/netlist/nl_parser.h
+++ b/src/lib/netlist/nl_parser.h
@@ -16,12 +16,8 @@ namespace netlist
class parser_t : public plib::ptokenizer
{
public:
- template <typename T>
- parser_t(T &&strm, nlparse_t &setup)
- : plib::ptokenizer(std::forward<T>(strm))
- , m_setup(setup)
- {
- }
+ parser_t(plib::putf8_reader &strm, setup_t &setup)
+ : plib::ptokenizer(strm), m_setup(setup) {}
bool parse(const pstring &nlname = "");
@@ -43,12 +39,12 @@ namespace netlist
void net_truthtable_start(const pstring &nlname);
/* for debugging messages */
- //netlist_state_t &netlist() { return m_setup.netlist(); }
+ netlist_t &netlist() { return m_setup.netlist(); }
- void verror(const pstring &msg, int line_num, const pstring &line) override;
+ virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
private:
- nl_double eval_param(const token_t &tok);
+ nl_double eval_param(const token_t tok);
token_id_t m_tok_param_left;
token_id_t m_tok_param_right;
@@ -72,9 +68,9 @@ namespace netlist
token_id_t m_tok_TT_LINE;
token_id_t m_tok_TT_FAMILY;
- nlparse_t &m_setup;
+ setup_t &m_setup;
};
-} // namespace netlist
+}
#endif /* NL_PARSER_H_ */
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index b9300f5ad9c..df761bc3f88 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -6,243 +6,128 @@
*/
#include "plib/palloc.h"
-#include "analog/nld_twoterm.h"
-#include "devices/nlid_proxy.h"
-#include "devices/nlid_system.h"
-#include "devices/nlid_truthtable.h"
+#include "plib/putil.h"
#include "nl_base.h"
-#include "nl_factory.h"
-#include "nl_parser.h"
#include "nl_setup.h"
-#include "plib/putil.h"
+#include "nl_parser.h"
+#include "nl_factory.h"
+#include "devices/nlid_system.h"
+#include "devices/nlid_proxy.h"
+#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"
+#include "devices/nlid_truthtable.h"
-#include <cmath>
+// ----------------------------------------------------------------------------------------
+// setup_t
+// ----------------------------------------------------------------------------------------
namespace netlist
{
- // ----------------------------------------------------------------------------------------
- // nl_parse_t
- // ----------------------------------------------------------------------------------------
-
- nlparse_t::nlparse_t(setup_t &setup, log_type &log)
- : m_factory(log)
- , m_setup(setup)
- , m_log(log)
+setup_t::setup_t(netlist_t &netlist)
+ : m_netlist(netlist)
+ , m_factory(*this)
+ , m_proxy_cnt(0)
, m_frontier_cnt(0)
- { }
-
- void nlparse_t::register_alias(const pstring &alias, const pstring &out)
- {
- pstring alias_fqn = build_fqn(alias);
- pstring out_fqn = build_fqn(out);
- register_alias_nofqn(alias_fqn, out_fqn);
- }
-
- void nlparse_t::register_dippins_arr(const pstring &terms)
- {
- std::vector<pstring> list(plib::psplit(terms,", "));
- if (list.size() == 0 || (list.size() % 2) == 1)
- log().fatal(MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1,
- build_fqn(""));
- std::size_t n = list.size();
- for (std::size_t i = 0; i < n / 2; i++)
- {
- register_alias(plib::pfmt("{1}")(i+1), list[i * 2]);
- register_alias(plib::pfmt("{1}")(n-i), list[i * 2 + 1]);
- }
- }
-
- void nlparse_t::register_dev(const pstring &classname, const pstring &name)
- {
- auto f = m_factory.factory_by_name(classname);
- if (f == nullptr)
- log().fatal(MF_1_CLASS_1_NOT_FOUND, classname);
- else
- {
- /* make sure we parse macro library entries */
- f->macro_actions(*this, name);
- pstring key = build_fqn(name);
- if (device_exists(key))
- log().fatal(MF_1_DEVICE_ALREADY_EXISTS_1, name);
- else
- m_device_factory.insert(m_device_factory.end(), {key, f});
- }
- }
-
- void nlparse_t::register_link(const pstring &sin, const pstring &sout)
- {
- register_link_fqn(build_fqn(sin), build_fqn(sout));
- }
-
- void nlparse_t::register_link_arr(const pstring &terms)
- {
- std::vector<pstring> list(plib::psplit(terms,", "));
- if (list.size() < 2)
- log().fatal(MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL);
- for (std::size_t i = 1; i < list.size(); i++)
- {
- register_link(list[0], list[i]);
- }
- }
-
- void nlparse_t::include(const pstring &netlist_name)
- {
- for (auto &source : m_sources)
- {
- if (source->parse(*this, netlist_name))
- return;
- }
- log().fatal(MF_1_NOT_FOUND_IN_SOURCE_COLLECTION, netlist_name);
- }
-
-
- void nlparse_t::namespace_push(const pstring &aname)
- {
- if (m_namespace_stack.empty())
- //m_namespace_stack.push(netlist().name() + "." + aname);
- m_namespace_stack.push(aname);
- else
- m_namespace_stack.push(m_namespace_stack.top() + "." + aname);
- }
-
- void nlparse_t::namespace_pop()
- {
- m_namespace_stack.pop();
- }
-
- void nlparse_t::register_param(const pstring &param, const double value)
- {
- if (std::abs(value - std::floor(value)) > 1e-30 || std::abs(value) > 1e9)
- register_param(param, plib::pfmt("{1:.9}").e(value));
- else
- register_param(param, plib::pfmt("{1}")(static_cast<long>(value)));
- }
-
- void nlparse_t::register_param(const pstring &param, const pstring &value)
- {
- pstring fqn = build_fqn(param);
-
- auto idx = m_param_values.find(fqn);
- if (idx == m_param_values.end())
- {
- if (!m_param_values.insert({fqn, value}).second)
- log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST,
- param);
- }
- else
- {
- log().warning(MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3, fqn, idx->second,
- value);
- m_param_values[fqn] = value;
- }
- }
+{
+ devices::initialize_factory(m_factory);
+}
- void nlparse_t::register_lib_entry(const pstring &name, const pstring &sourcefile)
- {
- m_factory.register_device(plib::make_unique<factory::library_element_t>(name, name, "", sourcefile));
- }
+setup_t::~setup_t()
+{
+ m_links.clear();
+ m_alias.clear();
+ m_params.clear();
+ m_terminals.clear();
+ m_param_values.clear();
- void nlparse_t::register_frontier(const pstring &attach, const double r_IN, const double r_OUT)
- {
- pstring frontier_name = plib::pfmt("frontier_{1}")(m_frontier_cnt);
- m_frontier_cnt++;
- register_dev("FRONTIER_DEV", frontier_name);
- register_param(frontier_name + ".RIN", r_IN);
- register_param(frontier_name + ".ROUT", r_OUT);
- register_link(frontier_name + ".G", "GND");
- pstring attfn = build_fqn(attach);
- pstring front_fqn = build_fqn(frontier_name);
- bool found = false;
- for (auto & link : m_links)
- {
- if (link.first == attfn)
- {
- link.first = front_fqn + ".I";
- found = true;
- }
- else if (link.second == attfn)
- {
- link.second = front_fqn + ".I";
- found = true;
- }
- }
- if (!found)
- log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, attach);
- register_link(attach, frontier_name + ".Q");
- }
+ m_sources.clear();
+}
- void nlparse_t::tt_factory_create(tt_desc &desc, const pstring &sourcefile)
- {
- auto fac = devices::tt_factory_create(desc, sourcefile);
- m_factory.register_device(std::move(fac));
- }
+pstring setup_t::build_fqn(const pstring &obj_name) const
+{
+ if (m_namespace_stack.empty())
+ //return netlist().name() + "." + obj_name;
+ return obj_name;
+ else
+ return m_namespace_stack.top() + "." + obj_name;
+}
- pstring nlparse_t::build_fqn(const pstring &obj_name) const
- {
- if (m_namespace_stack.empty())
- //return netlist().name() + "." + obj_name;
- return obj_name;
- else
- return m_namespace_stack.top() + "." + obj_name;
- }
+void setup_t::namespace_push(const pstring &aname)
+{
+ if (m_namespace_stack.empty())
+ //m_namespace_stack.push(netlist().name() + "." + aname);
+ m_namespace_stack.push(aname);
+ else
+ m_namespace_stack.push(m_namespace_stack.top() + "." + aname);
+}
- void nlparse_t::register_alias_nofqn(const pstring &alias, const pstring &out)
- {
- if (!m_alias.insert({alias, out}).second)
- log().fatal(MF_1_ADDING_ALI1_TO_ALIAS_LIST, alias);
- }
+void setup_t::namespace_pop()
+{
+ m_namespace_stack.pop();
+}
- void nlparse_t::register_link_fqn(const pstring &sin, const pstring &sout)
- {
- link_t temp = link_t(sin, sout);
- log().debug("link {1} <== {2}\n", sin, sout);
- m_links.push_back(temp);
- }
+void setup_t::register_lib_entry(const pstring &name, const pstring &sourcefile)
+{
+ factory().register_device(plib::make_unique_base<factory::element_t, factory::library_element_t>(*this, name, name, "", sourcefile));
+}
- bool nlparse_t::device_exists(const pstring &name) const
- {
- for (auto &d : m_device_factory)
- if (d.first == name)
- return true;
- return false;
- }
+void setup_t::register_dev(const pstring &classname, const pstring &name)
+{
+ auto f = factory().factory_by_name(classname);
+ if (f == nullptr)
+ log().fatal(MF_1_CLASS_1_NOT_FOUND, classname);
+ /* make sure we parse macro library entries */
+ f->macro_actions(netlist(), name);
+ m_device_factory.push_back(std::pair<pstring, factory::element_t *>(build_fqn(name), f));
+}
- bool nlparse_t::parse_stream(plib::unique_ptr<plib::pistream> &&istrm, const pstring &name)
+bool setup_t::device_exists(const pstring &name) const
+{
+ for (auto e : m_device_factory)
{
- return parser_t(std::move(plib::ppreprocessor(&m_defines).process(std::move(istrm))), *this).parse(name);
+ if (e.first == name)
+ return true;
}
+ return false;
+}
- void nlparse_t::add_define(const pstring &defstr)
- {
- auto p = defstr.find("=");
- if (p != pstring::npos)
- add_define(plib::left(defstr, p), defstr.substr(p+1));
- else
- add_define(defstr, "1");
- }
- // ----------------------------------------------------------------------------------------
- // setup_t
- // ----------------------------------------------------------------------------------------
+void setup_t::register_model(const pstring &model_in)
+{
+ auto pos = model_in.find(" ");
+ if (pos == pstring::npos)
+ log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
+ pstring model = model_in.left(pos).trim().ucase();
+ pstring def = model_in.substr(pos + 1).trim();
+ if (!m_models.insert({model, def}).second)
+ log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
+}
+void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
+{
+ if (!m_alias.insert({alias, out}).second)
+ log().fatal(MF_1_ADDING_ALI1_TO_ALIAS_LIST, alias);
+}
-setup_t::setup_t(netlist_state_t &nlstate)
- : nlparse_t(*this, nlstate.log())
- , m_nlstate(nlstate)
- , m_netlist_params(nullptr)
- , m_proxy_cnt(0)
+void setup_t::register_alias(const pstring &alias, const pstring &out)
{
+ pstring alias_fqn = build_fqn(alias);
+ pstring out_fqn = build_fqn(out);
+ register_alias_nofqn(alias_fqn, out_fqn);
}
-setup_t::~setup_t() noexcept
+void setup_t::register_dippins_arr(const pstring &terms)
{
- // FIXME: can't see a need any longer
- m_links.clear();
- m_params.clear();
- m_terminals.clear();
- m_param_values.clear();
- m_sources.clear();
+ std::vector<pstring> list(plib::psplit(terms,", "));
+ if (list.size() == 0 || (list.size() % 2) == 1)
+ log().fatal(MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1,
+ build_fqn(""));
+ std::size_t n = list.size();
+ for (std::size_t i = 0; i < n / 2; i++)
+ {
+ register_alias(plib::pfmt("{1}")(i+1), list[i * 2]);
+ register_alias(plib::pfmt("{1}")(n-i), list[i * 2 + 1]);
+ }
}
pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
@@ -260,7 +145,7 @@ pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
return pstring("Error");
}
-pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def) const
+pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def)
{
auto i = m_param_values.find(name);
if (i != m_param_values.end())
@@ -269,6 +154,40 @@ pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def)
return def;
}
+double setup_t::get_initial_param_val(const pstring &name, const double def)
+{
+ auto i = m_param_values.find(name);
+ if (i != m_param_values.end())
+ {
+ double vald = 0;
+ if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
+ log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
+ return vald;
+ }
+ else
+ return def;
+}
+
+int setup_t::get_initial_param_val(const pstring &name, const int def)
+{
+ auto i = m_param_values.find(name);
+ if (i != m_param_values.end())
+ {
+ double vald = 0;
+ if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
+ log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
+ return static_cast<int>(vald);
+ }
+ else
+ return def;
+}
+
+void setup_t::register_param(const pstring &name, param_t &param)
+{
+ if (!m_params.insert({param.name(), param_ref_t(param.name(), param.device(), param)}).second)
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST, name);
+}
+
void setup_t::register_term(detail::core_terminal_t &term)
{
if (!m_terminals.insert({term.name(), &term}).second)
@@ -277,6 +196,30 @@ void setup_t::register_term(detail::core_terminal_t &term)
log().debug("{1} {2}\n", termtype_as_str(term), term.name());
}
+void setup_t::register_link_arr(const pstring &terms)
+{
+ std::vector<pstring> list(plib::psplit(terms,", "));
+ if (list.size() < 2)
+ log().fatal(MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL);
+ for (std::size_t i = 1; i < list.size(); i++)
+ {
+ register_link(list[0], list[i]);
+ }
+}
+
+
+void setup_t::register_link_fqn(const pstring &sin, const pstring &sout)
+{
+ link_t temp = link_t(sin, sout);
+ log().debug("link {1} <== {2}\n", sin, sout);
+ m_links.push_back(temp);
+}
+
+void setup_t::register_link(const pstring &sin, const pstring &sout)
+{
+ register_link_fqn(build_fqn(sin), build_fqn(sout));
+}
+
void setup_t::remove_connections(const pstring &pin)
{
pstring pinfn = build_fqn(pin);
@@ -298,14 +241,59 @@ void setup_t::remove_connections(const pstring &pin)
}
+void setup_t::register_frontier(const pstring &attach, const double r_IN, const double r_OUT)
+{
+ pstring frontier_name = plib::pfmt("frontier_{1}")(m_frontier_cnt);
+ m_frontier_cnt++;
+ register_dev("FRONTIER_DEV", frontier_name);
+ register_param(frontier_name + ".RIN", r_IN);
+ register_param(frontier_name + ".ROUT", r_OUT);
+ register_link(frontier_name + ".G", "GND");
+ pstring attfn = build_fqn(attach);
+ pstring front_fqn = build_fqn(frontier_name);
+ bool found = false;
+ for (auto & link : m_links)
+ {
+ if (link.first == attfn)
+ {
+ link.first = front_fqn + ".I";
+ found = true;
+ }
+ else if (link.second == attfn)
+ {
+ link.second = front_fqn + ".I";
+ found = true;
+ }
+ }
+ if (!found)
+ log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, attach);
+ register_link(attach, frontier_name + ".Q");
+}
+
-void setup_t::register_param_t(const pstring &name, param_t &param)
+void setup_t::register_param(const pstring &param, const double value)
{
- if (!m_params.insert({param.name(), param_ref_t(param.name(), param.device(), param)}).second)
- log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST, name);
+ register_param(param, plib::pfmt("{1:.9}").e(value));
}
+void setup_t::register_param(const pstring &param, const pstring &value)
+{
+ pstring fqn = build_fqn(param);
+ auto idx = m_param_values.find(fqn);
+ if (idx == m_param_values.end())
+ {
+ if (!m_param_values.insert({fqn, value}).second)
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST,
+ param);
+ }
+ else
+ {
+ log().warning(MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3, fqn, idx->second,
+ value);
+ m_param_values[fqn] = value;
+ }
+}
const pstring setup_t::resolve_alias(const pstring &name) const
{
@@ -323,42 +311,6 @@ const pstring setup_t::resolve_alias(const pstring &name) const
return ret;
}
-std::vector<pstring> setup_t::get_terminals_for_device_name(const pstring &devname)
-{
- std::vector<pstring> terms;
- for (auto & t : m_terminals)
- {
- if (plib::startsWith(t.second->name(), devname))
- {
- pstring tn(t.second->name().substr(devname.length()+1));
- if (tn.find(".") == pstring::npos)
- terms.push_back(tn);
- }
- }
-
- for (auto & t : m_alias)
- {
- if (plib::startsWith(t.first, devname))
- {
- pstring tn(t.first.substr(devname.length()+1));
- //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), tn.c_str());
- if (tn.find(".") == pstring::npos)
- {
- terms.push_back(tn);
- pstring resolved = resolve_alias(t.first);
- //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), resolved.c_str());
- if (resolved != t.first)
- {
- auto found = std::find(terms.begin(), terms.end(), resolved.substr(devname.length()+1));
- if (found!=terms.end())
- terms.erase(found);
- }
- }
- }
- }
- return terms;
-}
-
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
@@ -425,7 +377,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
{
nl_assert(out.is_logic());
- auto &out_cast = static_cast<logic_output_t &>(out);
+ logic_output_t &out_cast = static_cast<logic_output_t &>(out);
devices::nld_base_proxy *proxy = out_cast.get_proxy();
if (proxy == nullptr)
@@ -433,25 +385,28 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
// create a new one ...
pstring x = plib::pfmt("proxy_da_{1}_{2}")(out.name())(m_proxy_cnt);
auto new_proxy =
- out_cast.logic_family()->create_d_a_proxy(m_nlstate, x, &out_cast);
+ out_cast.logic_family()->create_d_a_proxy(netlist(), x, &out_cast);
m_proxy_cnt++;
+
+ //new_proxy->start_dev();
+
/* connect all existing terminals to new net */
- for (auto & p : out.net().core_terms())
+ for (auto & p : out.net().m_core_terms)
{
p->clear_net(); // de-link from all nets ...
if (!connect(new_proxy->proxy_term(), *p))
log().fatal(MF_2_CONNECTING_1_TO_2,
new_proxy->proxy_term().name(), (*p).name());
}
- out.net().core_terms().clear(); // clear the list
+ out.net().m_core_terms.clear(); // clear the list
out.net().add_terminal(new_proxy->in());
out_cast.set_proxy(proxy);
proxy = new_proxy.get();
- m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
+ netlist().register_dev(std::move(new_proxy));
}
return proxy;
}
@@ -460,7 +415,7 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
nl_assert(inp.is_logic());
- auto &incast = dynamic_cast<logic_input_t &>(inp);
+ logic_input_t &incast = dynamic_cast<logic_input_t &>(inp);
devices::nld_base_proxy *proxy = incast.get_proxy();
if (proxy != nullptr)
@@ -469,7 +424,7 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
log().debug("connect_terminal_input: connecting proxy\n");
pstring x = plib::pfmt("proxy_ad_{1}_{2}")(inp.name())(m_proxy_cnt);
- auto new_proxy = incast.logic_family()->create_a_d_proxy(m_nlstate, x, &incast);
+ auto new_proxy = incast.logic_family()->create_a_d_proxy(netlist(), x, &incast);
//auto new_proxy = plib::owned_ptr<devices::nld_a_to_d_proxy>::Create(netlist(), x, &incast);
incast.set_proxy(new_proxy.get());
m_proxy_cnt++;
@@ -480,17 +435,17 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
if (inp.has_net())
{
- for (auto & p : inp.net().core_terms())
+ for (auto & p : inp.net().m_core_terms)
{
p->clear_net(); // de-link from all nets ...
if (!connect(ret->proxy_term(), *p))
log().fatal(MF_2_CONNECTING_1_TO_2,
ret->proxy_term().name(), (*p).name());
}
- inp.net().core_terms().clear(); // clear the list
+ inp.net().m_core_terms.clear(); // clear the list
}
ret->out().net().add_terminal(inp);
- m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
+ netlist().register_dev(std::move(new_proxy));
return ret;
}
}
@@ -613,12 +568,11 @@ void setup_t::connect_terminals(detail::core_terminal_t &t1, detail::core_termin
{
log().debug("adding analog net ...\n");
// FIXME: Nets should have a unique name
- auto anet = pool().make_poolptr<analog_net_t>(m_nlstate,"net." + t1.name());
- auto anetp = anet.get();
- m_nlstate.register_net(std::move(anet));
- t1.set_net(anetp);
- anetp->add_terminal(t2);
- anetp->add_terminal(t1);
+ auto anet = plib::palloc<analog_net_t>(netlist(),"net." + t1.name());
+ netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(anet, true));
+ t1.set_net(anet);
+ anet->add_terminal(t2);
+ anet->add_terminal(t1);
}
}
@@ -626,7 +580,7 @@ static detail::core_terminal_t &resolve_proxy(detail::core_terminal_t &term)
{
if (term.is_logic())
{
- auto &out = dynamic_cast<logic_t &>(term);
+ logic_t &out = dynamic_cast<logic_t &>(term);
if (out.has_proxy())
return out.get_proxy()->proxy_term();
}
@@ -642,7 +596,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
ret = connect(t2, t1.net().railterminal());
if (!ret)
{
- for (auto & t : t1.net().core_terms())
+ for (auto & t : t1.net().m_core_terms)
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t2, *t);
@@ -657,7 +611,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
ret = connect(t1, t2.net().railterminal());
if (!ret)
{
- for (auto & t : t2.net().core_terms())
+ for (auto & t : t2.net().m_core_terms)
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t1, *t);
@@ -669,6 +623,8 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
return ret;
}
+
+
bool setup_t::connect(detail::core_terminal_t &t1_in, detail::core_terminal_t &t2_in)
{
log().debug("Connecting {1} to {2}\n", t1_in.name(), t2_in.name());
@@ -756,7 +712,18 @@ void setup_t::resolve_inputs()
// delete empty nets
- delete_empty_nets();
+ netlist().m_nets.erase(
+ std::remove_if(netlist().m_nets.begin(), netlist().m_nets.end(),
+ [](plib::owned_ptr<detail::net_t> &x)
+ {
+ if (x->num_cons() == 0)
+ {
+ x->netlist().log().verbose("Deleting net {1} ...", x->name());
+ return true;
+ }
+ else
+ return false;
+ }), netlist().m_nets.end());
pstring errstr("");
@@ -777,7 +744,7 @@ void setup_t::resolve_inputs()
}
-void setup_t::register_dynamic_log_devices()
+void setup_t::start_devices()
{
pstring env = plib::util::environment("NL_LOGS", "");
@@ -785,43 +752,41 @@ void setup_t::register_dynamic_log_devices()
{
log().debug("Creating dynamic logs ...");
std::vector<pstring> loglist(plib::psplit(env, ":"));
- for (const pstring &ll : loglist)
+ for (pstring ll : loglist)
{
pstring name = "log_" + ll;
- auto nc = factory().factory_by_name("LOG")->Create(m_nlstate, name);
+ auto nc = factory().factory_by_name("LOG")->Create(netlist(), name);
register_link(name + ".I", ll);
log().debug(" dynamic link {1}: <{2}>\n",ll, name);
- m_nlstate.add_dev(nc->name(), std::move(nc));
+ netlist().register_dev(std::move(nc));
}
}
}
-log_type &setup_t::log()
+plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log()
{
- return m_nlstate.log();
+ return netlist().log();
}
-const log_type &setup_t::log() const
+const plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log() const
{
- return m_nlstate.log();
+ return netlist().log();
}
// ----------------------------------------------------------------------------------------
-// Models
+// Model
// ----------------------------------------------------------------------------------------
-void models_t::register_model(pstring model_in)
+static pstring model_string(detail::model_map_t &map)
{
- auto pos = model_in.find(" ");
- if (pos == pstring::npos)
- throw nl_exception(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
- pstring model = plib::ucase(plib::trim(plib::left(model_in, pos)));
- pstring def = plib::trim(model_in.substr(pos + 1));
- if (!m_models.insert({model, def}).second)
- throw nl_exception(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
+ pstring ret = map["COREMODEL"] + "(";
+ for (auto & i : map)
+ ret = ret + i.first + "=" + i.second + " ";
+
+ return ret + ")";
}
-void models_t::model_parse(const pstring &model_in, model_map_t &map)
+void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
{
pstring model = model_in;
std::size_t pos = 0;
@@ -832,15 +797,15 @@ void models_t::model_parse(const pstring &model_in, model_map_t &map)
pos = model.find("(");
if (pos != pstring::npos) break;
- key = plib::ucase(model);
+ key = model.ucase();
auto i = m_models.find(key);
if (i == m_models.end())
- throw nl_exception(MF_1_MODEL_NOT_FOUND, model);
+ log().fatal(MF_1_MODEL_NOT_FOUND, model);
model = i->second;
}
- pstring xmodel = plib::left(model, pos);
+ pstring xmodel = model.left(pos);
- if (xmodel == "_")
+ if (xmodel.equals("_"))
map["COREMODEL"] = key;
else
{
@@ -848,65 +813,46 @@ void models_t::model_parse(const pstring &model_in, model_map_t &map)
if (i != m_models.end())
model_parse(xmodel, map);
else
- throw nl_exception(MF_1_MODEL_NOT_FOUND, model_in);
+ log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
}
- pstring remainder = plib::trim(model.substr(pos + 1));
- if (!plib::endsWith(remainder, ")"))
- throw nl_exception(MF_1_MODEL_ERROR_1, model);
+ pstring remainder = model.substr(pos + 1).trim();
+ if (!remainder.endsWith(")"))
+ log().fatal(MF_1_MODEL_ERROR_1, model);
// FIMXE: Not optimal
- remainder = plib::left(remainder, remainder.size() - 1);
+ remainder = remainder.left(remainder.length() - 1);
std::vector<pstring> pairs(plib::psplit(remainder," ", true));
for (pstring &pe : pairs)
{
auto pose = pe.find("=");
if (pose == pstring::npos)
- throw nl_exception(MF_1_MODEL_ERROR_ON_PAIR_1, model);
- map[plib::ucase(plib::left(pe, pose))] = pe.substr(pose + 1);
+ log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
+ map[pe.left(pose).ucase()] = pe.substr(pose + 1);
}
}
-pstring models_t::model_string(model_map_t &map)
-{
- pstring ret = map["COREMODEL"] + "(";
- for (auto & i : map)
- ret = ret + i.first + "=" + i.second + " ";
-
- return ret + ")";
-}
-
-pstring models_t::model_value_str(pstring model, pstring entity)
+const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
{
- model_map_t &map = m_cache[model];
-
- if (map.size() == 0)
- model_parse(model , map);
-
pstring ret;
- if (entity != plib::ucase(entity))
- throw nl_exception(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
+ if (entity != entity.ucase())
+ log().fatal(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
model_string(map));
if (map.find(entity) == map.end())
- throw nl_exception(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
+ log().fatal(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
else
ret = map[entity];
return ret;
}
-nl_double models_t::model_value(pstring model, pstring entity)
+nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
{
- model_map_t &map = m_cache[model];
-
- if (map.size() == 0)
- model_parse(model , map);
+ pstring tmp = model_value_str(map, entity);
- pstring tmp = model_value_str(model, entity);
-
- nl_double factor = plib::constants<nl_double>::one();
- auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1));
+ nl_double factor = NL_FCONST(1.0);
+ auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.length() - 1));
switch (*p)
{
case 'M': factor = 1e6; break;
@@ -919,69 +865,85 @@ nl_double models_t::model_value(pstring model, pstring entity)
case 'a': factor = 1e-18; break;
default:
if (*p < '0' || *p > '9')
- throw nl_exception(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
+ log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
}
- if (factor != plib::constants<nl_double>::one())
- tmp = plib::left(tmp, tmp.size() - 1);
- // FIXME: check for errors
- //printf("%s %s %e %e\n", entity.c_str(), tmp.c_str(), plib::pstonum<nl_double>(tmp), factor);
- return plib::pstonum<nl_double>(tmp) * factor;
+ if (factor != NL_FCONST(1.0))
+ tmp = tmp.left(tmp.length() - 1);
+ return tmp.as_double() * factor;
}
class logic_family_std_proxy_t : public logic_family_desc_t
{
public:
- logic_family_std_proxy_t() = default;
- pool_owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist,
+ logic_family_std_proxy_t() { }
+ virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
const pstring &name, logic_output_t *proxied) const override;
- pool_owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
};
-pool_owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_state_t &anetlist,
+plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
const pstring &name, logic_output_t *proxied) const
{
- return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-pool_owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const
+plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
{
- return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
{
+ detail::model_map_t map;
+ model_parse(model, map);
- if (m_models.model_value_str(model, "TYPE") == "TTL")
+ if (model_value_str(map, "TYPE") == "TTL")
return family_TTL();
- if (m_models.model_value_str(model, "TYPE") == "CD4XXX")
+ if (model_value_str(map, "TYPE") == "CD4XXX")
return family_CD4XXX();
- for (auto & e : m_nlstate.m_family_cache)
+ for (auto & e : netlist().m_family_cache)
if (e.first == model)
return e.second.get();
- auto ret = plib::make_unique<logic_family_std_proxy_t>();
+ auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
- ret->m_fixed_V = m_models.model_value(model, "FV");
- ret->m_low_thresh_PCNT = m_models.model_value(model, "IVL");
- ret->m_high_thresh_PCNT = m_models.model_value(model, "IVH");
- ret->m_low_VO = m_models.model_value(model, "OVL");
- ret->m_high_VO = m_models. model_value(model, "OVH");
- ret->m_R_low = m_models.model_value(model, "ORL");
- ret->m_R_high = m_models.model_value(model, "ORH");
+ ret->m_fixed_V = model_value(map, "FV");
+ ret->m_low_thresh_PCNT = model_value(map, "IVL");
+ ret->m_high_thresh_PCNT = model_value(map, "IVH");
+ ret->m_low_VO = model_value(map, "OVL");
+ ret->m_high_VO = model_value(map, "OVH");
+ ret->m_R_low = model_value(map, "ORL");
+ ret->m_R_high = model_value(map, "ORH");
auto retp = ret.get();
- m_nlstate.m_family_cache.emplace_back(model, std::move(ret));
+ netlist().m_family_cache.emplace_back(model, std::move(ret));
return retp;
}
+void setup_t::tt_factory_create(tt_desc &desc, const pstring &sourcefile)
+{
+ devices::tt_factory_create(*this, desc, sourcefile);
+}
+
+
// ----------------------------------------------------------------------------------------
// Sources
// ----------------------------------------------------------------------------------------
-plib::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
+void setup_t::include(const pstring &netlist_name)
+{
+ for (auto &source : m_sources)
+ {
+ if (source->parse(netlist_name))
+ return;
+ }
+ log().fatal(MF_1_NOT_FOUND_IN_SOURCE_COLLECTION, netlist_name);
+}
+
+std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
{
for (auto &source : m_sources)
{
@@ -993,189 +955,77 @@ plib::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
}
}
log().warning(MW_1_DATA_1_NOT_FOUND, name);
- return plib::unique_ptr<plib::pistream>(nullptr);
+ return std::unique_ptr<plib::pistream>(nullptr);
}
-// ----------------------------------------------------------------------------------------
-// Device handling
-// ----------------------------------------------------------------------------------------
-
-void setup_t::delete_empty_nets()
+bool setup_t::parse_stream(plib::putf8_reader &istrm, const pstring &name)
{
- m_nlstate.nets().erase(
- std::remove_if(m_nlstate.nets().begin(), m_nlstate.nets().end(),
- [](pool_owned_ptr<detail::net_t> &x)
- {
- if (x->num_cons() == 0)
- {
- x->state().log().verbose("Deleting net {1} ...", x->name());
- x->state().run_state_manager().remove_save_items(x.get());
- return true;
- }
- else
- return false;
- }), m_nlstate.nets().end());
-}
+ plib::pomemstream ostrm;
+ plib::putf8_writer owrt(ostrm);
-// ----------------------------------------------------------------------------------------
-// Run preparation
-// ----------------------------------------------------------------------------------------
+ plib::ppreprocessor(&m_defines).process(istrm, owrt);
+ plib::pimemstream istrm2(ostrm);
+ plib::putf8_reader reader2(istrm2);
+ return parser_t(reader2, *this).parse(name);
+}
-void setup_t::prepare_to_run()
+void setup_t::register_define(pstring defstr)
{
- register_dynamic_log_devices();
-
- /* make sure the solver and parameters are started first! */
-
- for (auto & e : m_device_factory)
- {
- if ( factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
- || factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
- {
- m_nlstate.add_dev(e.first, pool_owned_ptr<device_t>(e.second->Create(m_nlstate, e.first)));
- }
- }
-
- log().debug("Searching for solver and parameters ...\n");
-
- auto solver = m_nlstate.get_single_device<devices::NETLIB_NAME(solver)>("solver");
- m_netlist_params = m_nlstate.get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
-
- /* create devices */
-
- log().debug("Creating devices ...\n");
- for (auto & e : m_device_factory)
- {
- if ( !factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
- && !factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
- {
- auto dev = pool_owned_ptr<device_t>(e.second->Create(m_nlstate, e.first));
- m_nlstate.add_dev(dev->name(), std::move(dev));
- }
- }
-
- log().debug("Looking for unknown parameters ...\n");
- for (auto &p : m_param_values)
- {
- auto f = m_params.find(p.first);
- if (f == m_params.end())
- {
- if (plib::endsWith(p.first, pstring(".HINT_NO_DEACTIVATE")))
- {
- // FIXME: get device name, check for device
- }
- else
- log().info("Unknown parameter: {}", p.first);
- }
- }
-
- bool use_deactivate = m_netlist_params->m_use_deactivate() ? true : false;
-
- for (auto &d : m_nlstate.devices())
- {
- if (use_deactivate)
- {
- auto p = m_param_values.find(d.second->name() + ".HINT_NO_DEACTIVATE");
- if (p != m_param_values.end())
- {
- //FIXME: check for errors ...
- auto v = plib::pstonum<double>(p->second);
- if (std::abs(v - std::floor(v)) > 1e-6 )
- log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
- d.second->set_hint_deactivate(v == 0.0);
- }
- }
- else
- d.second->set_hint_deactivate(false);
- }
-
- /* resolve inputs */
- resolve_inputs();
-
- log().verbose("looking for two terms connected to rail nets ...");
- for (auto & t : m_nlstate.get_device_list<analog::NETLIB_NAME(twoterm)>())
- {
- if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
- {
- log().warning(MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3,
- t->name(), t->m_N.net().name(), t->m_P.net().name());
- t->m_N.net().remove_terminal(t->m_N);
- t->m_P.net().remove_terminal(t->m_P);
- m_nlstate.remove_dev(t);
- }
- }
-
- log().verbose("initialize solver ...\n");
-
- if (solver == nullptr)
- {
- for (auto &p : m_nlstate.nets())
- if (p->is_analog())
- log().fatal(MF_0_NO_SOLVER);
- }
+ auto p = defstr.find("=");
+ if (p != pstring::npos)
+ register_define(defstr.left(p), defstr.substr(p+1));
else
- solver->post_start();
-
- for (auto &n : m_nlstate.nets())
- for (auto & term : n->core_terms())
- {
- //core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
- core_device_t *dev = &term->device();
- dev->set_default_delegate(*term);
- }
-
+ register_define(defstr, "1");
}
// ----------------------------------------------------------------------------------------
// base sources
// ----------------------------------------------------------------------------------------
-bool source_t::parse(nlparse_t &setup, const pstring &name)
+bool source_t::parse(const pstring &name)
{
if (m_type != SOURCE)
return false;
else
{
- return setup.parse_stream(stream(name), name);
+ auto rstream = stream(name);
+ plib::putf8_reader reader(*rstream);
+ return m_setup.parse_stream(reader, name);
}
}
-plib::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
+std::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
{
- plib::unused_var(name);
- return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
+ return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
}
-plib::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
+std::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
{
- plib::unused_var(name);
- return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
+ return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
}
-plib::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
+std::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
{
- plib::unused_var(name);
- return plib::make_unique<plib::pifilestream>(m_filename);
+ return plib::make_unique_base<plib::pistream, plib::pifilestream>(m_filename);
}
-bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
+bool source_proc_t::parse(const pstring &name)
{
if (name == m_setup_func_name)
{
- m_setup_func(setup);
+ m_setup_func(setup());
return true;
}
else
return false;
}
-plib::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
+std::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
{
- plib::unused_var(name);
- plib::unique_ptr<plib::pistream> p(nullptr);
+ std::unique_ptr<plib::pistream> p(nullptr);
return p;
}
-} // namespace netlist
+}
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index ed0248a48e6..d0359928711 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -8,20 +8,18 @@
#ifndef NLSETUP_H_
#define NLSETUP_H_
-#include "plib/pparser.h"
-#include "plib/pstream.h"
#include "plib/pstring.h"
#include "plib/putil.h"
+#include "plib/pstream.h"
+#include "plib/pparser.h"
-#include "nl_config.h"
#include "nl_factory.h"
-#include "nltypes.h"
+#include "nl_config.h"
+#include "netlist_types.h"
-#include <memory>
#include <stack>
-#include <unordered_map>
#include <vector>
-
+#include <memory>
//============================================================
// MACROS / inline netlist definitions
@@ -29,46 +27,46 @@
#define NET_STR(x) # x
-#define NET_MODEL(model) \
+#define NET_MODEL(model) \
setup.register_model(model);
-#define ALIAS(alias, name) \
+#define ALIAS(alias, name) \
setup.register_alias(# alias, # name);
-#define DIPPINS(pin1, ...) \
+#define DIPPINS(pin1, ...) \
setup.register_dippins_arr( # pin1 ", " # __VA_ARGS__);
/* to be used to reference new library truthtable devices */
-#define NET_REGISTER_DEV(type, name) \
+#define NET_REGISTER_DEV(type, name) \
setup.register_dev(# type, # name);
-#define NET_CONNECT(name, input, output) \
+#define NET_CONNECT(name, input, output) \
setup.register_link(# name "." # input, # output);
-#define NET_C(term1, ...) \
+#define NET_C(term1, ...) \
setup.register_link_arr( # term1 ", " # __VA_ARGS__);
-#define PARAM(name, val) \
+#define PARAM(name, val) \
setup.register_param(# name, val);
#define HINT(name, val) \
setup.register_param(# name ".HINT_" # val, 1);
-#define NETDEV_PARAMI(name, param, val) \
+#define NETDEV_PARAMI(name, param, val) \
setup.register_param(# name "." # param, val);
#define NETLIST_NAME(name) netlist ## _ ## name
#define NETLIST_EXTERNAL(name) \
- void NETLIST_NAME(name)(netlist::nlparse_t &setup);
+ void NETLIST_NAME(name)(netlist::setup_t &setup);
#define NETLIST_START(name) \
-void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
+void NETLIST_NAME(name)(netlist::setup_t &setup) \
{
#define NETLIST_END() }
#define LOCAL_SOURCE(name) \
- setup.register_source(plib::make_unique<netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
+ setup.register_source(plib::make_unique_base<netlist::source_t, netlist::source_proc_t>(setup, # name, &NETLIST_NAME(name)));
#define LOCAL_LIB_ENTRY(name) \
LOCAL_SOURCE(name) \
@@ -82,7 +80,7 @@ void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
NETLIST_NAME(model)(setup); \
setup.namespace_pop();
-#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
+#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
setup.register_frontier(# attach, r_in, r_out);
// -----------------------------------------------------------------------------
@@ -100,10 +98,10 @@ void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
desc.family = "";
#define TT_HEAD(x) \
- desc.desc.emplace_back(x);
+ desc.desc.push_back(x);
#define TT_LINE(x) \
- desc.desc.emplace_back(x);
+ desc.desc.push_back(x);
#define TT_FAMILY(x) \
desc.family = x;
@@ -112,23 +110,22 @@ void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
setup.tt_factory_create(desc, __FILE__); \
}
+
namespace netlist
{
namespace detail {
class core_terminal_t;
class net_t;
- } // namespace detail
+ }
namespace devices {
class nld_base_proxy;
- class nld_netlistparams;
- } // namespace devices
+ }
class core_device_t;
class param_t;
class setup_t;
- class netlist_state_t;
class netlist_t;
class logic_family_desc_t;
class terminal_t;
@@ -139,7 +136,6 @@ namespace netlist
struct tt_desc
{
- tt_desc() : ni(0), no(0) { }
pstring name;
pstring classname;
unsigned long ni;
@@ -172,222 +168,138 @@ namespace netlist
class source_t
{
public:
-
- friend class setup_t;
-
enum type_t
{
SOURCE,
DATA
};
- using list_t = std::vector<plib::unique_ptr<source_t>>;
+ using list_t = std::vector<std::unique_ptr<source_t>>;
- source_t(const type_t type = SOURCE)
- : m_type(type)
+ source_t(setup_t &setup, const type_t type = SOURCE)
+ : m_setup(setup), m_type(type)
{}
- COPYASSIGNMOVE(source_t, delete)
-
- virtual ~source_t() noexcept = default;
+ virtual ~source_t() { }
- virtual bool parse(nlparse_t &setup, const pstring &name);
+ virtual bool parse(const pstring &name);
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) = 0;
+ setup_t &setup() { return m_setup; }
type_t type() const { return m_type; }
-
- protected:
- virtual plib::unique_ptr<plib::pistream> stream(const pstring &name) = 0;
-
private:
+ setup_t &m_setup;
const type_t m_type;
};
-
// ----------------------------------------------------------------------------------------
- // Collection of models
+ // setup_t
// ----------------------------------------------------------------------------------------
- class models_t
+
+ class setup_t : plib::nocopyassignmove
{
public:
- void register_model(pstring model_in);
- /* model / family related */
-
- pstring model_value_str(pstring model, pstring entity);
- double model_value(pstring model, pstring entity);
+ using link_t = std::pair<pstring, pstring>;
- pstring model_type(pstring model) { return model_value_str(model, "COREMODEL"); }
+ explicit setup_t(netlist_t &netlist);
+ ~setup_t();
- private:
- using model_map_t = std::unordered_map<pstring, pstring>;
+ netlist_t &netlist() { return m_netlist; }
+ const netlist_t &netlist() const { return m_netlist; }
- void model_parse(const pstring &model, model_map_t &map);
- pstring model_string(model_map_t &map);
+ pstring build_fqn(const pstring &obj_name) const;
- std::unordered_map<pstring, pstring> m_models;
- std::unordered_map<pstring, model_map_t> m_cache;
- };
+ void register_param(const pstring &name, param_t &param);
+ pstring get_initial_param_val(const pstring &name, const pstring &def);
+ double get_initial_param_val(const pstring &name, const double def);
+ int get_initial_param_val(const pstring &name, const int def);
- // ----------------------------------------------------------------------------------------
- // nlparse_t
- // ----------------------------------------------------------------------------------------
+ void register_term(detail::core_terminal_t &obj);
- class nlparse_t
- {
- public:
- using link_t = std::pair<pstring, pstring>;
+ void register_dev(const pstring &classname, const pstring &name);
- nlparse_t(setup_t &netlist, log_type &log);
+ void register_lib_entry(const pstring &name, const pstring &sourcefile);
- void register_model(const pstring &model_in) { m_models.register_model(model_in); }
+ void register_model(const pstring &model_in);
void register_alias(const pstring &alias, const pstring &out);
void register_dippins_arr(const pstring &terms);
- void register_dev(const pstring &classname, const pstring &name);
- void register_link(const pstring &sin, const pstring &sout);
+
+ void register_alias_nofqn(const pstring &alias, const pstring &out);
+
void register_link_arr(const pstring &terms);
+ void register_link_fqn(const pstring &sin, const pstring &sout);
+ void register_link(const pstring &sin, const pstring &sout);
+
void register_param(const pstring &param, const pstring &value);
void register_param(const pstring &param, const double value);
- void register_lib_entry(const pstring &name, const pstring &sourcefile);
+
void register_frontier(const pstring &attach, const double r_IN, const double r_OUT);
- /* register a source */
- void register_source(plib::unique_ptr<source_t> &&src)
- {
- m_sources.push_back(std::move(src));
- }
+ void remove_connections(const pstring &attach);
- void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
+ bool connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
+
+ bool device_exists(const pstring &name) const;
+
+ param_t *find_param(const pstring &param_in, bool required = true) const;
+
+ void start_devices();
+ void resolve_inputs();
/* handle namespace */
void namespace_push(const pstring &aname);
void namespace_pop();
- /* include other files */
+ /* parse a source */
void include(const pstring &netlist_name);
- pstring build_fqn(const pstring &obj_name) const;
- void register_alias_nofqn(const pstring &alias, const pstring &out);
-
- /* also called from devices for latebinding connected terminals */
- void register_link_fqn(const pstring &sin, const pstring &sout);
+ std::unique_ptr<plib::pistream> get_data_stream(const pstring &name);
- /* used from netlist.cpp (mame) */
- bool device_exists(const pstring &name) const;
+ bool parse_stream(plib::putf8_reader &istrm, const pstring &name);
- /* FIXME: used by source_t - need a different approach at some time */
- bool parse_stream(plib::unique_ptr<plib::pistream> &&istrm, const pstring &name);
+ /* register a source */
- void add_define(const pstring &def, const pstring &val)
+ void register_source(std::unique_ptr<source_t> &&src)
{
- m_defines.insert({ def, plib::ppreprocessor::define_t(def, val)});
+ m_sources.push_back(std::move(src));
}
- void add_define(const pstring &defstr);
+ void register_define(pstring def, pstring val) { m_defines.push_back(plib::ppreprocessor::define_t(def, val)); }
+ void register_define(pstring defstr);
factory::list_t &factory() { return m_factory; }
const factory::list_t &factory() const { return m_factory; }
- log_type &log() { return m_log; }
- const log_type &log() const { return m_log; }
-
- /* FIXME: sources may need access to the netlist parent type
- * since they may be created in a context in which they don't
- * have access to their environment.
- * Example is the MAME memregion source.
- * We thus need a better approach to creating netlists in a context
- * other than static procedures.
- */
- setup_t &setup() { return m_setup; }
- const setup_t &setup() const { return m_setup; }
-
- models_t &models() { return m_models; }
- const models_t &models() const { return m_models; }
-
- protected:
- models_t m_models;
- std::stack<pstring> m_namespace_stack;
- std::unordered_map<pstring, pstring> m_alias;
- std::vector<link_t> m_links;
- std::unordered_map<pstring, pstring> m_param_values;
-
- source_t::list_t m_sources;
-
- factory::list_t m_factory;
-
- /* need to preserve order of device creation ... */
- std::vector<std::pair<pstring, factory::element_t *>> m_device_factory;
-
-
- private:
- plib::ppreprocessor::defines_map_type m_defines;
-
- setup_t &m_setup;
- log_type &m_log;
- unsigned m_frontier_cnt;
- };
-
- // ----------------------------------------------------------------------------------------
- // setup_t
- // ----------------------------------------------------------------------------------------
-
- class setup_t : public nlparse_t
- {
- public:
-
- explicit setup_t(netlist_state_t &nlstate);
- ~setup_t() noexcept;
-
- COPYASSIGNMOVE(setup_t, delete)
-
- netlist_state_t &nlstate() { return m_nlstate; }
- const netlist_state_t &nlstate() const { return m_nlstate; }
-
- void register_param_t(const pstring &name, param_t &param);
-
- pstring get_initial_param_val(const pstring &name, const pstring &def) const;
-
- void register_term(detail::core_terminal_t &obj);
-
- void remove_connections(const pstring &attach);
+ /* model / family related */
- bool connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
+ const pstring model_value_str(detail::model_map_t &map, const pstring &entity);
+ double model_value(detail::model_map_t &map, const pstring &entity);
- param_t *find_param(const pstring &param_in, bool required = true) const;
+ void model_parse(const pstring &model, detail::model_map_t &map);
- /* get family */
const logic_family_desc_t *family_from_model(const pstring &model);
- void register_dynamic_log_devices();
- void resolve_inputs();
-
- plib::unique_ptr<plib::pistream> get_data_stream(const pstring &name);
-
- factory::list_t &factory() { return m_factory; }
- const factory::list_t &factory() const { return m_factory; }
+ void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
/* helper - also used by nltool */
const pstring resolve_alias(const pstring &name) const;
- /* needed by nltool */
- std::vector<pstring> get_terminals_for_device_name(const pstring &devname);
+ plib::plog_base<netlist_t, NL_DEBUG> &log();
+ const plib::plog_base<netlist_t, NL_DEBUG> &log() const;
+
+ std::vector<std::pair<pstring, factory::element_t *>> m_device_factory;
- log_type &log();
- const log_type &log() const;
+ std::unordered_map<pstring, pstring> m_alias;
+ std::unordered_map<pstring, pstring> m_param_values;
+ std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
/* needed by proxy */
detail::core_terminal_t *find_terminal(const pstring &outname_in, const detail::terminal_type atype, bool required = true);
- /* core net handling */
-
- void delete_empty_nets();
-
- /* run preparation */
-
- void prepare_to_run();
-
private:
detail::core_terminal_t *find_terminal(const pstring &outname_in, bool required = true);
@@ -406,30 +318,35 @@ namespace netlist
devices::nld_base_proxy *get_d_a_proxy(detail::core_terminal_t &out);
devices::nld_base_proxy *get_a_d_proxy(detail::core_terminal_t &inp);
- std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
-
- netlist_state_t &m_nlstate;
- devices::nld_netlistparams *m_netlist_params;
+ netlist_t &m_netlist;
std::unordered_map<pstring, param_ref_t> m_params;
+ std::vector<link_t> m_links;
+ factory::list_t m_factory;
+ std::unordered_map<pstring, pstring> m_models;
+
+ std::stack<pstring> m_namespace_stack;
+ source_t::list_t m_sources;
+ std::vector<plib::ppreprocessor::define_t> m_defines;
unsigned m_proxy_cnt;
- };
+ unsigned m_frontier_cnt;
+};
// ----------------------------------------------------------------------------------------
// base sources
// ----------------------------------------------------------------------------------------
+
class source_string_t : public source_t
{
public:
- source_string_t(const pstring &source)
- : source_t(), m_str(source)
+ source_string_t(setup_t &setup, const pstring &source)
+ : source_t(setup), m_str(source)
{
}
- protected:
- plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_str;
@@ -439,13 +356,12 @@ namespace netlist
{
public:
- source_file_t(const pstring &filename)
- : source_t(), m_filename(filename)
+ source_file_t(setup_t &setup, const pstring &filename)
+ : source_t(setup), m_filename(filename)
{
}
- protected:
- plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_filename;
@@ -454,13 +370,12 @@ namespace netlist
class source_mem_t : public source_t
{
public:
- source_mem_t(const char *mem)
- : source_t(), m_str(mem)
+ source_mem_t(setup_t &setup, const char *mem)
+ : source_t(setup), m_str(mem, pstring::UTF8)
{
}
- protected:
- plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_str;
@@ -469,28 +384,22 @@ namespace netlist
class source_proc_t : public source_t
{
public:
- source_proc_t(const pstring &name, void (*setup_func)(nlparse_t &))
- : source_t(),
+ source_proc_t(setup_t &setup, pstring name, void (*setup_func)(setup_t &))
+ : source_t(setup),
m_setup_func(setup_func),
m_setup_func_name(name)
{
}
- bool parse(nlparse_t &setup, const pstring &name) override;
-
- protected:
- plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ virtual bool parse(const pstring &name) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
- void (*m_setup_func)(nlparse_t &);
+ void (*m_setup_func)(setup_t &);
pstring m_setup_func_name;
};
- // -----------------------------------------------------------------------------
- // inline implementations
- // -----------------------------------------------------------------------------
-
-} // namespace netlist
+}
#endif /* NLSETUP_H_ */
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
new file mode 100644
index 00000000000..7c81f890e07
--- /dev/null
+++ b/src/lib/netlist/nl_time.h
@@ -0,0 +1,145 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nltime.h
+ */
+
+#ifndef NLTIME_H_
+#define NLTIME_H_
+
+#include "nl_config.h"
+#include "plib/ptypes.h"
+#include "plib/pstate.h"
+
+#include <cstdint>
+
+//============================================================
+// MACROS
+//============================================================
+
+#define NLTIME_FROM_NS(t) netlist_time::from_nsec(t)
+#define NLTIME_FROM_US(t) netlist_time::from_usec(t)
+#define NLTIME_FROM_MS(t) netlist_time::from_msec(t)
+#define NLTIME_IMMEDIATE netlist_time::from_nsec(1)
+
+// ----------------------------------------------------------------------------------------
+// netlist_time
+// ----------------------------------------------------------------------------------------
+
+namespace netlist
+{
+ template <typename TYPE, TYPE RES>
+ struct ptime final
+ {
+ public:
+
+ using internal_type = TYPE;
+ using mult_type = std::uint64_t;
+
+ constexpr ptime() noexcept : m_time(0) {}
+
+ constexpr ptime(const ptime &rhs) noexcept = default;
+ constexpr ptime(ptime &&rhs) noexcept = default;
+ C14CONSTEXPR ptime &operator=(const ptime &rhs) noexcept = default;
+ C14CONSTEXPR ptime &operator=(ptime &&rhs) noexcept = default;
+
+ constexpr explicit ptime(const double t) = delete;
+ //: m_time((internal_type) ( t * (double) resolution)) { }
+ constexpr explicit ptime(const internal_type &nom, const internal_type &den) noexcept
+ : m_time(nom * (RES / den)) { }
+
+ C14CONSTEXPR ptime &operator+=(const ptime &rhs) noexcept { m_time += rhs.m_time; return *this; }
+ C14CONSTEXPR ptime &operator-=(const ptime &rhs) noexcept { m_time -= rhs.m_time; return *this; }
+ C14CONSTEXPR ptime &operator*=(const mult_type &factor) noexcept { m_time *= static_cast<internal_type>(factor); return *this; }
+
+ friend C14CONSTEXPR ptime operator-(ptime lhs, const ptime &rhs) noexcept
+ {
+ return lhs -= rhs;
+ }
+
+ friend C14CONSTEXPR ptime operator+(ptime lhs, const ptime &rhs) noexcept
+ {
+ return lhs += rhs;
+ }
+
+ friend C14CONSTEXPR ptime operator*(ptime lhs, const mult_type &factor) noexcept
+ {
+ return lhs *= factor;
+ }
+
+ friend constexpr mult_type operator/(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return static_cast<mult_type>(lhs.m_time / rhs.m_time);
+ }
+
+ friend constexpr bool operator<(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return (lhs.m_time < rhs.m_time);
+ }
+
+ friend constexpr bool operator>(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return (rhs < lhs);
+ }
+
+ friend constexpr bool operator<=(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return !(lhs > rhs);
+ }
+
+ friend constexpr bool operator>=(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return !(lhs < rhs);
+ }
+
+ friend constexpr bool operator==(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return lhs.m_time == rhs.m_time;
+ }
+
+ friend constexpr bool operator!=(const ptime &lhs, const ptime &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ constexpr internal_type as_raw() const noexcept { return m_time; }
+ constexpr double as_double() const noexcept
+ {
+ return static_cast<double>(m_time) / static_cast<double>(RES);
+ }
+
+ // for save states ....
+ C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; }
+
+ static constexpr ptime from_nsec(const internal_type &ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type &us) noexcept { return ptime(us, UINT64_C(1000000)); }
+ static constexpr ptime from_msec(const internal_type &ms) noexcept { return ptime(ms, UINT64_C(1000)); }
+ static constexpr ptime from_hz(const internal_type &hz) noexcept { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type &raw) noexcept { return ptime(raw); }
+ static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(RES)), RES); }
+
+ static constexpr ptime zero() noexcept { return ptime(0, RES); }
+ static constexpr ptime quantum() noexcept { return ptime(1, RES); }
+ static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), RES); }
+ static constexpr internal_type resolution() noexcept { return RES; }
+ private:
+ constexpr explicit ptime(const internal_type &time) : m_time(time) {}
+ constexpr explicit ptime(internal_type &&time) : m_time(time) {}
+ internal_type m_time;
+ };
+
+#if (PHAS_INT128)
+ using netlist_time = ptime<UINT128, NETLIST_INTERNAL_RES>;
+#else
+ using netlist_time = ptime<std::uint64_t, NETLIST_INTERNAL_RES>;
+#endif
+}
+
+namespace plib {
+template<> inline void state_manager_t::save_item(const void *owner, netlist::netlist_time &nlt, const pstring &stname)
+{
+ save_state_ptr(owner, stname, datatype_t(sizeof(netlist::netlist_time::internal_type), true, false), 1, nlt.get_internaltype_ptr());
+}
+}
+
+#endif /* NLTIME_H_ */
diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h
deleted file mode 100644
index 7d7582774b1..00000000000
--- a/src/lib/netlist/nltypes.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*!
- *
- * \file nltypes.h
- *
- */
-
-/* \note never change the name to nl_types.h. This creates a conflict
- * with nl_types.h file provided by libc++ (clang, macosx)
- */
-
-#ifndef NLTYPES_H_
-#define NLTYPES_H_
-
-#include "nl_config.h"
-#include "plib/pchrono.h"
-#include "plib/pfmtlog.h"
-#include "plib/pmempool.h"
-#include "plib/pstate.h"
-#include "plib/pstring.h"
-#include "plib/ptime.h"
-#include "plib/putil.h"
-
-#include <cstdint>
-#include <unordered_map>
-
-namespace netlist
-{
- /*! @brief plib::constants struct specialized for nl_double
- *
- * This may be any of bool, uint8_t, uint16_t, uin32_t and uint64_t.
- * The choice has little to no impact on performance.
- */
- using constants = plib::constants<nl_double>;
-
- /*! @brief netlist_sig_t is the type used for logic signals.
- *
- * This may be any of bool, uint8_t, uint16_t, uin32_t and uint64_t.
- * The choice has little to no impact on performance.
- */
- using netlist_sig_t = std::uint32_t;
-
- /* FIXME: belongs into nl_base.h to nlstate */
- /**
- * @brief Interface definition for netlist callbacks into calling code
- *
- * A class inheriting from netlist_callbacks_t has to be passed to the netlist_t
- * constructor. Netlist does processing during construction and thus needs
- * the object passed completely constructed.
- *
- */
- class callbacks_t
- {
- public:
-
- callbacks_t() = default;
- /* what is done before this is passed as a unique_ptr to netlist
- * we should not limit.
- */
- virtual ~callbacks_t() = default;
- COPYASSIGNMOVE(callbacks_t, default)
-
- /* logging callback */
- virtual void vlog(const plib::plog_level &l, const pstring &ls) const = 0;
-
- };
-
- using log_type = plib::plog_base<callbacks_t, NL_DEBUG>;
-
-
- //============================================================
- // Performance tracking
- //============================================================
-
- template<bool enabled_>
- using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, enabled_>;
-
- template<bool enabled_>
- using nperfcount_t = plib::chrono::counter<enabled_>;
-
- //============================================================
- // Types needed by various includes
- //============================================================
-
- /*! The memory pool for netlist objects
- *
- * \note This is not the right location yet.
- *
- */
-
-#if (USE_MEMPOOL)
- using nlmempool = plib::mempool;
-#else
- using nlmempool = plib::aligned_arena;
-#endif
-
- /*! Owned pointer type for pooled allocations.
- *
- */
- template <typename T>
- using pool_owned_ptr = nlmempool::owned_pool_ptr<T>;
-
- inline nlmempool &pool()
- {
- static nlmempool static_pool;
- return static_pool;
- }
-
- namespace detail {
-
- /*! Enum specifying the type of object */
- enum terminal_type {
- TERMINAL = 0, /*!< object is an analog terminal */
- INPUT = 1, /*!< object is an input */
- OUTPUT = 2, /*!< object is an output */
- };
-
- } // namespace detail
-
-#if (PHAS_INT128)
- using netlist_time = ptime<INT128, NETLIST_INTERNAL_RES>;
-#else
- using netlist_time = plib::ptime<std::int64_t, NETLIST_INTERNAL_RES>;
- static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr");
-#endif
-
- //============================================================
- // MACROS
- //============================================================
-
- template <typename T> inline constexpr const netlist_time NLTIME_FROM_NS(T &&t) noexcept { return netlist_time::from_nsec(t); }
- template <typename T> inline constexpr const netlist_time NLTIME_FROM_US(T &&t) noexcept { return netlist_time::from_usec(t); }
- template <typename T> inline constexpr const netlist_time NLTIME_FROM_MS(T &&t) noexcept { return netlist_time::from_msec(t); }
-
-} // namespace netlist
-
-namespace plib {
-
- template<>
- inline void state_manager_t::save_item(const void *owner, netlist::netlist_time &nlt, const pstring &stname)
- {
- save_state_ptr(owner, stname, datatype_t(sizeof(netlist::netlist_time::internal_type), true, false), 1, nlt.get_internaltype_ptr());
- }
-} // namespace plib
-
-#endif /* NLTYPES_H_ */
diff --git a/src/lib/netlist/plib/gmres.h b/src/lib/netlist/plib/gmres.h
deleted file mode 100644
index 2c357e97624..00000000000
--- a/src/lib/netlist/plib/gmres.h
+++ /dev/null
@@ -1,450 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * gmres.h
- *
- */
-
-#ifndef PLIB_GMRES_H_
-#define PLIB_GMRES_H_
-
-#include "mat_cr.h"
-#include "parray.h"
-#include "pconfig.h"
-#include "vector_ops.h"
-
-#include <algorithm>
-#include <cmath>
-
-
-namespace plib
-{
-
- template <typename FT, int SIZE>
- struct mat_precondition_ILU
- {
- using mat_type = plib::matrix_compressed_rows_t<FT, SIZE>;
-
- mat_precondition_ILU(std::size_t size, int ilu_scale = 4
- , std::size_t bw = plib::matrix_compressed_rows_t<FT, SIZE>::FILL_INFINITY)
- : m_mat(static_cast<typename mat_type::index_type>(size))
- , m_LU(static_cast<typename mat_type::index_type>(size))
- , m_use_iLU_preconditioning(ilu_scale >= 0)
- , m_ILU_scale(static_cast<std::size_t>(ilu_scale))
- , m_band_width(bw)
- {
- }
-
- template <typename M>
- void build(M &fill)
- {
- m_mat.build_from_fill_mat(fill, 0);
- if (m_use_iLU_preconditioning)
- {
- m_LU.gaussian_extend_fill_mat(fill);
- m_LU.build_from_fill_mat(fill, m_ILU_scale, m_band_width); // ILU(2)
- //m_LU.build_from_fill_mat(fill, 9999, 20); // Band matrix width 20
- }
- }
-
-
- template<typename R, typename V>
- void calc_rhs(R &rhs, const V &v)
- {
- m_mat.mult_vec(rhs, v);
- }
-
- void precondition()
- {
- if (m_use_iLU_preconditioning)
- {
- if (m_ILU_scale < 1)
- m_LU.raw_copy_from(m_mat);
- else
- m_LU.reduction_copy_from(m_mat);
- m_LU.incomplete_LU_factorization();
- }
- }
-
- template<typename V>
- void solve_LU_inplace(V &v)
- {
- if (m_use_iLU_preconditioning)
- {
- m_LU.solveLUx(v);
- }
- }
-
- PALIGNAS_VECTOROPT()
- mat_type m_mat;
- PALIGNAS_VECTOROPT()
- mat_type m_LU;
- bool m_use_iLU_preconditioning;
- std::size_t m_ILU_scale;
- std::size_t m_band_width;
- };
-
- template <typename FT, int SIZE>
- struct mat_precondition_diag
- {
- mat_precondition_diag(std::size_t size)
- : m_mat(size)
- , m_diag(size)
- , m_use_iLU_preconditioning(true)
- {
- }
-
- template <typename M>
- void build(M &fill)
- {
- m_mat.build_from_fill_mat(fill, 0);
- }
-
- template<typename R, typename V>
- void calc_rhs(R &rhs, const V &v)
- {
- m_mat.mult_vec(rhs, v);
- }
-
- void precondition()
- {
- if (m_use_iLU_preconditioning)
- {
- for (std::size_t i = 0; i< m_diag.size(); i++)
- {
- m_diag[i] = 1.0 / m_mat.A[m_mat.diag[i]];
- }
- }
- }
-
- template<typename V>
- void solve_LU_inplace(V &v)
- {
- if (m_use_iLU_preconditioning)
- {
- for (std::size_t i = 0; i< m_diag.size(); i++)
- v[i] = v[i] * m_diag[i];
- }
- }
-
- plib::matrix_compressed_rows_t<FT, SIZE> m_mat;
- plib::parray<FT, SIZE> m_diag;
- bool m_use_iLU_preconditioning;
- };
-
- /* FIXME: hardcoding RESTART to 20 becomes an issue on very large
- * systems.
- */
- template <typename FT, int SIZE, int RESTART = 20>
- struct gmres_t
- {
- public:
-
- using float_type = FT;
- // FIXME: dirty hack to make this compile
- static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS();
-
- gmres_t(std::size_t size)
- : residual(size)
- , Ax(size)
- , m_size(size)
- , m_use_more_precise_stop_condition(false)
- {
- }
-
- void givens_mult( const FT c, const FT s, FT & g0, FT & g1 )
- {
- const FT g0_last(g0);
-
- g0 = c * g0 - s * g1;
- g1 = s * g0_last + c * g1;
- }
-
- std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); }
-
- template <typename OPS, typename VT, typename VRHS>
- std::size_t solve(OPS &ops, VT &x, const VRHS & rhs, const std::size_t itr_max, float_type accuracy)
- {
- /*-------------------------------------------------------------------------
- * The code below was inspired by code published by John Burkardt under
- * the LPGL here:
- *
- * http://people.sc.fsu.edu/~jburkardt/cpp_src/mgmres/mgmres.html
- *
- * The code below was completely written from scratch based on the pseudo code
- * found here:
- *
- * http://de.wikipedia.org/wiki/GMRES-Verfahren
- *
- * The Algorithm itself is described in
- *
- * Yousef Saad,
- * Iterative Methods for Sparse Linear Systems,
- * Second Edition,
- * SIAM, 20003,
- * ISBN: 0898715342,
- * LC: QA188.S17.
- *
- *------------------------------------------------------------------------*/
-
- std::size_t itr_used = 0;
- double rho_delta = 0.0;
-
- const std::size_t n = size();
-
- ops.precondition();
-
- if (m_use_more_precise_stop_condition)
- {
- /* derive residual for a given delta x
- *
- * LU y = A dx
- *
- * ==> rho / accuracy = sqrt(y * y)
- *
- * This approach will approximate the iterative stop condition
- * based |xnew - xold| pretty precisely. But it is slow, or expressed
- * differently: The invest doesn't pay off.
- */
-
- vec_set_scalar(n, residual, accuracy);
- ops.calc_rhs(Ax, residual);
-
- ops.solve_LU_inplace(Ax);
-
- const float_type rho_to_accuracy = std::sqrt(vec_mult2<FT>(n, Ax)) / accuracy;
-
- rho_delta = accuracy * rho_to_accuracy;
- }
- else
- rho_delta = accuracy * std::sqrt(static_cast<FT>(n));
-
- /*
- * Using
- *
- * vec_set(n, x, rhs);
- * ops.solve_LU_inplace(x);
- *
- * to get a starting point for x degrades convergence speed compared
- * to using the last solution for x.
- *
- * LU x = b; solve for x;
- *
- */
-
- while (itr_used < itr_max)
- {
- std::size_t last_k = RESTART;
- float_type rho;
-
- ops.calc_rhs(Ax, x);
-
- vec_sub(n, residual, rhs, Ax);
-
- ops.solve_LU_inplace(residual);
-
- rho = std::sqrt(vec_mult2<FT>(n, residual));
-
- if (rho < rho_delta)
- return itr_used + 1;
-
- /* FIXME: The "+" is necessary to avoid link issues
- * on some systems / compiler versions. Issue reported by
- * AJR, no details known yet.
- */
- vec_set_scalar(RESTART+1, m_g, +constants<FT>::zero());
- m_g[0] = rho;
-
- //for (std::size_t i = 0; i < mr + 1; i++)
- // vec_set_scalar(mr, m_ht[i], NL_FCONST(0.0));
-
- vec_mult_scalar(n, m_v[0], residual, constants<FT>::one() / rho);
-
- for (std::size_t k = 0; k < RESTART; k++)
- {
- const std::size_t kp1 = k + 1;
-
- ops.calc_rhs(m_v[kp1], m_v[k]);
- ops.solve_LU_inplace(m_v[kp1]);
-
- for (std::size_t j = 0; j <= k; j++)
- {
- m_ht[j][k] = vec_mult<FT>(n, m_v[kp1], m_v[j]);
- vec_add_mult_scalar(n, m_v[kp1], m_v[j], -m_ht[j][k]);
- }
- m_ht[kp1][k] = std::sqrt(vec_mult2<FT>(n, m_v[kp1]));
-
- if (m_ht[kp1][k] != 0.0)
- vec_scale(n, m_v[kp1], constants<FT>::one() / m_ht[kp1][k]);
-
- for (std::size_t j = 0; j < k; j++)
- givens_mult(m_c[j], m_s[j], m_ht[j][k], m_ht[j+1][k]);
-
- const float_type mu = 1.0 / std::hypot(m_ht[k][k], m_ht[kp1][k]);
-
- m_c[k] = m_ht[k][k] * mu;
- m_s[k] = -m_ht[kp1][k] * mu;
- m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[kp1][k];
- m_ht[kp1][k] = 0.0;
-
- givens_mult(m_c[k], m_s[k], m_g[k], m_g[kp1]);
-
- rho = std::abs(m_g[kp1]);
-
- itr_used = itr_used + 1;
-
- if (rho <= rho_delta)
- {
- last_k = k;
- break;
- }
- }
-
- if (last_k >= RESTART)
- /* didn't converge within accuracy */
- last_k = RESTART - 1;
-
- /* Solve the system H * y = g */
- /* x += m_v[j] * m_y[j] */
- for (std::size_t i = last_k + 1; i-- > 0;)
- {
- double tmp = m_g[i];
- for (std::size_t j = i + 1; j <= last_k; j++)
- tmp -= m_ht[i][j] * m_y[j];
- m_y[i] = tmp / m_ht[i][i];
- }
-
- for (std::size_t i = 0; i <= last_k; i++)
- vec_add_mult_scalar(n, x, m_v[i], m_y[i]);
-
- if (rho <= rho_delta)
- break;
-
- }
- return itr_used;
- }
-
- private:
-
- //typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
-
- plib::parray<float_type, SIZE> residual;
- plib::parray<float_type, SIZE> Ax;
-
- plib::parray<float_type, RESTART + 1> m_c; /* mr + 1 */
- plib::parray<float_type, RESTART + 1> m_g; /* mr + 1 */
- plib::parray<plib::parray<float_type, RESTART>, RESTART + 1> m_ht; /* (mr + 1), mr */
- plib::parray<float_type, RESTART + 1> m_s; /* mr + 1 */
- plib::parray<float_type, RESTART + 1> m_y; /* mr + 1 */
-
- //plib::parray<float_type, SIZE> m_v[RESTART + 1]; /* mr + 1, n */
- plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
-
- std::size_t m_size;
-
- bool m_use_more_precise_stop_condition;
-
-
- };
-
-
-#if 0
- /* Example of a Chebyshev iteration solver. This one doesn't work yet,
- * it needs to be extended for non-symmetric matrix operation and
- * depends on spectral radius estimates - which we don't have.
- *
- * Left here as another example.
- */
-
- template <typename FT, int SIZE>
- struct ch_t
- {
- public:
-
- typedef FT float_type;
- // FIXME: dirty hack to make this compile
- static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS();
-
- // Maximum iterations before a restart ...
- static constexpr const std::size_t restart_N = (storage_N > 0 ? 20 : 0);
-
- ch_t(std::size_t size)
- : residual(size)
- , Ax(size)
- , m_size(size)
- {
- }
-
- std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); }
-
- template <typename OPS, typename VT, typename VRHS>
- std::size_t solve(OPS &ops, VT &x0, const VRHS & rhs, const std::size_t iter_max, float_type accuracy)
- {
- /*-------------------------------------------------------------------------
- *
- *
- *------------------------------------------------------------------------*/
-
- ops.precondition();
-
- const FT lmax = 20.0;
- const FT lmin = 0.0001;
-
- const FT d = (lmax+lmin)/2.0;
- const FT c = (lmax-lmin)/2.0;
- FT alpha = 0;
- FT beta = 0;
- std::size_t itr_used = 0;
-
- plib::parray<FT, SIZE> x(size());
- plib::parray<FT, SIZE> p(size());
-
- plib::vec_set(size(), x, x0);
-
- ops.calc_rhs(Ax, x);
- vec_sub(size(), rhs, Ax, residual);
-
- FT rho_delta = accuracy * std::sqrt(static_cast<FT>(size()));
-
- rho_delta = 1e-9;
-
- for (int i = 0; i < iter_max; i++)
- {
- ops.solve_LU_inplace(residual);
- if (i==0)
- {
- vec_set(size(), p, residual);
- alpha = 2.0 / d;
- }
- else
- {
- beta = alpha * ( c / 2.0)*( c / 2.0);
- alpha = 1.0 / (d - beta);
- for (std::size_t k = 0; k < size(); k++)
- p[k] = residual[k] + beta * p[k];
- }
- plib::vec_add_mult_scalar(size(), p, alpha, x);
- ops.calc_rhs(Ax, x);
- plib::vec_sub(size(), rhs, Ax, residual);
- FT rho = std::sqrt(plib::vec_mult2<FT>(size(), residual));
- if (rho < rho_delta)
- break;
- itr_used++;
- }
- return itr_used;
- }
- private:
-
- //typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
-
- plib::parray<float_type, SIZE> residual;
- plib::parray<float_type, SIZE> Ax;
-
- std::size_t m_size;
-
- };
-#endif
-
-} // namespace plib
-
-#endif /* PLIB_GMRES_H_ */
diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h
deleted file mode 100644
index 4cc027f0d8f..00000000000
--- a/src/lib/netlist/plib/mat_cr.h
+++ /dev/null
@@ -1,530 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * mat_cr.h
- *
- * Compressed row format matrices
- *
- */
-
-#ifndef MAT_CR_H_
-#define MAT_CR_H_
-
-#include "palloc.h"
-#include "parray.h"
-#include "pconfig.h"
-#include "pomp.h"
-#include "pstate.h"
-#include "ptypes.h"
-#include "putil.h"
-
-#include <algorithm>
-#include <array>
-#include <cmath>
-#include <cstdlib>
-#include <type_traits>
-#include <vector>
-
-namespace plib
-{
-
- // FIXME: causes a crash with GMRES handler
- // template<typename T, int N, typename C = std::size_t>
-
- template<typename T, int N, typename C = uint16_t>
- struct matrix_compressed_rows_t
- {
- using index_type = C;
- using value_type = T;
-
- COPYASSIGNMOVE(matrix_compressed_rows_t, default)
-
- enum constants_e
- {
- FILL_INFINITY = 9999999
- };
-
- parray<index_type, N> diag; // diagonal index pointer n
- parray<index_type, (N == 0) ? 0 : (N < 0 ? N - 1 : N + 1)> row_idx; // row index pointer n + 1
- parray<index_type, N < 0 ? -N * N : N *N> col_idx; // column index array nz_num, initially (n * n)
- parray<value_type, N < 0 ? -N * N : N *N> A; // Matrix elements nz_num, initially (n * n)
- //parray<C, N < 0 ? -N * (N-1) / 2 : N * (N+1) / 2 > nzbd; // Support for gaussian elimination
- parray<std::vector<index_type>, N > nzbd; // Support for gaussian elimination
- // contains elimination rows below the diagonal
- // FIXME: convert to pvector
- std::vector<std::vector<index_type>> m_ge_par;
-
- index_type nz_num;
-
- explicit matrix_compressed_rows_t(const index_type n)
- : diag(n)
- , row_idx(n+1)
- , col_idx(n*n)
- , A(n*n)
- //, nzbd(n * (n+1) / 2)
- , nzbd(n)
- , nz_num(0)
- , m_size(n)
- {
- for (index_type i=0; i<n+1; i++)
- row_idx[i] = 0;
- }
-
- ~matrix_compressed_rows_t() = default;
-
- constexpr index_type size() const { return static_cast<index_type>((N>0) ? N : m_size); }
-
- void clear()
- {
- nz_num = 0;
- for (index_type i=0; i < size() + 1; i++)
- row_idx[i] = 0;
- }
-
- void set_scalar(const T scalar)
- {
- for (index_type i=0, e=nz_num; i<e; i++)
- A[i] = scalar;
- }
-
- void set(C r, C c, T val)
- {
- C ri = row_idx[r];
- while (ri < row_idx[r+1] && col_idx[ri] < c)
- ri++;
- // we have the position now;
- if (ri < row_idx[r+1] && col_idx[ri] == c)
- A[ri] = val;
- else
- {
- for (C i = nz_num; i>ri; i--)
- {
- A[i] = A[i-1];
- col_idx[i] = col_idx[i-1];
- }
- A[ri] = val;
- col_idx[ri] = c;
- for (C i = r + 1; i < size() + 1; i++)
- row_idx[i]++;
- nz_num++;
- if (c==r)
- diag[r] = ri;
- }
- }
-
- template <typename M>
- std::pair<std::size_t, std::size_t> gaussian_extend_fill_mat(M &fill)
- {
- std::size_t ops = 0;
- std::size_t fill_max = 0;
-
- for (std::size_t k = 0; k < fill.size(); k++)
- {
- ops++; // 1/A(k,k)
- for (std::size_t row = k + 1; row < fill.size(); row++)
- {
- if (fill[row][k] < FILL_INFINITY)
- {
- ops++;
- for (std::size_t col = k + 1; col < fill[row].size(); col++)
- //if (fill[k][col] < FILL_INFINITY)
- {
- auto f = std::min(fill[row][col], 1 + fill[row][k] + fill[k][col]);
- if (f < FILL_INFINITY)
- {
- if (f > fill_max)
- fill_max = f;
- ops += 2;
- }
- fill[row][col] = f;
- }
- }
- }
- }
- build_parallel_gaussian_execution_scheme(fill);
- return { fill_max, ops };
- }
-
- template <typename M>
- void build_from_fill_mat(const M &f, std::size_t max_fill = FILL_INFINITY - 1,
- std::size_t band_width = FILL_INFINITY)
- {
- C nz = 0;
- if (nz_num != 0)
- throw pexception("build_from_mat only allowed on empty CR matrix");
- for (std::size_t k=0; k < size(); k++)
- {
- row_idx[k] = nz;
-
- for (std::size_t j=0; j < size(); j++)
- if (f[k][j] <= max_fill && std::abs(static_cast<int>(k)-static_cast<int>(j)) <= static_cast<int>(band_width))
- {
- col_idx[nz] = static_cast<C>(j);
- if (j == k)
- diag[k] = nz;
- nz++;
- }
- }
-
- row_idx[size()] = nz;
- nz_num = nz;
- /* build nzbd */
-
- for (std::size_t k=0; k < size(); k++)
- {
- for (std::size_t j=k + 1; j < size(); j++)
- if (f[j][k] < FILL_INFINITY)
- nzbd[k].push_back(static_cast<C>(j));
- nzbd[k].push_back(0); // end of sequence
- }
- }
-
- template <typename V>
- void gaussian_elimination(V & RHS)
- {
- const std::size_t iN = size();
-
- for (std::size_t i = 0; i < iN - 1; i++)
- {
- std::size_t nzbdp = 0;
- std::size_t pi = diag[i];
- const value_type f = 1.0 / A[pi++];
- const std::size_t piie = row_idx[i+1];
- const auto &nz = nzbd[i];
-
- while (auto j = nz[nzbdp++])
- {
- // proceed to column i
-
- std::size_t pj = row_idx[j];
-
- while (col_idx[pj] < i)
- pj++;
-
- const value_type f1 = - A[pj++] * f;
-
- // subtract row i from j
- // fill-in available assumed, i.e. matrix was prepared
-
- for (std::size_t pii = pi; pii<piie; pii++)
- {
- while (col_idx[pj] < col_idx[pii])
- pj++;
- if (col_idx[pj] == col_idx[pii])
- A[pj++] += A[pii] * f1;
- }
-
- RHS[j] += f1 * RHS[i];
- }
- }
- }
-
- template <typename V>
- void gaussian_elimination_parallel(V & RHS)
- {
- // FIXME: move into solver creation ...
- plib::omp::set_num_threads(4);
- for (auto l = 0ul; l < m_ge_par.size(); l++)
- plib::omp::for_static(0ul, m_ge_par[l].size(), [this, &RHS, &l] (unsigned ll)
- {
- auto &i = m_ge_par[l][ll];
- {
- std::size_t nzbdp = 0;
- std::size_t pi = diag[i];
- const value_type f = 1.0 / A[pi++];
- const std::size_t piie = row_idx[i+1];
-
- while (auto j = nzbd[i][nzbdp++])
- {
- // proceed to column i
-
- std::size_t pj = row_idx[j];
-
- while (col_idx[pj] < i)
- pj++;
-
- const value_type f1 = - A[pj++] * f;
-
- // subtract row i from j
- // fill-in available assumed, i.e. matrix was prepared
- for (std::size_t pii = pi; pii<piie; pii++)
- {
- while (col_idx[pj] < col_idx[pii])
- pj++;
- if (col_idx[pj] == col_idx[pii])
- A[pj++] += A[pii] * f1;
- }
- RHS[j] += f1 * RHS[i];
- }
- }
- });
- }
-
- template <typename V1, typename V2>
- void gaussian_back_substitution(V1 &V, const V2 &RHS)
- {
- const std::size_t iN = size();
- /* row n-1 */
- V[iN - 1] = RHS[iN - 1] / A[diag[iN - 1]];
-
- for (std::size_t j = iN - 1; j-- > 0;)
- {
- value_type tmp = 0;
- const auto jdiag = diag[j];
- const std::size_t e = row_idx[j+1];
- for (std::size_t pk = jdiag + 1; pk < e; pk++)
- tmp += A[pk] * V[col_idx[pk]];
- V[j] = (RHS[j] - tmp) / A[jdiag];
- }
- }
-
- template <typename V1>
- void gaussian_back_substitution(V1 &V)
- {
- const std::size_t iN = size();
- /* row n-1 */
- V[iN - 1] = V[iN - 1] / A[diag[iN - 1]];
-
- for (std::size_t j = iN - 1; j-- > 0;)
- {
- value_type tmp = 0;
- const auto jdiag = diag[j];
- const std::size_t e = row_idx[j+1];
- for (std::size_t pk = jdiag + 1; pk < e; pk++)
- tmp += A[pk] * V[col_idx[pk]];
- V[j] = (V[j] - tmp) / A[jdiag];
- }
- }
-
-
- template <typename VTV, typename VTR>
- void mult_vec(VTR & res, const VTV & x)
- {
- /*
- * res = A * x
- */
-
- std::size_t row = 0;
- std::size_t k = 0;
- const std::size_t oe = nz_num;
-
- while (k < oe)
- {
- T tmp = 0.0;
- const std::size_t e = row_idx[row+1];
- for (; k < e; k++)
- tmp += A[k] * x[col_idx[k]];
- res[row++] = tmp;
- }
- }
-
- /* throws error if P(source)>P(destination) */
- template <typename LUMAT>
- void slim_copy_from(LUMAT & src)
- {
- for (std::size_t r=0; r<src.size(); r++)
- {
- C dp = row_idx[r];
- for (C sp = src.row_idx[r]; sp < src.row_idx[r+1]; sp++)
- {
- /* advance dp to source column and fill 0s if necessary */
- while (col_idx[dp] < src.col_idx[sp])
- A[dp++] = 0;
- if (row_idx[r+1] <= dp || col_idx[dp] != src.col_idx[sp])
- throw plib::pexception("slim_copy_from error");
- A[dp++] = src.A[sp];
- }
- /* fill remaining elements in row */
- while (dp < row_idx[r+1])
- A[dp++] = 0;
- }
- }
-
- /* only copies common elements */
- template <typename LUMAT>
- void reduction_copy_from(LUMAT & src)
- {
- C sp = 0;
- for (std::size_t r=0; r<src.size(); r++)
- {
- C dp = row_idx[r];
- while(sp < src.row_idx[r+1])
- {
- /* advance dp to source column and fill 0s if necessary */
- if (col_idx[dp] < src.col_idx[sp])
- A[dp++] = 0;
- else if (col_idx[dp] == src.col_idx[sp])
- A[dp++] = src.A[sp++];
- else
- sp++;
- }
- /* fill remaining elements in row */
- while (dp < row_idx[r+1])
- A[dp++] = 0;
- }
- }
-
- /* checks at all - may crash */
- template <typename LUMAT>
- void raw_copy_from(LUMAT & src)
- {
- for (std::size_t k = 0; k < nz_num; k++)
- A[k] = src.A[k];
- }
-
- void incomplete_LU_factorization()
- {
- /*
- * incomplete LU Factorization according to http://de.wikipedia.org/wiki/ILU-Zerlegung
- *
- * Result is stored in matrix LU
- *
- * For i = 1,...,N-1
- * For k = 0, ... , i - 1
- * If a[i,k] != 0
- * a[i,k] = a[i,k] / a[k,k]
- * For j = k + 1, ... , N - 1
- * If a[i,j] != 0
- * a[i,j] = a[i,j] - a[i,k] * a[k,j]
- * j=j+1
- * k=k+1
- * i=i+1
- *
- */
-
- for (std::size_t i = 1; i < size(); i++) // row i
- {
- const std::size_t p_i_end = row_idx[i + 1];
- // loop over all columns k left of diag in row i
- for (std::size_t i_k = row_idx[i]; i_k < diag[i]; i_k++)
- {
- const std::size_t k = col_idx[i_k];
- const std::size_t p_k_end = row_idx[k + 1];
- const T LUp_i_k = A[i_k] = A[i_k] / A[diag[k]];
-
- std::size_t k_j = diag[k] + 1;
- std::size_t i_j = i_k + 1;
-
- while (i_j < p_i_end && k_j < p_k_end ) // pj = (i, j)
- {
- // we can assume that within a row ja increases continuously */
- const std::size_t c_i_j = col_idx[i_j]; // row i, column j
- const std::size_t c_k_j = col_idx[k_j]; // row i, column j
- if (c_k_j < c_i_j)
- k_j++;
- else if (c_k_j == c_i_j)
- A[i_j++] -= LUp_i_k * A[k_j++];
- else
- i_j++;
- }
- }
- }
- }
-
- template <typename R>
- void solveLUx (R &r)
- {
- /*
- * Solve a linear equation Ax = r
- * where
- * A = L*U
- *
- * L unit lower triangular
- * U upper triangular
- *
- * ==> LUx = r
- *
- * ==> Ux = L⁻¹ r = w
- *
- * ==> r = Lw
- *
- * This can be solved for w using backwards elimination in L.
- *
- * Now Ux = w
- *
- * This can be solved for x using backwards elimination in U.
- *
- */
- for (std::size_t i = 1; i < size(); ++i )
- {
- T tmp = 0.0;
- const std::size_t j1 = row_idx[i];
- const std::size_t j2 = diag[i];
-
- for (std::size_t j = j1; j < j2; ++j )
- tmp += A[j] * r[col_idx[j]];
- r[i] -= tmp;
- }
- // i now is equal to n;
- for (std::size_t i = size(); i-- > 0; )
- {
- T tmp = 0.0;
- const std::size_t di = diag[i];
- const std::size_t j2 = row_idx[i+1];
- for (std::size_t j = di + 1; j < j2; j++ )
- tmp += A[j] * r[col_idx[j]];
- r[i] = (r[i] - tmp) / A[di];
- }
- }
- private:
- template <typename M>
- void build_parallel_gaussian_execution_scheme(const M &fill)
- {
- // calculate parallel scheme for gaussian elimination
- std::vector<std::vector<index_type>> rt(size());
- for (index_type k = 0; k < size(); k++)
- {
- for (index_type j = k+1; j < size(); j++)
- {
- if (fill[j][k] < FILL_INFINITY)
- {
- rt[k].push_back(j);
- }
- }
- }
-
- std::vector<index_type> levGE(size(), 0);
- index_type cl = 0;
-
- for (index_type k = 0; k < size(); k++ )
- {
- if (levGE[k] >= cl)
- {
- std::vector<index_type> t = rt[k];
- for (index_type j = k+1; j < size(); j++ )
- {
- bool overlap = false;
- // is there overlap
- if (plib::container::contains(t, j))
- overlap = true;
- for (auto &x : rt[j])
- if (plib::container::contains(t, x))
- {
- overlap = true;
- break;
- }
- if (overlap)
- levGE[j] = cl + 1;
- else
- {
- t.push_back(j);
- for (auto &x : rt[j])
- t.push_back(x);
- }
- }
- cl++;
- }
- }
-
- m_ge_par.clear();
- m_ge_par.resize(cl+1);
- for (index_type k = 0; k < size(); k++)
- m_ge_par[levGE[k]].push_back(k);
- }
-
- index_type m_size;
- };
-
-} // namespace plib
-
-#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp
new file mode 100644
index 00000000000..e4d31985b23
--- /dev/null
+++ b/src/lib/netlist/plib/palloc.cpp
@@ -0,0 +1,105 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * palloc.c
+ *
+ */
+
+#include "pconfig.h"
+#include "palloc.h"
+#include "pfmtlog.h"
+
+#include <algorithm>
+
+namespace plib {
+
+//============================================================
+// Memory pool
+//============================================================
+
+mempool::mempool(size_t min_alloc, size_t min_align)
+: m_min_alloc(min_alloc), m_min_align(min_align)
+{
+}
+mempool::~mempool()
+{
+ for (auto & b : m_blocks)
+ {
+ if (b.m_num_alloc != 0)
+ {
+ fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc));
+ }
+ ::operator delete(b.data);
+ }
+ m_blocks.clear();
+}
+
+size_t mempool::new_block()
+{
+ block b;
+ b.data = static_cast<char *>(::operator new(m_min_alloc));
+ b.cur_ptr = b.data;
+ b.m_free = m_min_alloc;
+ b.m_num_alloc = 0;
+ m_blocks.push_back(b);
+ return m_blocks.size() - 1;
+}
+
+size_t mempool::mininfosize()
+{
+ size_t sinfo = sizeof(mempool::info);
+#ifdef __APPLE__
+ size_t ma = 16;
+#else
+ size_t ma = 8;
+#endif
+ return ((std::max(m_min_align, sinfo) + ma - 1) / ma) * ma;
+}
+
+void *mempool::alloc(size_t size)
+{
+ size_t rs = (size + mininfosize() + m_min_align - 1) & ~(m_min_align - 1);
+ for (size_t bn=0; bn < m_blocks.size(); bn++)
+ {
+ auto &b = m_blocks[bn];
+ if (b.m_free > rs)
+ {
+ b.m_free -= rs;
+ b.m_num_alloc++;
+ auto i = reinterpret_cast<info *>(b.cur_ptr);
+ i->m_block = bn;
+ auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
+ b.cur_ptr += rs;
+ return ret;
+ }
+ }
+ {
+ size_t bn = new_block();
+ auto &b = m_blocks[bn];
+ b.m_num_alloc = 1;
+ b.m_free = m_min_alloc - rs;
+ auto i = reinterpret_cast<info *>(b.cur_ptr);
+ i->m_block = bn;
+ auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize());
+ b.cur_ptr += rs;
+ return ret;
+ }
+}
+
+void mempool::free(void *ptr)
+{
+ auto p = reinterpret_cast<char *>(ptr);
+
+ auto i = reinterpret_cast<info *>(p - mininfosize());
+ block *b = &m_blocks[i->m_block];
+ if (b->m_num_alloc == 0)
+ fprintf(stderr, "Argh .. double free\n");
+ else
+ {
+ //b->m_free = m_min_alloc;
+ //b->cur_ptr = b->data;
+ }
+ b->m_num_alloc--;
+}
+
+}
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index 15fede3a99b..a35bc50ff17 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -8,427 +8,172 @@
#ifndef PALLOC_H_
#define PALLOC_H_
-#include "pconfig.h"
#include "pstring.h"
-#include "ptypes.h"
-#include <cstddef>
-#include <cstdlib>
-#include <memory>
-#include <type_traits>
-#include <utility>
#include <vector>
-
-#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
-#include <malloc.h>
-#endif
+#include <memory>
namespace plib {
- //============================================================
- // Standard arena_deleter
- //============================================================
-
- template <typename P, typename T>
- struct arena_deleter
- {
- //using arena_storage_type = P *;
- using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
- template <typename X, typename Y = void>
- typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
- template <typename X, typename Y = void *>
- typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
- getref(X &x, Y y = nullptr)
- {
- unused_var(y);
- return x;
- }
-
- constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept
- : m_a(a) { }
-
- template<typename PU, typename U, typename = typename
- std::enable_if<std::is_convertible< U*, T*>::value>::type>
- arena_deleter(const arena_deleter<PU, U> &rhs) noexcept : m_a(rhs.m_a) { }
-
- void operator()(T *p) //const
- {
- /* call destructor */
- p->~T();
- getref(m_a).deallocate(p);
- }
- //private:
- arena_storage_type m_a;
- };
-
- //============================================================
- // owned_ptr: smart pointer with ownership information
- //============================================================
-
- template <typename SC, typename D>
- class owned_ptr
- {
- public:
-
- using pointer = SC *;
- using element_type = SC;
- using deleter_type = D;
-
- owned_ptr()
- : m_ptr(nullptr), m_deleter(), m_is_owned(true) { }
-
- template <typename, typename>
- friend class owned_ptr;
-
- owned_ptr(pointer p, bool owned) noexcept
- : m_ptr(p), m_deleter(), m_is_owned(owned)
- { }
-
- owned_ptr(pointer p, bool owned, D deleter) noexcept
- : m_ptr(p), m_deleter(deleter), m_is_owned(owned)
- { }
-
-
- owned_ptr(const owned_ptr &r) = delete;
- owned_ptr & operator =(owned_ptr &r) = delete;
-
- template<typename DC, typename DC_D>
- owned_ptr & operator =(owned_ptr<DC, DC_D> &&r)
- {
- if (m_is_owned && (m_ptr != nullptr))
- //delete m_ptr;
- m_deleter(m_ptr);
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- m_deleter = r.m_deleter;
- r.m_is_owned = false;
- r.m_ptr = nullptr;
- return *this;
- }
-
- owned_ptr(owned_ptr &&r) noexcept
- : m_ptr(r.m_ptr)
- , m_deleter(r.m_deleter)
- , m_is_owned(r.m_is_owned)
- {
- r.m_is_owned = false;
- r.m_ptr = nullptr;
- }
-
- owned_ptr &operator=(owned_ptr &&r) noexcept
- {
- if (m_is_owned && (m_ptr != nullptr))
- //delete m_ptr;
- m_deleter(m_ptr);
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- m_deleter = std::move(r.m_deleter);
- r.m_is_owned = false;
- r.m_ptr = nullptr;
- return *this;
- }
-
- template<typename DC, typename DC_D>
- owned_ptr(owned_ptr<DC, DC_D> &&r) noexcept
- : m_ptr(static_cast<pointer >(r.get()))
- , m_deleter(r.m_deleter)
- , m_is_owned(r.is_owned())
- {
- r.release();
- }
-
- ~owned_ptr() noexcept
- {
- if (m_is_owned && (m_ptr != nullptr))
- {
- //delete m_ptr;
- m_deleter(m_ptr);
- }
- m_is_owned = false;
- m_ptr = nullptr;
- }
-
- /**
- * \brief Return @c true if the stored pointer is not null.
- */
- explicit operator bool() const noexcept { return m_ptr != nullptr; }
-
- pointer release()
- {
- pointer tmp = m_ptr;
- m_is_owned = false;
- m_ptr = nullptr;
- return tmp;
- }
-
- bool is_owned() const { return m_is_owned; }
-
- pointer operator ->() const noexcept { return m_ptr; }
- typename std::add_lvalue_reference<element_type>::type operator *() const noexcept { return *m_ptr; }
- pointer get() const noexcept { return m_ptr; }
-
- deleter_type& get_deleter() noexcept { return m_deleter; }
- const deleter_type& get_deleter() const noexcept { return m_deleter; }
-
- private:
- pointer m_ptr;
- D m_deleter;
- bool m_is_owned;
- };
-
- //============================================================
- // Arena allocator for use with containers
- //============================================================
-
- template <class ARENA, class T, std::size_t ALIGN = alignof(T)>
- class arena_allocator
+//============================================================
+// Memory allocation
+//============================================================
+
+template<typename T, typename... Args>
+T *palloc(Args&&... args)
+{
+ return new T(std::forward<Args>(args)...);
+}
+
+template<typename T>
+void pfree(T *ptr)
+{
+ delete ptr;
+}
+
+template<typename T>
+T* palloc_array(const std::size_t num)
+{
+ return new T[num]();
+}
+
+template<typename T>
+void pfree_array(T *ptr)
+{
+ delete [] ptr;
+}
+
+template<typename T, typename... Args>
+std::unique_ptr<T> make_unique(Args&&... args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+template<typename BC, typename DC, typename... Args>
+static std::unique_ptr<BC> make_unique_base(Args&&... args)
+{
+ std::unique_ptr<BC> ret(new DC(std::forward<Args>(args)...));
+ return ret;
+}
+
+template <typename SC>
+class owned_ptr
+{
+private:
+ owned_ptr()
+ : m_ptr(nullptr), m_is_owned(true) { }
+public:
+ owned_ptr(SC *p, bool owned) noexcept
+ : m_ptr(p), m_is_owned(owned)
+ { }
+
+ owned_ptr(const owned_ptr &r) = delete;
+ owned_ptr & operator =(owned_ptr &r) = delete;
+
+ template<typename DC>
+ owned_ptr & operator =(owned_ptr<DC> &&r)
{
- public:
- using value_type = T;
- static constexpr const std::size_t align_size = ALIGN;
- using arena_type = ARENA;
-
- static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0,
- "ALIGN must be greater than alignof(T) and a multiple");
-
- arena_allocator() noexcept
- : m_a(arena_type::instance())
- { }
-
- ~arena_allocator() noexcept = default;
-
- arena_allocator(const arena_allocator &rhs) noexcept = default;
- arena_allocator& operator=(const arena_allocator&) noexcept = delete;
-
- arena_allocator(arena_allocator&&) noexcept = default;
- arena_allocator& operator=(arena_allocator&&) = delete;
-
- arena_allocator(arena_type & a) noexcept : m_a(a)
- {
- }
-
- template <class U>
- arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept
- : m_a(rhs.m_a)
- {
- }
-
- template <class U> struct rebind
- {
- using other = arena_allocator<ARENA, U, ALIGN>;
- };
-
- T* allocate(std::size_t n)
- {
- return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
- }
-
- void deallocate(T* p, std::size_t n) noexcept
- {
- unused_var(n);
- m_a.deallocate(p);
- }
-
- template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
- friend bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
- const arena_allocator<AR2, T2, A2>& rhs) noexcept;
-
- template <class AU, class U, std::size_t A> friend class arena_allocator;
- private:
- arena_type &m_a;
- };
-
- template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
- inline bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
- const arena_allocator<AR2, T2, A2>& rhs) noexcept
- {
- return A1 == A2 && rhs.m_a == lhs.m_a;
- }
- template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2>
- inline bool operator!=(const arena_allocator<AR1, T1, A1>& lhs,
- const arena_allocator<AR2, T2, A2>& rhs) noexcept
- {
- return !(lhs == rhs);
+ if (m_is_owned && (m_ptr != nullptr))
+ delete m_ptr;
+ m_is_owned = r.m_is_owned;
+ m_ptr = r.m_ptr;
+ r.m_is_owned = false;
+ r.m_ptr = nullptr;
+ return *this;
}
- //============================================================
- // Memory allocation
- //============================================================
-
- struct aligned_arena
+ owned_ptr(owned_ptr &&r) noexcept
{
- static constexpr const bool is_stateless = true;
- template <class T, std::size_t ALIGN = alignof(T)>
- using allocator_type = arena_allocator<aligned_arena, T, ALIGN>;
-
- template <typename T>
- using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<aligned_arena, T>>;
-
- static inline aligned_arena &instance()
- {
- static aligned_arena s_arena;
- return s_arena;
- }
-
- static inline void *allocate( size_t alignment, size_t size )
- {
- #if (USE_ALIGNED_ALLOCATION)
- #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
- return _aligned_malloc(size, alignment);
- #elif defined(__APPLE__)
- void* p;
- if (::posix_memalign(&p, alignment, size) != 0) {
- p = nullptr;
- }
- return p;
- #else
- return aligned_alloc(alignment, size);
- #endif
- #else
- unused_var(alignment);
- return ::operator new(size);
- #endif
- }
-
- static inline void deallocate( void *ptr )
- {
- #if (USE_ALIGNED_ALLOCATION)
- // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
- free(ptr);
- #else
- ::operator delete(ptr);
- #endif
- }
-
- template<typename T, typename... Args>
- owned_pool_ptr<T> make_poolptr(Args&&... args)
- {
- auto *mem = allocate(alignof(T), sizeof(T));
- return owned_pool_ptr<T>(new (mem) T(std::forward<Args>(args)...), true, arena_deleter<aligned_arena, T>(*this));
- }
-
- };
-
- template <typename T, std::size_t ALIGN>
- /*inline */ C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept
- {
- static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
- static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
- //auto t = reinterpret_cast<std::uintptr_t>(p);
- //if (t & (ALIGN-1))
- // printf("alignment error!");
-#if (USE_ALIGNED_HINTS)
- return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
-#else
- return p;
-#endif
+ m_is_owned = r.m_is_owned;
+ m_ptr = r.m_ptr;
+ r.m_is_owned = false;
+ r.m_ptr = nullptr;
}
- template <typename T, std::size_t ALIGN>
- constexpr const T *assume_aligned_ptr(const T *p) noexcept
+ template<typename DC>
+ owned_ptr(owned_ptr<DC> &&r) noexcept
{
- static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
- static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
-#if (USE_ALIGNED_HINTS)
- return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
-#else
- return p;
-#endif
+ m_ptr = static_cast<SC *>(r.get());
+ m_is_owned = r.is_owned();
+ r.release();
}
- // FIXME: remove
- template<typename T, typename... Args>
- inline T *pnew(Args&&... args)
+ ~owned_ptr()
{
- auto *p = aligned_arena::allocate(alignof(T), sizeof(T));
- return new(p) T(std::forward<Args>(args)...);
+ if (m_is_owned && (m_ptr != nullptr))
+ delete m_ptr;
+ m_is_owned = false;
+ m_ptr = nullptr;
}
-
- template<typename T>
- inline void pdelete(T *ptr)
+ template<typename DC, typename... Args>
+ static owned_ptr Create(Args&&... args)
{
- ptr->~T();
- aligned_arena::deallocate(ptr);
+ owned_ptr a;
+ DC *x = new DC(std::forward<Args>(args)...);
+ a.m_ptr = static_cast<SC *>(x);
+ return std::move(a);
}
-
- template <typename T>
- using unique_ptr = std::unique_ptr<T, arena_deleter<aligned_arena, T>>;
-
- template<typename T, typename... Args>
- plib::unique_ptr<T> make_unique(Args&&... args)
+ template<typename... Args>
+ static owned_ptr Create(Args&&... args)
{
- return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...));
+ owned_ptr a;
+ a.m_ptr = new SC(std::forward<Args>(args)...);
+ return std::move(a);
}
-
-#if 0
- template<typename T, typename... Args>
- static owned_ptr<T> make_owned(Args&&... args)
+ SC * release()
{
- return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true);
+ SC *tmp = m_ptr;
+ m_is_owned = false;
+ m_ptr = nullptr;
+ return tmp;
}
-#endif
-
-
- template <class T, std::size_t ALIGN = alignof(T)>
- using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>;
-
- //============================================================
- // traits to determine alignment size and stride size
- // from types supporting alignment
- //============================================================
- PDEFINE_HAS_MEMBER(has_align, align_size);
+ bool is_owned() const { return m_is_owned; }
- template <typename T, typename X = void>
- struct align_traits
- {
- static constexpr const std::size_t align_size = alignof(std::max_align_t);
- static constexpr const std::size_t value_size = sizeof(typename T::value_type);
- static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
- };
+ SC * operator ->() const { return m_ptr; }
+ SC & operator *() const { return *m_ptr; }
+ SC * get() const { return m_ptr; }
+private:
+ SC *m_ptr;
+ bool m_is_owned;
+};
- template <typename T>
- struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type>
+class mempool
+{
+private:
+ struct block
{
- static constexpr const std::size_t align_size = T::align_size;
- static constexpr const std::size_t value_size = sizeof(typename T::value_type);
- static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
+ block() : m_num_alloc(0), m_free(0), cur_ptr(nullptr), data(nullptr) { }
+ std::size_t m_num_alloc;
+ std::size_t m_free;
+ char *cur_ptr;
+ char *data;
};
- //============================================================
- // Aligned vector
- //============================================================
+ size_t new_block();
+ size_t mininfosize();
- // FIXME: needs a separate file
- template <class T, std::size_t ALIGN = alignof(T)>
- class aligned_vector : public std::vector<T, aligned_allocator<T, ALIGN>>
+ struct info
{
- public:
- using base = std::vector<T, aligned_allocator<T, ALIGN>>;
+ info() : m_block(0) { }
+ size_t m_block;
+ };
- using reference = typename base::reference;
- using const_reference = typename base::const_reference;
- using pointer = typename base::pointer;
- using const_pointer = typename base::const_pointer;
- using size_type = typename base::size_type;
+ size_t m_min_alloc;
+ size_t m_min_align;
- using base::base;
+ std::vector<block> m_blocks;
- C14CONSTEXPR reference operator[](size_type i) noexcept
- {
- return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
- }
- constexpr const_reference operator[](size_type i) const noexcept
- {
- return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
- }
+public:
+ mempool(size_t min_alloc, size_t min_align);
+ ~mempool();
- pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
- const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
+ void *alloc(size_t size);
+ void free(void *ptr);
- };
+};
-} // namespace plib
+}
#endif /* PALLOC_H_ */
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h
deleted file mode 100644
index 1be37b908cd..00000000000
--- a/src/lib/netlist/plib/parray.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * parray.h
- *
- */
-
-#ifndef PARRAY_H_
-#define PARRAY_H_
-
-#include "palloc.h"
-#include "pconfig.h"
-#include "pexception.h"
-
-#include <array>
-#include <memory>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-namespace plib {
-
- template <typename FT, int SIZE>
- struct sizeabs
- {
- static constexpr std::size_t ABS() { return (SIZE < 0) ? static_cast<std::size_t>(0 - SIZE) : static_cast<std::size_t>(SIZE); }
- using container = typename std::array<FT, ABS()> ;
- };
-
- template <typename FT>
- struct sizeabs<FT, 0>
- {
- static constexpr const std::size_t ABS = 0;
- using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
- };
-
- /**
- * \brief Array with preallocated or dynamic allocation
- *
- * Passing SIZE > 0 has the same functionality as a std::array.
- * SIZE = 0 is pure dynamic allocation, the actual array size is passed to the
- * constructor.
- * SIZE < 0 reserves std::abs(SIZE) elements statically in place allocated. The
- * actual size is passed in by the constructor.
- * This array is purely intended for HPC application where depending on the
- * architecture a preference dynamic/static has to be made.
- *
- * This struct is not intended to be a full replacement to std::array.
- * It is a subset to enable switching between dynamic and static allocation.
- * I consider > 10% performance difference to be a use case.
- */
-
- template <typename FT, int SIZE>
- struct parray
- {
- public:
- static constexpr std::size_t SIZEABS() { return sizeabs<FT, SIZE>::ABS(); }
-
- using base_type = typename sizeabs<FT, SIZE>::container;
- using size_type = typename base_type::size_type;
- using reference = typename base_type::reference;
- using const_reference = typename base_type::const_reference;
- using value_type = typename base_type::value_type;
-
- template <int X = SIZE >
- parray(size_type size, typename std::enable_if<X==0, int>::type = 0)
- : m_a(size), m_size(size)
- {
- }
-
-#if 1
- /* allow construction in fixed size arrays */
- template <int X = SIZE >
- parray(typename std::enable_if<(X > 0), int>::type = 0)
- : m_size(X)
- {
- }
-#endif
- template <int X = SIZE >
- parray(size_type size, typename std::enable_if<X!=0, int>::type = 0)
- : m_size(size)
- {
- if (SIZE < 0 && size > SIZEABS())
- throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZEABS()));
- else if (SIZE > 0 && size != SIZEABS())
- throw plib::pexception("parray: size error");
- }
-
- inline size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); }
-
- constexpr size_type max_size() const noexcept { return base_type::max_size(); }
-
- bool empty() const noexcept { return size() == 0; }
-
-#if 0
- reference operator[](size_type i) /*noexcept*/
- {
- if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size));
- return m_a[i];
- }
- const_reference operator[](size_type i) const /*noexcept*/
- {
- if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size));
- return m_a[i];
- }
-#else
- C14CONSTEXPR reference operator[](size_type i) noexcept
- {
- return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
- }
- constexpr const_reference operator[](size_type i) const noexcept
- {
- return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
- }
-#endif
- FT * data() noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); }
- const FT * data() const noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); }
-
- private:
- PALIGNAS_VECTOROPT()
- base_type m_a;
- size_type m_size;
- };
-} // namespace plib
-
-#endif /* PARRAY_H_ */
diff --git a/src/lib/netlist/plib/pchrono.cpp b/src/lib/netlist/plib/pchrono.cpp
index 953d948e062..971d19b3645 100644
--- a/src/lib/netlist/plib/pchrono.cpp
+++ b/src/lib/netlist/plib/pchrono.cpp
@@ -49,5 +49,5 @@ exact_ticks::type exact_ticks::per_second()
#endif
-} // namespace chrono
-} // namespace plib
+}
+}
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
index 8ce0eca23b3..a229128e7b8 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -9,17 +9,16 @@
#define PCHRONO_H_
#include "pconfig.h"
-#include "ptypes.h"
-#include <chrono>
#include <cstdint>
+#include <chrono>
namespace plib {
namespace chrono {
template <typename T>
struct sys_ticks
{
- using type = typename T::rep;
+ typedef typename T::rep type;
static inline type start() { return T::now().time_since_epoch().count(); }
static inline type stop() { return T::now().time_since_epoch().count(); }
static inline constexpr type per_second() { return T::period::den / T::period::num; }
@@ -146,7 +145,7 @@ namespace chrono {
struct counter
{
counter() : m_count(0) { }
- using type = uint_least64_t;
+ typedef uint_least64_t type;
type operator()() const { return m_count; }
void inc() { ++m_count; }
void reset() { m_count = 0; }
@@ -158,7 +157,7 @@ namespace chrono {
template<>
struct counter<false>
{
- using type = uint_least64_t;
+ typedef uint_least64_t type;
constexpr type operator()() const { return 0; }
void inc() const { }
void reset() const { }
@@ -169,28 +168,15 @@ namespace chrono {
template< typename T, bool enabled_ = true>
struct timer
{
- using type = typename T::type;
- using ctype = uint_least64_t;
- constexpr static bool enabled = enabled_;
-
- struct guard_t
- {
- guard_t() = delete;
- guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); }
- ~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; }
-
- COPYASSIGNMOVE(guard_t, default)
-
- private:
- timer &m_m;
- };
-
- friend struct guard_t;
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
timer() : m_time(0), m_count(0) { }
type operator()() const { return m_time; }
+ void start() { m_time -= T::start(); }
+ void stop() { m_time += T::stop(); ++m_count; }
void reset() { m_time = 0; m_count = 0; }
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
type total() const { return m_time; }
@@ -199,7 +185,7 @@ namespace chrono {
double as_seconds() const { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
- guard_t guard() { return guard_t(*this); }
+ constexpr static bool enabled = enabled_;
private:
type m_time;
ctype m_count;
@@ -208,31 +194,19 @@ namespace chrono {
template<typename T>
struct timer<T, false>
{
- using type = typename T::type;
- using ctype = uint_least64_t;
-
- struct guard_t
- {
- guard_t() = default;
- COPYASSIGNMOVE(guard_t, default)
- /* using default constructor will trigger warning on
- * unused local variable.
- */
- // NOLINTNEXTLINE(modernize-use-equals-default)
- ~guard_t() { }
- };
-
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
constexpr type operator()() const { return 0; }
+ void start() const { }
+ void stop() const { }
void reset() const { }
constexpr type average() const { return 0; }
constexpr type total() const { return 0; }
constexpr ctype count() const { return 0; }
constexpr double as_seconds() const { return 0.0; }
constexpr static bool enabled = false;
- guard_t guard() { return guard_t(); }
};
-
} // namespace chrono
} // namespace plib
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index d66b342f815..0200c305ecd 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -21,46 +21,18 @@
* if PHAS_RDTSCP == 1
*/
#ifndef PUSE_ACCURATE_STATS
-#define PUSE_ACCURATE_STATS (0)
+#define PUSE_ACCURATE_STATS (1)
#endif
/*
* Set this to one if you want to use 128 bit int for ptime.
- * This is about 5% slower on a kaby lake processor.
+ * This is for tests only.
*/
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
#endif
-/*
- * Set this to one if you want to use aligned storage optimizations.
- */
-
-#ifndef USE_ALIGNED_OPTIMIZATIONS
-#define USE_ALIGNED_OPTIMIZATIONS (0)
-#endif
-
-#define USE_ALIGNED_ALLOCATION (USE_ALIGNED_OPTIMIZATIONS)
-#define USE_ALIGNED_HINTS (USE_ALIGNED_OPTIMIZATIONS)
-/*
- * Standard alignment macros
- */
-
-#define PALIGN_CACHELINE (64)
-#define PALIGN_VECTOROPT (64)
-
-#define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE)
-#define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT)
-
-/* Breaks mame build on windows due to -Wattribute
- * FIXME: no error on cross-compile - need further checks */
-#if defined(_WIN32) && defined(__GNUC__)
-#define PALIGNAS(x)
-#else
-#define PALIGNAS(x) alignas(x)
-#endif
-
/*============================================================
* Check for CPP Version
*
@@ -75,13 +47,6 @@
*
*============================================================*/
-#ifndef NVCCBUILD
-#define NVCCBUILD (0)
-#endif
-
-#if NVCCBUILD
-#define C14CONSTEXPR
-#else
#if __cplusplus == 201103L
#define C14CONSTEXPR
#elif __cplusplus == 201402L
@@ -93,7 +58,6 @@
#else
#error "C++ version not supported"
#endif
-#endif
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
@@ -104,6 +68,17 @@ typedef __uint128_t UINT128;
typedef __int128_t INT128;
#endif
+#if defined(__GNUC__)
+#ifdef RESTRICT
+#undef RESTRICT
+#endif
+#define RESTRICT __restrict__
+#define ATTR_UNUSED __attribute__((__unused__))
+#else
+#define RESTRICT
+#define ATTR_UNUSED
+#endif
+
//============================================================
// Standard defines
//============================================================
diff --git a/src/lib/netlist/plib/pdynlib.cpp b/src/lib/netlist/plib/pdynlib.cpp
index 0d32bead51d..13827eaf24c 100644
--- a/src/lib/netlist/plib/pdynlib.cpp
+++ b/src/lib/netlist/plib/pdynlib.cpp
@@ -25,7 +25,7 @@ CHAR *astring_from_utf8(const char *utf8string)
// convert UTF-16 to "ANSI code page" string
char_count = WideCharToMultiByte(CP_ACP, 0, wstring, -1, nullptr, 0, nullptr, nullptr);
- result = new CHAR[char_count];
+ result = palloc_array<CHAR>(char_count);
if (result != nullptr)
WideCharToMultiByte(CP_ACP, 0, wstring, -1, result, char_count, nullptr, nullptr);
@@ -39,7 +39,7 @@ WCHAR *wstring_from_utf8(const char *utf8string)
// convert MAME string (UTF-8) to UTF-16
char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, nullptr, 0);
- result = new WCHAR[char_count];
+ result = palloc_array<WCHAR>(char_count);
if (result != nullptr)
MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
@@ -58,7 +58,7 @@ WCHAR *wstring_from_utf8(const char *utf8string)
#endif
namespace plib {
-dynlib::dynlib(const pstring &libname)
+dynlib::dynlib(const pstring libname)
: m_isLoaded(false), m_lib(nullptr)
{
#ifdef _WIN32
@@ -72,7 +72,7 @@ dynlib::dynlib(const pstring &libname)
m_isLoaded = true;
//else
// fprintf(stderr, "win: library <%s> not found!\n", libname.c_str());
- delete [] buffer;
+ pfree_array(buffer);
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -88,11 +88,9 @@ dynlib::dynlib(const pstring &libname)
#endif
}
-dynlib::dynlib(const pstring &path, const pstring &libname)
+dynlib::dynlib(const pstring path, const pstring libname)
: m_isLoaded(false), m_lib(nullptr)
{
- // FIXME: implement path search
- plib::unused_var(path);
// printf("win: loading <%s>\n", libname.c_str());
#ifdef _WIN32
TCHAR *buffer = tstring_from_utf8(libname.c_str());
@@ -106,7 +104,7 @@ dynlib::dynlib(const pstring &path, const pstring &libname)
{
//printf("win: library <%s> not found!\n", libname.c_str());
}
- delete [] buffer;
+ pfree_array(buffer);
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -141,7 +139,7 @@ bool dynlib::isLoaded() const
return m_isLoaded;
}
-void *dynlib::getsym_p(const pstring &name)
+void *dynlib::getsym_p(const pstring name)
{
#ifdef _WIN32
return (void *) GetProcAddress((HMODULE) m_lib, name.c_str());
@@ -150,4 +148,4 @@ void *dynlib::getsym_p(const pstring &name)
#endif
}
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pdynlib.h b/src/lib/netlist/plib/pdynlib.h
index 1454c053298..7c9412593c9 100644
--- a/src/lib/netlist/plib/pdynlib.h
+++ b/src/lib/netlist/plib/pdynlib.h
@@ -8,31 +8,28 @@
#define PDYNLIB_H_
#include "pstring.h"
-#include "ptypes.h"
namespace plib {
// ----------------------------------------------------------------------------------------
// pdynlib: dynamic loading of libraries ...
// ----------------------------------------------------------------------------------------
-class dynlib : public nocopyassignmove
+class dynlib
{
public:
- explicit dynlib(const pstring &libname);
- dynlib(const pstring &path, const pstring &libname);
-
+ explicit dynlib(const pstring libname);
+ dynlib(const pstring path, const pstring libname);
~dynlib();
- COPYASSIGNMOVE(dynlib, delete)
bool isLoaded() const;
template <typename T>
- T getsym(const pstring &name)
+ T getsym(const pstring name)
{
return reinterpret_cast<T>(getsym_p(name));
}
private:
- void *getsym_p(const pstring &name);
+ void *getsym_p(const pstring name);
bool m_isLoaded;
void *m_lib;
@@ -67,6 +64,6 @@ private:
calltype m_sym;
};
-} // namespace plib
+}
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index 8d6907d66f2..a4ed8f367e0 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -9,7 +9,6 @@
#include "pfmtlog.h"
#include <cfenv>
-#include <iostream>
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
#define HAS_FEENABLE_EXCEPT (1)
@@ -18,113 +17,127 @@
#endif
namespace plib {
-
- //============================================================
- // terminate
- //============================================================
-
- void terminate(const pstring &msg) noexcept
- {
- std::cerr << msg.c_str() << "\n";
- std::terminate();
- }
-
-
- //============================================================
- // Exceptions
- //============================================================
-
- pexception::pexception(const pstring &text)
- : m_text(text)
- {
- }
-
-
- file_e::file_e(const pstring &fmt, const pstring &filename)
- : pexception(pfmt(fmt)(filename))
- {
- }
-
-
- file_open_e::file_open_e(const pstring &filename)
- : file_e("File open failed: {}", filename)
- {
- }
-
-
- file_read_e::file_read_e(const pstring &filename)
- : file_e("File read failed: {}", filename)
- {
- }
-
-
- file_write_e::file_write_e(const pstring &filename)
- : file_e("File write failed: {}", filename)
+//============================================================
+// Exceptions
+//============================================================
+
+pexception::pexception(const pstring &text)
+: m_text(text)
+{
+}
+
+pexception::~pexception() noexcept
+{
+}
+
+file_e::file_e(const pstring &fmt, const pstring &filename)
+ : pexception(pfmt(fmt)(filename))
+{
+}
+
+file_e::~file_e() noexcept
+{
+}
+
+file_open_e::file_open_e(const pstring &filename)
+ : file_e("File open failed: {}", filename)
+{
+}
+
+file_open_e::~file_open_e() noexcept
+{
+
+}
+
+file_read_e::file_read_e(const pstring &filename)
+ : file_e("File read failed: {}", filename)
+{
+}
+
+file_read_e::~file_read_e() noexcept
+{
+
+}
+
+file_write_e::file_write_e(const pstring &filename)
+ : file_e("File write failed: {}", filename)
+{
+}
+
+file_write_e::~file_write_e() noexcept
+{
+}
+
+null_argument_e::null_argument_e(const pstring &argument)
+ : pexception(pfmt("Null argument passed: {}")(argument))
+{
+}
+
+null_argument_e::~null_argument_e() noexcept
+{
+}
+
+out_of_mem_e::out_of_mem_e(const pstring &location)
+ : pexception(pfmt("Out of memory: {}")(location))
+{
+}
+
+out_of_mem_e::~out_of_mem_e() noexcept
+{
+}
+
+fpexception_e::fpexception_e(const pstring &text)
+ : pexception(pfmt("Out of memory: {}")(text))
+{
+}
+
+fpexception_e::~fpexception_e() noexcept
+{
+}
+
+bool fpsignalenabler::m_enable = false;
+
+fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
+{
+#if HAS_FEENABLE_EXCEPT
+ if (m_enable)
{
+ int b = 0;
+ if (fpexceptions & plib::FP_INEXACT) b = b | FE_INEXACT;
+ if (fpexceptions & plib::FP_DIVBYZERO) b = b | FE_DIVBYZERO;
+ if (fpexceptions & plib::FP_UNDERFLOW) b = b | FE_UNDERFLOW;
+ if (fpexceptions & plib::FP_OVERFLOW) b = b | FE_OVERFLOW;
+ if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
+ m_last_enabled = feenableexcept(b);
}
+#else
+ m_last_enabled = 0;
+#endif
+}
- null_argument_e::null_argument_e(const pstring &argument)
- : pexception(pfmt("Null argument passed: {}")(argument))
- {
- }
-
-
- out_of_mem_e::out_of_mem_e(const pstring &location)
- : pexception(pfmt("Out of memory: {}")(location))
- {
- }
-
-
- fpexception_e::fpexception_e(const pstring &text)
- : pexception(pfmt("Out of memory: {}")(text))
- {
- }
-
-
- bool fpsignalenabler::m_enable = false;
-
- fpsignalenabler::fpsignalenabler(unsigned fpexceptions)
- {
- #if HAS_FEENABLE_EXCEPT
- if (m_enable)
- {
- int b = 0;
- if (fpexceptions & plib::FP_INEXACT) b = b | FE_INEXACT;
- if (fpexceptions & plib::FP_DIVBYZERO) b = b | FE_DIVBYZERO;
- if (fpexceptions & plib::FP_UNDERFLOW) b = b | FE_UNDERFLOW;
- if (fpexceptions & plib::FP_OVERFLOW) b = b | FE_OVERFLOW;
- if (fpexceptions & plib::FP_INVALID) b = b | FE_INVALID;
- m_last_enabled = feenableexcept(b);
- }
- #else
- m_last_enabled = 0;
- #endif
- }
-
-
- fpsignalenabler::~fpsignalenabler()
+fpsignalenabler::~fpsignalenabler()
+{
+#if HAS_FEENABLE_EXCEPT
+ if (m_enable)
{
- #if HAS_FEENABLE_EXCEPT
- if (m_enable)
- {
- fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
- feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
- }
- #endif
+ fedisableexcept(FE_ALL_EXCEPT); // Enable all floating point exceptions but FE_INEXACT
+ feenableexcept(m_last_enabled); // Enable all floating point exceptions but FE_INEXACT
}
+#endif
+}
- bool fpsignalenabler::supported()
- {
- return true;
- }
+bool fpsignalenabler::supported()
+{
+ return true;
+}
- bool fpsignalenabler::global_enable(bool enable)
- {
- bool old = m_enable;
- m_enable = enable;
- return old;
- }
+bool fpsignalenabler::global_enable(bool enable)
+{
+ bool old = m_enable;
+ m_enable = enable;
+ return old;
+}
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
index 28a3ac1adf1..4827081b754 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -9,116 +9,118 @@
#define PEXCEPTION_H_
#include "pstring.h"
-#include "ptypes.h"
#include <exception>
namespace plib {
+//============================================================
+// exception base
+//============================================================
+
+class pexception : public std::exception
+{
+public:
+ explicit pexception(const pstring &text);
+ pexception(const pexception &e) : std::exception(e), m_text(e.m_text) { }
+
+ virtual ~pexception() noexcept;
+
+ const pstring &text() { return m_text; }
+ const char* what() const noexcept override { return m_text.c_str(); }
+
+private:
+ pstring m_text;
+};
+
+class file_e : public plib::pexception
+{
+public:
+ file_e(const pstring &fmt, const pstring &filename);
+ file_e(const file_e &e) : pexception(e) { }
+ virtual ~file_e() noexcept;
+};
+
+class file_open_e : public file_e
+{
+public:
+ explicit file_open_e(const pstring &filename);
+ file_open_e(const file_open_e &e) : file_e(e) { }
+ virtual ~file_open_e() noexcept;
+};
+
+class file_read_e : public file_e
+{
+public:
+ explicit file_read_e(const pstring &filename);
+ file_read_e(const file_read_e &e) : file_e(e) { }
+ virtual ~file_read_e() noexcept;
+};
+
+class file_write_e : public file_e
+{
+public:
+ explicit file_write_e(const pstring &filename);
+ file_write_e(const file_write_e &e) : file_e(e) { }
+ virtual ~file_write_e() noexcept;
+};
+
+class null_argument_e : public plib::pexception
+{
+public:
+ explicit null_argument_e(const pstring &argument);
+ null_argument_e(const null_argument_e &e) : pexception(e) { }
+ virtual ~null_argument_e() noexcept;
+};
+
+class out_of_mem_e : public plib::pexception
+{
+public:
+ explicit out_of_mem_e(const pstring &location);
+ out_of_mem_e(const out_of_mem_e &e) : pexception(e) { }
+ virtual ~out_of_mem_e() noexcept;
+};
+
+/* FIXME: currently only a stub for later use. More use could be added by
+ * using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
+ */
+
+class fpexception_e : public pexception
+{
+public:
+ explicit fpexception_e(const pstring &text);
+ fpexception_e(const fpexception_e &e) : pexception(e) { }
+ virtual ~fpexception_e() noexcept;
+};
+
+static constexpr unsigned FP_INEXACT = 0x0001;
+static constexpr unsigned FP_DIVBYZERO = 0x0002;
+static constexpr unsigned FP_UNDERFLOW = 0x0004;
+static constexpr unsigned FP_OVERFLOW = 0x0008;
+static constexpr unsigned FP_INVALID = 0x00010;
+static constexpr unsigned FP_ALL = 0x0001f;
+
+/*
+ * Catch SIGFPE on linux for debugging purposes.
+ */
+
+class fpsignalenabler
+{
+public:
+ explicit fpsignalenabler(unsigned fpexceptions);
+ ~fpsignalenabler();
+
+ /* is the functionality supported ? */
+ static bool supported();
+ /* returns last global enable state */
+ static bool global_enable(bool enable);
+
+private:
+ int m_last_enabled;
+
+ static bool m_enable;
+};
+
- //============================================================
- // terminate
- //============================================================
-
- /*! Terminate the program
- *
- * \note could be enhanced by setting a termination handler
- */
- [[noreturn]] void terminate(const pstring &msg) noexcept;
-
- //============================================================
- // exception base
- //============================================================
-
- class pexception : public std::exception
- {
- public:
- explicit pexception(const pstring &text);
-
- const pstring &text() { return m_text; }
- const char* what() const noexcept override { return m_text.c_str(); }
-
- private:
- pstring m_text;
- };
-
- class file_e : public plib::pexception
- {
- public:
- file_e(const pstring &fmt, const pstring &filename);
- };
-
- class file_open_e : public file_e
- {
- public:
- explicit file_open_e(const pstring &filename);
- };
-
- class file_read_e : public file_e
- {
- public:
- explicit file_read_e(const pstring &filename);
- };
-
- class file_write_e : public file_e
- {
- public:
- explicit file_write_e(const pstring &filename);
- };
-
- class null_argument_e : public plib::pexception
- {
- public:
- explicit null_argument_e(const pstring &argument);
- };
-
- class out_of_mem_e : public plib::pexception
- {
- public:
- explicit out_of_mem_e(const pstring &location);
- };
-
- /* FIXME: currently only a stub for later use. More use could be added by
- * using “-fnon-call-exceptions" and sigaction to enable c++ exception supported.
- */
-
- class fpexception_e : public pexception
- {
- public:
- explicit fpexception_e(const pstring &text);
- };
-
- static constexpr unsigned FP_INEXACT = 0x0001;
- static constexpr unsigned FP_DIVBYZERO = 0x0002;
- static constexpr unsigned FP_UNDERFLOW = 0x0004;
- static constexpr unsigned FP_OVERFLOW = 0x0008;
- static constexpr unsigned FP_INVALID = 0x00010;
- static constexpr unsigned FP_ALL = 0x0001f;
-
- /*
- * Catch SIGFPE on linux for debugging purposes.
- */
-
- class fpsignalenabler
- {
- public:
- explicit fpsignalenabler(unsigned fpexceptions);
-
- COPYASSIGNMOVE(fpsignalenabler, delete)
-
- ~fpsignalenabler();
-
- /* is the functionality supported ? */
- static bool supported();
- /* returns last global enable state */
- static bool global_enable(bool enable);
-
- private:
- int m_last_enabled;
-
- static bool m_enable;
- };
-
-
-} // namespace plib
+}
#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp
index af87251fbdf..b8b5fcb3b91 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -8,96 +8,83 @@
#include "pfmtlog.h"
#include "palloc.h"
-#include <algorithm>
-#include <array>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
#include <cstring>
-#include <iostream>
+#include <cstdlib>
+#include <cstdarg>
+#include <algorithm>
#include <locale>
+#include <iostream>
namespace plib {
pfmt &pfmt::format_element(const char *l, const unsigned cfmt_spec, ...)
{
va_list ap;
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
- std::array<char, 2048> buf;
+ va_start(ap, cfmt_spec);
+ pstring fmt("%");
+ char buf[2048]; // FIXME
std::size_t sl;
- bool found_abs = false;
m_arg++;
- do {
- pstring fmt("%");
- va_start(ap, cfmt_spec);
- found_abs = false;
- buf[0] = 0;
- pstring search("{");
- search += plib::to_string(m_arg);
- sl = search.size();
+ pstring search("{");
+ search += plib::to_string(m_arg);
+ sl = search.length();
- auto p = m_str.find(search + ":");
- sl++; // ":"
- if (p == pstring::npos) // no further specifiers
+ auto p = m_str.find(search + ":");
+ sl++; // ":"
+ if (p == pstring::npos) // no further specifiers
+ {
+ p = m_str.find(search + "}");
+ if (p == pstring::npos) // not found try default
{
- p = m_str.find(search + "}");
- if (p == pstring::npos) // not found try default
- {
- sl = 2;
- p = m_str.find("{}");
- }
- else
- // found absolute positional place holder
- found_abs = true;
- if (p == pstring::npos)
- {
- sl=2;
- p = m_str.find("{:");
- if (p != pstring:: npos)
- {
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
- {
- sl = p1 - p + 1;
- fmt += m_str.substr(p+1, p1 - p - 1);
- }
- }
- }
+ sl = 2;
+ p = m_str.find("{}");
}
- else
+ if (p == pstring::npos)
{
- // found absolute positional place holder
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
+ sl=1;
+ p = m_str.find("{");
+ if (p != pstring:: npos)
{
- sl = p1 - p + 1;
- fmt += ((m_arg>=10) ? m_str.substr(p+4, p1 - p - 4) : m_str.substr(p+3, p1 - p - 3));
- found_abs = true;
+ auto p1 = m_str.find("}", p);
+ if (p1 != pstring::npos)
+ {
+ sl = p1 - p + 1;
+ fmt += m_str.substr(p+1, p1 - p - 1);
+ }
}
}
- pstring::value_type pend = fmt.at(fmt.size() - 1);
- if (pstring("duxo").find(cfmt_spec) != pstring::npos)
+ }
+ else
+ {
+ auto p1 = m_str.find("}", p);
+ if (p1 != pstring::npos)
{
- if (pstring("duxo").find(pend) == pstring::npos)
- fmt += (pstring(l) + static_cast<pstring::value_type>(cfmt_spec));
- else
- fmt = plib::left(fmt, fmt.size() - 1) + pstring(l) + plib::right(fmt, 1);
- }
- else if (pstring("fge").find(cfmt_spec) != pstring::npos)
- {
- if (pstring("fge").find(pend) == pstring::npos)
- fmt += cfmt_spec;
+ sl = p1 - p + 1;
+ fmt += ((m_arg>=10) ? m_str.substr(p+4, p1 - p - 4) : m_str.substr(p+3, p1 - p - 3));
}
+ }
+ pstring::code_t pend = fmt.at(fmt.length() - 1);
+ if (pstring("duxo").find(cfmt_spec) != pstring::npos)
+ {
+ if (pstring("duxo").find(pend) == pstring::npos)
+ fmt += (pstring(l, pstring::UTF8) + cfmt_spec);
else
+ fmt = fmt.left(fmt.length() - 1) + pstring(l, pstring::UTF8) + fmt.right(1);
+ }
+ else if (pstring("fge").find(cfmt_spec) != pstring::npos)
+ {
+ if (pstring("fge").find(pend) == pstring::npos)
fmt += cfmt_spec;
- std::vsnprintf(buf.data(), buf.size(), fmt.c_str(), ap);
- if (p != pstring::npos)
- m_str = m_str.substr(0, p) + pstring(buf.data()) + m_str.substr(p + sl);
- va_end(ap);
- } while (found_abs);
+ }
+ else
+ fmt += cfmt_spec;
+ vsprintf(buf, fmt.c_str(), ap);
+ if (p != pstring::npos)
+ m_str = m_str.substr(0, p) + pstring(buf, pstring::UTF8) + m_str.substr(p + sl);
+ va_end(ap);
return *this;
}
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index cb9b59c01ce..9b7a85d8d8d 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -9,7 +9,6 @@
#include "pstring.h"
#include "ptypes.h"
-#include "putil.h"
#include <limits>
@@ -35,6 +34,7 @@ struct ptype_traits_base
template <>
struct ptype_traits_base<bool>
{
+ static unsigned int cast(bool &x) { return static_cast<unsigned int>(x); }
static unsigned int cast(const bool &x) { return static_cast<unsigned int>(x); }
static const bool is_signed = std::numeric_limits<bool>::is_signed;
static const char *size_spec() { return ""; }
@@ -136,6 +136,7 @@ struct ptype_traits<double> : ptype_traits_base<double>
static char32_t fmt_spec() { return 'f'; }
};
+
template<>
struct ptype_traits<char *> : ptype_traits_base<char *>
{
@@ -143,13 +144,6 @@ struct ptype_traits<char *> : ptype_traits_base<char *>
static char32_t fmt_spec() { return 's'; }
};
-template<>
-struct ptype_traits<std::string> : ptype_traits_base<char *>
-{
- static const char *cast(const std::string &x) { return x.c_str(); }
- static char32_t fmt_spec() { return 's'; }
-};
-
class pfmt
{
public:
@@ -157,57 +151,44 @@ public:
: m_str(fmt), m_arg(0)
{
}
- COPYASSIGNMOVE(pfmt, default)
- ~pfmt() noexcept = default;
+ pfmt(const pfmt &rhs) : m_str(rhs.m_str), m_arg(rhs.m_arg) { }
+
+ ~pfmt()
+ {
+ }
operator pstring() const { return m_str; }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & e(const double &x) {return format_element("", 'e', x); }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & g(const double &x) {return format_element("", 'g', x); }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & e(const float &x) {return format_element("", 'e', static_cast<double>(x)); }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt & g(const float &x) {return format_element("", 'g', static_cast<double>(x)); }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt &operator ()(const void *x) {return format_element("", 'p', x); }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
pfmt &operator ()(const pstring &x) {return format_element("", 's', x.c_str() ); }
template<typename T>
pfmt &operator ()(const T &x)
{
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), ptype_traits<T>::fmt_spec(), ptype_traits<T>::cast(x));
}
template<typename T>
pfmt &operator ()(const T *x)
{
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T *>::size_spec(), ptype_traits<T *>::fmt_spec(), ptype_traits<T *>::cast(x));
}
- template<typename X, typename Y, typename... Args>
- pfmt &operator()(X&& x, Y && y, Args&&... args)
- {
- return ((*this)(std::forward<X>(x)))(std::forward<Y>(y), std::forward<Args>(args)...);
- }
-
template<typename T>
pfmt &x(const T &x)
{
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), 'x', x);
}
template<typename T>
pfmt &o(const T &x)
{
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
return format_element(ptype_traits<T>::size_spec(), 'o', x);
}
@@ -222,13 +203,11 @@ private:
};
template <class T, bool build_enabled = true>
-class pfmt_writer_t
+class pfmt_writer_t : plib::nocopyassignmove
{
public:
explicit pfmt_writer_t() : m_enabled(true) { }
- COPYASSIGNMOVE(pfmt_writer_t, delete)
-
/* runtime enable */
template<bool enabled, typename... Args>
void log(const pstring & fmt, Args&&... args) const
@@ -258,7 +237,7 @@ public:
bool is_enabled() const { return m_enabled; }
protected:
- ~pfmt_writer_t() noexcept = default;
+ ~pfmt_writer_t() { }
private:
pfmt &xlog(pfmt &fmt) const { return fmt; }
@@ -279,10 +258,7 @@ class plog_channel : public pfmt_writer_t<plog_channel<T, L, build_enabled>, bui
friend class pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled>;
public:
explicit plog_channel(T &b) : pfmt_writer_t<plog_channel, build_enabled>(), m_base(b) { }
-
- COPYASSIGNMOVE(plog_channel, delete)
-
- ~plog_channel() noexcept = default;
+ ~plog_channel() { }
protected:
void vdowrite(const pstring &ls) const
@@ -307,9 +283,7 @@ public:
error(proxy),
fatal(proxy)
{}
-
- COPYASSIGNMOVE(plog_base, default)
- virtual ~plog_base() noexcept = default;
+ virtual ~plog_base() {}
plog_channel<T, plog_level::DEBUG, debug_enabled> debug;
plog_channel<T, plog_level::INFO> info;
@@ -319,7 +293,7 @@ public:
plog_channel<T, plog_level::FATAL> fatal;
};
-} // namespace plib
+}
template<typename T>
plib::pfmt& operator<<(plib::pfmt &p, T&& val) { return p(std::forward<T>(val)); }
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 6a2179e0e6f..79f09cb4a46 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -6,9 +6,9 @@
*/
#include "pfunction.h"
-#include "pexception.h"
#include "pfmtlog.h"
#include "putil.h"
+#include "pexception.h"
#include <cmath>
#include <stack>
@@ -17,7 +17,7 @@ namespace plib {
void pfunction::compile(const std::vector<pstring> &inputs, const pstring &expr)
{
- if (plib::startsWith(expr, "rpn:"))
+ if (expr.startsWith("rpn:"))
compile_postfix(inputs, expr.substr(4));
else
compile_infix(inputs, expr);
@@ -56,7 +56,7 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
{ rc.m_cmd = RAND; stk += 1; }
else
{
- for (std::size_t i = 0; i < inputs.size(); i++)
+ for (unsigned i = 0; i < inputs.size(); i++)
{
if (inputs[i] == cmd)
{
@@ -68,9 +68,9 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
}
if (rc.m_cmd != PUSH_INPUT)
{
+ bool err = false;
rc.m_cmd = PUSH_CONST;
- bool err;
- rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
+ rc.m_param = cmd.as_double(&err);
if (err)
throw plib::pexception(plib::pfmt("nld_function: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
stk += 1;
@@ -84,11 +84,11 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
}
-static int get_prio(const pstring &v)
+static int get_prio(pstring v)
{
if (v == "(" || v == ")")
return 1;
- else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z")
+ else if (v.left(1) >= "a" && v.left(1) <= "z")
return 0;
else if (v == "*" || v == "/")
return 20;
@@ -113,11 +113,12 @@ void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring
{
// Shunting-yard infix parsing
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
- std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, pstring(" "), pstring("")), sep));
+ std::vector<pstring> sexpr(plib::psplit(expr.replace_all(" ",""), sep));
std::stack<pstring> opstk;
std::vector<pstring> postfix;
- for (std::size_t i = 0; i < sexpr.size(); i++)
+ //printf("dbg: %s\n", expr.c_str());
+ for (unsigned i = 0; i < sexpr.size(); i++)
{
pstring &s = sexpr[i];
if (s=="(")
@@ -181,15 +182,14 @@ void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring
#define OP(OP, ADJ, EXPR) \
case OP: \
- ptr-= (ADJ); \
- stack[ptr-1] = (EXPR); \
+ ptr-=ADJ; \
+ stack[ptr-1] = EXPR; \
break;
double pfunction::evaluate(const std::vector<double> &values)
{
- std::array<double, 20> stack = { 0 };
+ double stack[20];
unsigned ptr = 0;
- stack[0] = 0.0;
for (auto &rc : m_precompiled)
{
switch (rc.m_cmd)
@@ -199,8 +199,8 @@ double pfunction::evaluate(const std::vector<double> &values)
OP(SUB, 1, ST2 - ST1)
OP(DIV, 1, ST2 / ST1)
OP(POW, 1, std::pow(ST2, ST1))
- OP(SIN, 0, std::sin(ST2))
- OP(COS, 0, std::cos(ST2))
+ OP(SIN, 0, std::sin(ST2));
+ OP(COS, 0, std::cos(ST2));
case RAND:
stack[ptr++] = lfsr_random();
break;
@@ -215,4 +215,4 @@ double pfunction::evaluate(const std::vector<double> &values)
return stack[ptr-1];
}
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index fbb6c508333..7d5984f9d15 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -8,8 +8,8 @@
#ifndef PFUNCTION_H_
#define PFUNCTION_H_
-#include "pstate.h"
#include "pstring.h"
+#include "pstate.h"
#include <vector>
@@ -112,6 +112,6 @@ namespace plib {
};
-} // namespace plib
+}
#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index c2fee9c2f8e..5fefa658b83 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -12,8 +12,6 @@
#include "pstring.h"
-#include <array>
-#include <type_traits>
#include <vector>
namespace plib {
@@ -31,13 +29,14 @@ class uninitialised_array_t
{
public:
- using iterator = C *;
- using const_iterator = const C *;
+ typedef C* iterator;
+ typedef const C* const_iterator;
- uninitialised_array_t() noexcept = default;
+ uninitialised_array_t()
+ {
+ }
- COPYASSIGNMOVE(uninitialised_array_t, delete)
- ~uninitialised_array_t() noexcept
+ ~uninitialised_array_t()
{
for (std::size_t i=0; i<N; i++)
(*this)[i].~C();
@@ -52,7 +51,7 @@ public:
const C& operator[](const std::size_t &index) const noexcept
{
- return *reinterpret_cast<const C *>(&m_buf[index]);
+ return *reinterpret_cast<C *>(&m_buf[index]);
}
template<typename... Args>
@@ -76,8 +75,7 @@ protected:
private:
/* ensure proper alignment */
- PALIGNAS_VECTOROPT()
- std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf;
+ typename std::aligned_storage<sizeof(C), alignof(C)>::type m_buf[N];
};
// ----------------------------------------------------------------------------------------
@@ -85,7 +83,6 @@ private:
// the list allows insertions / deletions if used properly
// ----------------------------------------------------------------------------------------
-#if 0
template <class LC>
class linkedlist_t
{
@@ -155,10 +152,9 @@ public:
void remove(const LC *elem) noexcept
{
auto p = &m_head;
- while(*p != elem)
+ for ( ; *p != elem; p = &((*p)->m_next))
{
//nl_assert(*p != nullptr);
- p = &((*p)->m_next);
}
(*p) = elem->m_next;
}
@@ -170,105 +166,7 @@ public:
private:
LC *m_head;
};
-#else
-template <class LC>
-class linkedlist_t
-{
-public:
-
- struct element_t
- {
- public:
-
- friend class linkedlist_t<LC>;
-
- constexpr element_t() : m_next(nullptr), m_prev(nullptr) {}
- ~element_t() noexcept = default;
-
- COPYASSIGNMOVE(element_t, delete)
-
- constexpr LC *next() const noexcept { return m_next; }
- constexpr LC *prev() const noexcept { return m_prev; }
- private:
- LC * m_next;
- LC * m_prev;
- };
-
- struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
- {
- private:
- LC* p;
- public:
- explicit constexpr iter_t(LC* x) noexcept : p(x) { }
- constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
- iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
- iter_t& operator=(const iter_t &rhs) noexcept { iter_t t(rhs); std::swap(*this, t); return *this; }
- iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
- iter_t& operator++() noexcept {p = p->next();return *this;}
- // NOLINTNEXTLINE(cert-dcl21-cpp)
- iter_t operator++(int) & noexcept {const iter_t tmp(*this); operator++(); return tmp;}
-
- ~iter_t() = default;
-
- constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;}
- constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;}
- /* constexpr */ LC& operator*() noexcept {return *p;}
- /* constexpr */ LC* operator->() noexcept {return p;}
-
- constexpr LC& operator*() const noexcept {return *p;}
- constexpr LC* operator->() const noexcept {return p;}
- };
-
- constexpr linkedlist_t() : m_head(nullptr) {}
- constexpr iter_t begin() const noexcept { return iter_t(m_head); }
- constexpr iter_t end() const noexcept { return iter_t(nullptr); }
-
- void push_front(LC *elem) noexcept
- {
- if (m_head)
- m_head->m_prev = elem;
- elem->m_next = m_head;
- elem->m_prev = nullptr;
- m_head = elem;
- }
-
- void push_back(LC *elem) noexcept
- {
- LC ** p(&m_head);
- LC * prev(nullptr);
- while (*p != nullptr)
- {
- prev = *p;
- p = &((*p)->m_next);
- }
- *p = elem;
- elem->m_prev = prev;
- elem->m_next = nullptr;
- }
-
- void remove(const LC *elem) noexcept
- {
- if (elem->m_prev)
- elem->m_prev->m_next = elem->m_next;
- else
- m_head = elem->m_next;
- if (elem->m_next)
- elem->m_next->m_prev = elem->m_prev;
- else
- {
- /* update tail */
- }
- }
-
- LC *front() const noexcept { return m_head; }
- void clear() noexcept { m_head = nullptr; }
- constexpr bool empty() const noexcept { return (m_head == nullptr); }
-
-private:
- LC *m_head;
-};
-#endif
-} // namespace plib
+}
#endif /* PLISTS_H_ */
diff --git a/src/lib/netlist/plib/pmain.cpp b/src/lib/netlist/plib/pmain.cpp
index b381d96dca7..93c4076bac2 100644
--- a/src/lib/netlist/plib/pmain.cpp
+++ b/src/lib/netlist/plib/pmain.cpp
@@ -23,7 +23,7 @@ namespace plib {
char *buf = new char[dst_char_count + 1];
WideCharToMultiByte(CP_UTF8, 0, w, wlen, buf, dst_char_count, nullptr, nullptr);
buf[dst_char_count] = 0;
- auto ret = pstring(buf);
+ auto ret = pstring(buf, pstring::UTF8);
delete [] buf;
return ret;
}
@@ -37,13 +37,18 @@ namespace plib {
: options()
, pout_strm()
, perr_strm()
- , pout(&pout_strm)
- , perr(&perr_strm)
+ , pout(pout_strm)
+ , perr(perr_strm)
{
}
- int app::main_utfX(int argc, char **argv)
+ app::~app()
+ {
+
+ }
+
+ int app::main_utfX(int argc, char *argv[])
{
auto r = this->parse(argc, argv);
int ret = 0;
diff --git a/src/lib/netlist/plib/pmain.h b/src/lib/netlist/plib/pmain.h
index 4f4be779251..e2f84b90de6 100644
--- a/src/lib/netlist/plib/pmain.h
+++ b/src/lib/netlist/plib/pmain.h
@@ -10,21 +10,20 @@
#ifndef PMAIN_H_
#define PMAIN_H_
-#include "palloc.h"
#include "poptions.h"
-#include "pstream.h"
#include "pstring.h"
#include "putil.h"
+#include "pstream.h"
-#include <cwchar>
#include <memory>
+#include <cwchar>
#ifdef _WIN32
#define PMAIN(appclass) \
extern "C" int wmain(int argc, wchar_t *argv[]) { return plib::app::mainrun<appclass, wchar_t>(argc, argv); }
#else
#define PMAIN(appclass) \
-int main(int argc, char **argv) { return plib::app::mainrun<appclass, char>(argc, argv); }
+int main(int argc, char *argv[]) { return plib::app::mainrun<appclass, char>(argc, argv); }
#endif
@@ -37,10 +36,7 @@ namespace plib {
{
public:
app();
-
- COPYASSIGNMOVE(app, delete)
-
- virtual ~app() = default;
+ virtual ~app();
virtual pstring usage() = 0;
virtual int execute() = 0;
@@ -52,21 +48,21 @@ namespace plib {
plib::putf8_fmt_writer perr;
template <class C, typename T>
- static int mainrun(int argc, T **argv)
+ static int mainrun(int argc, T *argv[])
{
- auto a = plib::make_unique<C>();
+ auto a = std::unique_ptr<C>(new C);
return a->main_utfX(argc, argv);
}
private:
- int main_utfX(int argc, char **argv);
+ int main_utfX(int argc, char *argv[]);
#ifdef _WIN32
int main_utfX(int argc, wchar_t *argv[]);
#endif
};
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pmatrix2d.h b/src/lib/netlist/plib/pmatrix2d.h
deleted file mode 100644
index eab533688d7..00000000000
--- a/src/lib/netlist/plib/pmatrix2d.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * pmatrix2d.h
- *
- * NxM regular matrix
- *
- */
-
-#ifndef PMATRIX2D_H_
-#define PMATRIX2D_H_
-
-#include "palloc.h"
-
-#include <algorithm>
-#include <cmath>
-#include <cstdlib>
-#include <type_traits>
-#include <vector>
-
-namespace plib
-{
-
-
- template<typename T, typename A = aligned_allocator<T>>
- class pmatrix2d
- {
- public:
- using value_type = T;
- using allocator_type = A;
-
- static constexpr const std::size_t align_size = align_traits<A>::align_size;
- static constexpr const std::size_t stride_size = align_traits<A>::stride_size;
- pmatrix2d()
- : m_N(0), m_M(0), m_stride(8), m_v()
- {
- }
-
- pmatrix2d(std::size_t N, std::size_t M)
- : m_N(N), m_M(M), m_v()
- {
- m_stride = ((M + stride_size-1) / stride_size) * stride_size;
- m_v.resize(N * m_stride);
- }
-
- void resize(std::size_t N, std::size_t M)
- {
- m_N = N;
- m_M = M;
- m_stride = ((M + stride_size-1) / stride_size) * stride_size;
- m_v.resize(N * m_stride);
- }
-
- C14CONSTEXPR T * operator[] (std::size_t row) noexcept
- {
- return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
- }
-
- constexpr const T * operator[] (std::size_t row) const noexcept
- {
- return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
- }
-
- T & operator()(std::size_t r, std::size_t c) noexcept
- {
- return (*this)[r][c];
- }
-
- const T & operator()(std::size_t r, std::size_t c) const noexcept
- {
- return (*this)[r][c];
- }
-
- private:
-
- std::size_t m_N;
- std::size_t m_M;
- std::size_t m_stride;
-
- std::vector<T, A> m_v;
- };
-
-} // namespace plib
-
-#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h
deleted file mode 100644
index f55807c86dc..00000000000
--- a/src/lib/netlist/plib/pmempool.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * pmempool.h
- *
- */
-
-#ifndef PMEMPOOL_H_
-#define PMEMPOOL_H_
-
-#include "palloc.h"
-#include "pstream.h"
-#include "pstring.h"
-#include "ptypes.h"
-#include "putil.h"
-
-#include <algorithm>
-#include <cstddef>
-#include <memory>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-namespace plib {
-
- //============================================================
- // Memory pool
- //============================================================
-
- class mempool
- {
- private:
- struct block
- {
- block(mempool *mp, std::size_t min_bytes)
- : m_num_alloc(0)
- , m_cur(0)
- , m_data(nullptr)
- , m_mempool(mp)
- {
- min_bytes = std::max(mp->m_min_alloc, min_bytes);
- m_free = min_bytes;
- std::size_t alloc_bytes = (min_bytes + mp->m_min_align - 1) & ~(mp->m_min_align - 1);
- m_data_allocated = static_cast<char *>(::operator new(alloc_bytes));
- void *r = m_data_allocated;
- std::align(mp->m_min_align, min_bytes, r, alloc_bytes);
- m_data = reinterpret_cast<char *>(r);
- }
- std::size_t m_num_alloc;
- std::size_t m_free;
- std::size_t m_cur;
- char *m_data;
- char *m_data_allocated;
- mempool *m_mempool;
- };
-
- struct info
- {
- info(block *b, std::size_t p) : m_block(b), m_pos(p) { }
- ~info() = default;
- COPYASSIGNMOVE(info, default)
-
- block * m_block;
- std::size_t m_pos;
- };
-
-
- block * new_block(std::size_t min_bytes)
- {
- auto *b = plib::pnew<block>(this, min_bytes);
- m_blocks.push_back(b);
- return b;
- }
-
-
- static std::unordered_map<void *, info> &sinfo()
- {
- static std::unordered_map<void *, info> spinfo;
- return spinfo;
- }
-
- size_t m_min_alloc;
- size_t m_min_align;
-
- std::vector<block *> m_blocks;
-
- public:
- static constexpr const bool is_stateless = false;
- template <class T, std::size_t ALIGN = alignof(T)>
- using allocator_type = arena_allocator<mempool, T, ALIGN>;
-
- mempool(size_t min_alloc = (1<<21), size_t min_align = 16)
- : m_min_alloc(min_alloc), m_min_align(min_align)
- {
- }
-
- COPYASSIGNMOVE(mempool, delete)
-
- ~mempool()
- {
-
- for (auto & b : m_blocks)
- {
- if (b->m_num_alloc != 0)
- {
- plib::perrlogger("Found {} info blocks\n", sinfo().size());
- plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc);
- }
- ::operator delete(b->m_data);
- }
- }
-
- void *allocate(size_t align, size_t size)
- {
- if (align < m_min_align)
- align = m_min_align;
-
- size_t rs = size + align;
- for (auto &b : m_blocks)
- {
- if (b->m_free > rs)
- {
- b->m_free -= rs;
- b->m_num_alloc++;
- auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur);
- auto capacity(rs);
- ret = std::align(align, size, ret, capacity);
- // FIXME: if (ret == nullptr)
- // printf("Oh no\n");
- sinfo().insert({ ret, info(b, b->m_cur)});
- rs -= (capacity - size);
- b->m_cur += rs;
-
- return ret;
- }
- }
- {
- block *b = new_block(rs);
- b->m_num_alloc = 1;
- b->m_free = m_min_alloc - rs;
- auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur);
- auto capacity(rs);
- ret = std::align(align, size, ret, capacity);
- // FIXME: if (ret == nullptr)
- // printf("Oh no\n");
- sinfo().insert({ ret, info(b, b->m_cur)});
- rs -= (capacity - size);
- b->m_cur += rs;
- return ret;
- }
- }
-
- static void deallocate(void *ptr)
- {
-
- auto it = sinfo().find(ptr);
- if (it == sinfo().end())
- plib::terminate("mempool::free - pointer not found\n");
- info i = it->second;
- block *b = i.m_block;
- if (b->m_num_alloc == 0)
- plib::terminate("mempool::free - double free was called\n");
- else
- {
- //b->m_free = m_min_alloc;
- //b->cur_ptr = b->data;
- }
- b->m_num_alloc--;
- //printf("Freeing in block %p %lu\n", b, b->m_num_alloc);
- sinfo().erase(it);
- }
-
- template <typename T>
- using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<mempool, T>>;
-
- template<typename T, typename... Args>
- owned_pool_ptr<T> make_poolptr(Args&&... args)
- {
- auto *mem = this->allocate(alignof(T), sizeof(T));
- return owned_pool_ptr<T>(new (mem) T(std::forward<Args>(args)...), true, arena_deleter<mempool, T>(this));
- }
-
- };
-
-} // namespace plib
-
-#endif /* PMEMPOOL_H_ */
diff --git a/src/lib/netlist/plib/pomp.h b/src/lib/netlist/plib/pomp.h
index f8a516df485..6559207f09d 100644
--- a/src/lib/netlist/plib/pomp.h
+++ b/src/lib/netlist/plib/pomp.h
@@ -11,8 +11,6 @@
#include "pconfig.h"
-#include <cstddef>
-
#if HAS_OPENMP
#include "omp.h"
#endif
@@ -20,39 +18,29 @@
namespace plib {
namespace omp {
-template <typename I, class T>
-void for_static(const I start, const I end, const T &what)
+template <class T>
+void for_static(const int start, const int end, const T &what)
{
#if HAS_OPENMP && USE_OPENMP
#pragma omp parallel
#endif
{
#if HAS_OPENMP && USE_OPENMP
- #pragma omp for //schedule(static)
+ #pragma omp for schedule(static)
#endif
- for (I i = start; i < end; i++)
+ for (int i = start; i < end; i++)
what(i);
}
}
-template <typename I, class T>
-void for_static_np(const I start, const I end, const T &what)
-{
- for (I i = start; i < end; i++)
- what(i);
-}
-
-
-inline void set_num_threads(const std::size_t threads)
+inline void set_num_threads(const int threads)
{
#if HAS_OPENMP && USE_OPENMP
omp_set_num_threads(threads);
-#else
- plib::unused_var(threads);
#endif
}
-inline std::size_t get_max_threads()
+inline int get_max_threads()
{
#if HAS_OPENMP && USE_OPENMP
return omp_get_max_threads();
@@ -66,7 +54,7 @@ inline std::size_t get_max_threads()
// pdynlib: dynamic loading of libraries ...
// ----------------------------------------------------------------------------------------
-} // namespace omp
-} // namespace plib
+}
+}
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
index 4a3d32c4723..910660acb3d 100644
--- a/src/lib/netlist/plib/poptions.cpp
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -6,39 +6,77 @@
*/
#include "poptions.h"
-#include "pexception.h"
-#include "ptypes.h"
namespace plib {
/***************************************************************************
Options
***************************************************************************/
- option_base::option_base(options &parent, const pstring &help)
+ option_base::option_base(options &parent, pstring help)
: m_help(help)
{
parent.register_option(this);
}
- option::option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument)
+ option_base::~option_base()
+ {
+ }
+
+ option_group::~option_group()
+ {
+ }
+
+ option_example::~option_example()
+ {
+ }
+
+ option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
: option_base(parent, help), m_short(ashort), m_long(along),
m_has_argument(has_argument), m_specified(false)
{
}
+ option::~option()
+ {
+ }
+
int option_str::parse(const pstring &argument)
{
m_val = argument;
return 0;
}
+ int option_str_limit::parse(const pstring &argument)
+ {
+ if (plib::container::contains(m_limit, argument))
+ {
+ m_val = argument;
+ return 0;
+ }
+ else
+ return 1;
+ }
+
int option_bool::parse(const pstring &argument)
{
- unused_var(argument);
m_val = true;
return 0;
}
+ int option_double::parse(const pstring &argument)
+ {
+ bool err = false;
+ m_val = argument.as_double(&err);
+ return (err ? 1 : 0);
+ }
+
+ int option_long::parse(const pstring &argument)
+ {
+ bool err = false;
+ m_val = argument.as_long(&err);
+ return (err ? 1 : 0);
+ }
+
int option_vec::parse(const pstring &argument)
{
bool err = false;
@@ -47,88 +85,53 @@ namespace plib {
}
options::options()
- : m_other_args(nullptr)
{
}
- options::options(option **o)
- : m_other_args(nullptr)
+ options::options(option *o[])
{
int i=0;
while (o[i] != nullptr)
{
- register_option(o[i]);
+ m_opts.push_back(o[i]);
i++;
}
}
- void options::register_option(option_base *opt)
+ options::~options()
{
- m_opts.push_back(opt);
+ m_opts.clear();
}
- void options::check_consistency()
+ void options::register_option(option_base *opt)
{
- for (auto &opt : m_opts)
- {
- auto *o = dynamic_cast<option *>(opt);
- if (o != nullptr)
- {
- if (o->short_opt() == "" && o->long_opt() == "")
- {
- auto *ov = dynamic_cast<option_args *>(o);
- if (ov != nullptr)
- {
- if (m_other_args != nullptr)
- {
- throw pexception("other args can only be specified once!");
- }
- else
- {
- m_other_args = ov;
- }
- }
- else
- throw pexception("found option with neither short or long tag!" );
- }
- }
- }
+ m_opts.push_back(opt);
}
- int options::parse(int argc, char **argv)
+ int options::parse(int argc, char *argv[])
{
- check_consistency();
- m_app = pstring(argv[0]);
- bool seen_other_args = false;
+ m_app = pstring(argv[0], pstring::UTF8);
for (int i=1; i<argc; )
{
- pstring arg(argv[i]);
+ pstring arg(argv[i], pstring::UTF8);
option *opt = nullptr;
pstring opt_arg;
bool has_equal_arg = false;
- if (!seen_other_args && plib::startsWith(arg, "--"))
+ if (arg.startsWith("--"))
{
auto v = psplit(arg.substr(2),"=");
- if (v.size() && v[0] != pstring(""))
- {
- opt = getopt_long(v[0]);
- has_equal_arg = (v.size() > 1);
- if (has_equal_arg)
- {
- for (std::size_t j = 1; j < v.size() - 1; j++)
- opt_arg = opt_arg + v[j] + "=";
- opt_arg += v[v.size()-1];
- }
- }
- else
+ opt = getopt_long(v[0]);
+ has_equal_arg = (v.size() > 1);
+ if (has_equal_arg)
{
- opt = m_other_args;
- seen_other_args = true;
+ for (unsigned j = 1; j < v.size() - 1; j++)
+ opt_arg = opt_arg + v[j] + "=";
+ opt_arg += v[v.size()-1];
}
}
- else if (!seen_other_args && plib::startsWith(arg, "-"))
+ else if (arg.startsWith("-"))
{
std::size_t p = 1;
opt = getopt_short(arg.substr(p, 1));
@@ -141,11 +144,7 @@ namespace plib {
}
else
{
- seen_other_args = true;
- if (m_other_args == nullptr)
- return i;
- opt = m_other_args;
- i--; // we haven't had an option specifier;
+ return i;
}
if (opt == nullptr)
return i;
@@ -159,7 +158,7 @@ namespace plib {
else
{
i++; // FIXME: are there more arguments?
- if (opt->do_parse(pstring(argv[i])) != 0)
+ if (opt->do_parse(pstring(argv[i], pstring::UTF8)) != 0)
return i - 1;
}
}
@@ -174,7 +173,7 @@ namespace plib {
return argc;
}
- pstring options::split_paragraphs(const pstring &text, unsigned width, unsigned indent,
+ pstring options::split_paragraphs(pstring text, unsigned width, unsigned indent,
unsigned firstline_indent)
{
auto paragraphs = psplit(text,"\n");
@@ -182,13 +181,13 @@ namespace plib {
for (auto &p : paragraphs)
{
- pstring line = plib::rpad(pstring(""), pstring(" "), firstline_indent);
+ pstring line = pstring("").rpad(" ", firstline_indent);
for (auto &s : psplit(p, " "))
{
if (line.length() + s.length() > width)
{
ret += line + "\n";
- line = plib::rpad(pstring(""), pstring(" "), indent);
+ line = pstring("").rpad(" ", indent);
}
line += s + " ";
}
@@ -197,8 +196,8 @@ namespace plib {
return ret;
}
- pstring options::help(const pstring &description, const pstring &usage,
- unsigned width, unsigned indent) const
+ pstring options::help(pstring description, pstring usage,
+ unsigned width, unsigned indent)
{
pstring ret;
@@ -207,10 +206,6 @@ namespace plib {
for (auto & optbase : m_opts )
{
- // Skip anonymous inputs which are collected in option_args
- if (dynamic_cast<option_args *>(optbase) != nullptr)
- continue;
-
if (auto opt = dynamic_cast<option *>(optbase))
{
pstring line = "";
@@ -226,20 +221,20 @@ namespace plib {
if (opt->has_argument())
{
line += "=";
- auto *ol = dynamic_cast<option_str_limit_base *>(opt);
+ option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
if (ol)
{
for (auto &v : ol->limit())
{
line += v + "|";
}
- line = plib::left(line, line.length() - 1);
+ line = line.left(line.length() - 1);
}
else
line += "Value";
}
}
- line = plib::rpad(line, pstring(" "), indent - 2) + " ";
+ line = line.rpad(" ", indent - 2) + " ";
if (line.length() > indent)
{
//ret += "TestGroup abc\n def gef\nxyz\n\n" ;
@@ -255,7 +250,6 @@ namespace plib {
if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n";
}
}
- // FIXME: other help ...
pstring ex("");
for (auto & optbase : m_opts )
{
@@ -272,22 +266,22 @@ namespace plib {
return ret;
}
- option *options::getopt_short(const pstring &arg) const
+ option *options::getopt_short(pstring arg)
{
for (auto & optbase : m_opts)
{
auto opt = dynamic_cast<option *>(optbase);
- if (opt && arg != "" && opt->short_opt() == arg)
+ if (opt && opt->short_opt() == arg)
return opt;
}
return nullptr;
}
- option *options::getopt_long(const pstring &arg) const
+ option *options::getopt_long(pstring arg)
{
for (auto & optbase : m_opts)
{
auto opt = dynamic_cast<option *>(optbase);
- if (opt && arg !="" && opt->long_opt() == arg)
+ if (opt && opt->long_opt() == arg)
return opt;
}
return nullptr;
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 086fe32fc8a..491ac0b4d91 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -10,8 +10,8 @@
#ifndef POPTIONS_H_
#define POPTIONS_H_
-#include "plists.h"
#include "pstring.h"
+#include "plists.h"
#include "putil.h"
namespace plib {
@@ -24,12 +24,10 @@ class options;
class option_base
{
public:
- option_base(options &parent, const pstring &help);
- virtual ~option_base() = default;
-
- COPYASSIGNMOVE(option_base, delete)
+ option_base(options &parent, pstring help);
+ virtual ~option_base();
- pstring help() const { return m_help; }
+ pstring help() { return m_help; }
private:
pstring m_help;
};
@@ -37,10 +35,11 @@ private:
class option_group : public option_base
{
public:
- option_group(options &parent, const pstring &group, const pstring &help)
+ option_group(options &parent, pstring group, pstring help)
: option_base(parent, help), m_group(group) { }
+ ~option_group();
- pstring group() const { return m_group; }
+ pstring group() { return m_group; }
private:
pstring m_group;
};
@@ -48,10 +47,11 @@ private:
class option_example : public option_base
{
public:
- option_example(options &parent, const pstring &group, const pstring &help)
+ option_example(options &parent, pstring group, pstring help)
: option_base(parent, help), m_example(group) { }
+ ~option_example();
- pstring example() const { return m_example; }
+ pstring example() { return m_example; }
private:
pstring m_example;
};
@@ -60,7 +60,8 @@ private:
class option : public option_base
{
public:
- option(options &parent, const pstring &ashort, const pstring &along, const pstring &help, bool has_argument);
+ option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument);
+ ~option();
/* no_argument options will be called with "" argument */
@@ -88,177 +89,131 @@ private:
class option_str : public option
{
public:
- option_str(options &parent, const pstring &ashort, const pstring &along, const pstring &defval, const pstring &help)
+ option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help)
: option(parent, ashort, along, help, true), m_val(defval)
{}
- pstring operator ()() const { return m_val; }
+ pstring operator ()() { return m_val; }
protected:
- int parse(const pstring &argument) override;
+ virtual int parse(const pstring &argument) override;
private:
pstring m_val;
};
-class option_str_limit_base : public option
+class option_str_limit : public option
{
public:
- option_str_limit_base(options &parent, const pstring &ashort, const pstring &along, std::vector<pstring> &&limit, const pstring &help)
- : option(parent, ashort, along, help, true)
- , m_limit(limit)
+ option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
+ , m_limit(plib::psplit(limit, ":"))
{
}
- const std::vector<pstring> &limit() const { return m_limit; }
+
+ pstring operator ()() { return m_val; }
+ const std::vector<pstring> &limit() { return m_limit; }
protected:
+ virtual int parse(const pstring &argument) override;
private:
+ pstring m_val;
std::vector<pstring> m_limit;
};
-
-template <typename T>
-class option_str_limit : public option_str_limit_base
+class option_bool : public option
{
public:
- option_str_limit(options &parent, const pstring &ashort, const pstring &along, const T &defval, std::vector<pstring> &&limit, const pstring &help)
- : option_str_limit_base(parent, ashort, along, std::move(limit), help), m_val(defval)
- {
- }
-
- T operator ()() const { return m_val; }
+ option_bool(options &parent, pstring ashort, pstring along, pstring help)
+ : option(parent, ashort, along, help, false), m_val(false)
+ {}
- pstring as_string() const { return limit()[m_val]; }
+ bool operator ()() { return m_val; }
protected:
- int parse(const pstring &argument) override
- {
- auto raw = plib::container::indexof(limit(), argument);
-
- if (raw != plib::container::npos)
- {
- m_val = static_cast<T>(raw);
- return 0;
- }
- else
- return 1;
- }
+ virtual int parse(const pstring &argument) override;
private:
- T m_val;
+ bool m_val;
};
-class option_bool : public option
+class option_double : public option
{
public:
- option_bool(options &parent, const pstring &ashort, const pstring &along, const pstring &help)
- : option(parent, ashort, along, help, false), m_val(false)
+ option_double(options &parent, pstring ashort, pstring along, double defval, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
{}
- bool operator ()() const { return m_val; }
+ double operator ()() { return m_val; }
protected:
- int parse(const pstring &argument) override;
+ virtual int parse(const pstring &argument) override;
private:
- bool m_val;
+ double m_val;
};
-template <typename T>
-class option_num : public option
+class option_long : public option
{
public:
- option_num(options &parent, const pstring &ashort, const pstring &along, T defval,
- const pstring &help,
- T minval = std::numeric_limits<T>::min(),
- T maxval = std::numeric_limits<T>::max() )
- : option(parent, ashort, along, help, true)
- , m_val(defval)
- , m_min(minval)
- , m_max(maxval)
+ option_long(options &parent, pstring ashort, pstring along, long defval, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
{}
- T operator ()() const { return m_val; }
+ long operator ()() { return m_val; }
protected:
- int parse(const pstring &argument) override
- {
- bool err;
- m_val = pstonum_ne<T>(argument, err);
- return (err ? 1 : (m_val < m_min || m_val > m_max));
- }
+ virtual int parse(const pstring &argument) override;
private:
- T m_val;
- T m_min;
- T m_max;
+ long m_val;
};
class option_vec : public option
{
public:
- option_vec(options &parent, const pstring &ashort, const pstring &along, const pstring &help)
+ option_vec(options &parent, pstring ashort, pstring along, pstring help)
: option(parent, ashort, along, help, true)
{}
- const std::vector<pstring> &operator ()() const { return m_val; }
+ std::vector<pstring> operator ()() { return m_val; }
protected:
- int parse(const pstring &argument) override;
+ virtual int parse(const pstring &argument) override;
private:
std::vector<pstring> m_val;
};
-class option_args : public option_vec
-{
-public:
- option_args(options &parent, const pstring &help)
- : option_vec(parent, "", "", help)
- {}
-};
-
-class options : public nocopyassignmove
+class options
{
public:
options();
- explicit options(option **o);
+ explicit options(option *o[]);
+
+ ~options();
void register_option(option_base *opt);
- int parse(int argc, char **argv);
+ int parse(int argc, char *argv[]);
- pstring help(const pstring &description, const pstring &usage,
- unsigned width = 72, unsigned indent = 20) const;
+ pstring help(pstring description, pstring usage,
+ unsigned width = 72, unsigned indent = 20);
- pstring app() const { return m_app; }
+ pstring app() { return m_app; }
private:
- static pstring split_paragraphs(const pstring &text, unsigned width, unsigned indent,
+ static pstring split_paragraphs(pstring text, unsigned width, unsigned indent,
unsigned firstline_indent);
- void check_consistency();
-
- template <typename T>
- T *getopt_type() const
- {
- for (auto & optbase : m_opts )
- {
- if (auto opt = dynamic_cast<T *>(optbase))
- return opt;
- }
- return nullptr;
- }
-
- option *getopt_short(const pstring &arg) const;
- option *getopt_long(const pstring &arg) const;
+ option *getopt_short(pstring arg);
+ option *getopt_long(pstring arg);
std::vector<option_base *> m_opts;
pstring m_app;
- option_args * m_other_args;
};
-} // namespace plib
+}
#endif /* POPTIONS_H_ */
diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp
index 5e1a231da81..7547572192d 100644
--- a/src/lib/netlist/plib/pparser.cpp
+++ b/src/lib/netlist/plib/pparser.cpp
@@ -16,6 +16,16 @@ namespace plib {
// A simple tokenizer
// ----------------------------------------------------------------------------------------
+ptokenizer::ptokenizer(plib::putf8_reader &strm)
+: m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
+{
+}
+
+ptokenizer::~ptokenizer()
+{
+}
+
+
pstring ptokenizer::currentline_str()
{
return m_cur_line;
@@ -24,7 +34,7 @@ pstring ptokenizer::currentline_str()
void ptokenizer::skipeol()
{
- pstring::value_type c = getc();
+ pstring::code_t c = getc();
while (c)
{
if (c == 10)
@@ -39,11 +49,11 @@ void ptokenizer::skipeol()
}
-pstring::value_type ptokenizer::getc()
+pstring::code_t ptokenizer::getc()
{
if (m_unget != 0)
{
- pstring::value_type c = m_unget;
+ pstring::code_t c = m_unget;
m_unget = 0;
return c;
}
@@ -56,11 +66,11 @@ pstring::value_type ptokenizer::getc()
return 0;
return '\n';
}
- pstring::value_type c = *(m_px++);
+ pstring::code_t c = *(m_px++);
return c;
}
-void ptokenizer::ungetc(pstring::value_type c)
+void ptokenizer::ungetc(pstring::code_t c)
{
m_unget = c;
}
@@ -112,7 +122,6 @@ pstring ptokenizer::get_identifier_or_number()
return tok.str();
}
-// FIXME: combine into template
double ptokenizer::get_number_double()
{
token_t tok = get_token();
@@ -120,8 +129,8 @@ double ptokenizer::get_number_double()
{
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
}
- bool err;
- auto ret = plib::pstonum_ne<double>(tok.str(), err);
+ bool err = false;
+ double ret = tok.str().as_double(&err);
if (err)
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
return ret;
@@ -134,8 +143,8 @@ long ptokenizer::get_number_long()
{
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
}
- bool err;
- auto ret = plib::pstonum_ne<long>(tok.str(), err);
+ bool err = false;
+ long ret = tok.str().as_long(&err);
if (err)
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
return ret;
@@ -173,7 +182,7 @@ ptokenizer::token_t ptokenizer::get_token()
ptokenizer::token_t ptokenizer::get_token_internal()
{
/* skip ws */
- pstring::value_type c = getc();
+ pstring::code_t c = getc();
while (m_whitespace.find(c) != pstring::npos)
{
c = getc();
@@ -263,31 +272,28 @@ void ptokenizer::error(const pstring &errs)
// A simple preprocessor
// ----------------------------------------------------------------------------------------
-ppreprocessor::ppreprocessor(defines_map_type *defines)
-: pistream()
-, m_ifflag(0)
-, m_level(0)
-, m_lineno(0)
-, m_pos(0)
-, m_state(PROCESS)
-, m_comment(false)
+ppreprocessor::ppreprocessor(std::vector<define_t> *defines)
+: m_ifflag(0), m_level(0), m_lineno(0)
{
- m_expr_sep.emplace_back("!");
- m_expr_sep.emplace_back("(");
- m_expr_sep.emplace_back(")");
- m_expr_sep.emplace_back("+");
- m_expr_sep.emplace_back("-");
- m_expr_sep.emplace_back("*");
- m_expr_sep.emplace_back("/");
- m_expr_sep.emplace_back("&&");
- m_expr_sep.emplace_back("||");
- m_expr_sep.emplace_back("==");
- m_expr_sep.emplace_back(" ");
- m_expr_sep.emplace_back("\t");
+ m_expr_sep.push_back("!");
+ m_expr_sep.push_back("(");
+ m_expr_sep.push_back(")");
+ m_expr_sep.push_back("+");
+ m_expr_sep.push_back("-");
+ m_expr_sep.push_back("*");
+ m_expr_sep.push_back("/");
+ m_expr_sep.push_back("==");
+ m_expr_sep.push_back(" ");
+ m_expr_sep.push_back("\t");
- if (defines != nullptr)
- m_defines = *defines;
m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")});
+ if (defines != nullptr)
+ {
+ for (auto & p : *defines)
+ {
+ m_defines.insert({p.m_name, p});
+ }
+ }
}
void ppreprocessor::error(const pstring &err)
@@ -295,42 +301,35 @@ void ppreprocessor::error(const pstring &err)
throw pexception("PREPRO ERROR: " + err);
}
-pstream::size_type ppreprocessor::vread(value_type *buf, const pstream::size_type n)
-{
- size_type bytes = std::min(m_buf.size() - m_pos, n);
-
- if (bytes==0)
- return 0;
-
- std::memcpy(buf, m_buf.c_str() + m_pos, bytes);
- m_pos += bytes;
- return bytes;
-}
-
-#define CHECKTOK2(p_op, p_prio) \
- else if (tok == # p_op) \
- { \
- if (prio < (p_prio)) \
- return val; \
- start++; \
- const auto v2 = expr(sexpr, start, (p_prio)); \
- val = (val p_op v2); \
- } \
-// Operator precedence see https://en.cppreference.com/w/cpp/language/operator_precedence
-int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio)
+double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio)
{
- int val = 0;
+ double val;
pstring tok=sexpr[start];
if (tok == "(")
{
start++;
- val = expr(sexpr, start, /*prio*/ 255);
+ val = expr(sexpr, start, /*prio*/ 0);
if (sexpr[start] != ")")
error("parsing error!");
start++;
}
+ else if (tok == "!")
+ {
+ start++;
+ val = expr(sexpr, start, 90);
+ if (val != 0)
+ val = 0;
+ else
+ val = 1;
+ }
+ else
+ {
+ tok=sexpr[start];
+ val = tok.as_double();
+ start++;
+ }
while (start < sexpr.size())
{
tok=sexpr[start];
@@ -339,25 +338,36 @@ int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, i
// FIXME: catch error
return val;
}
- else if (tok == "!")
+ else if (tok == "+")
{
- if (prio < 3)
+ if (prio > 10)
return val;
start++;
- val = !expr(sexpr, start, 3);
+ val = val + expr(sexpr, start, 10);
}
- CHECKTOK2(*, 5)
- CHECKTOK2(/, 5)
- CHECKTOK2(+, 6)
- CHECKTOK2(-, 6)
- CHECKTOK2(==, 10)
- CHECKTOK2(&&, 14)
- CHECKTOK2(||, 15)
- else
+ else if (tok == "-")
{
- // FIXME: error handling
- val = plib::pstonum<decltype(val)>(tok);
+ if (prio > 10)
+ return val;
+ start++;
+ val = val - expr(sexpr, start, 10);
+ }
+ else if (tok == "*")
+ {
+ start++;
+ val = val * expr(sexpr, start, 20);
+ }
+ else if (tok == "/")
+ {
+ start++;
+ val = val / expr(sexpr, start, 20);
+ }
+ else if (tok == "==")
+ {
+ if (prio > 5)
+ return val;
start++;
+ val = (val == expr(sexpr, start, 5)) ? 1.0 : 0.0;
}
}
return val;
@@ -366,7 +376,10 @@ int ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, i
ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
{
auto idx = m_defines.find(name);
- return (idx != m_defines.end()) ? &idx->second : nullptr;
+ if (idx != m_defines.end())
+ return &idx->second;
+ else
+ return nullptr;
}
pstring ppreprocessor::replace_macros(const pstring &line)
@@ -376,135 +389,78 @@ pstring ppreprocessor::replace_macros(const pstring &line)
for (auto & elem : elems)
{
define_t *def = get_define(elem);
- ret += (def != nullptr) ? def->m_replace : elem;
+ if (def != nullptr)
+ ret += def->m_replace;
+ else
+ ret += elem;
}
return ret;
}
-static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, const pstring &sep)
+static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, pstring sep)
{
pstring ret("");
- for (std::size_t i = start; i < elems.size(); i++)
+ for (auto & elem : elems)
{
- ret += elems[i];
+ ret += elem;
ret += sep;
}
return ret;
}
-pstring ppreprocessor::process_comments(pstring line)
-{
- bool in_string = false;
-
- std::size_t e = line.size();
- pstring ret = "";
- for (std::size_t i=0; i < e; )
- {
- pstring c = plib::left(line, 1);
- line = line.substr(1);
- if (!m_comment)
- {
- if (c=="\"")
- {
- in_string = !in_string;
- ret += c;
- }
- else if (in_string && c=="\\")
- {
- i++;
- ret += (c + plib::left(line, 1));
- line = line.substr(1);
- }
- else if (!in_string && c=="/" && plib::left(line,1) == "*")
- m_comment = true;
- else if (!in_string && c=="/" && plib::left(line,1) == "/")
- break;
- else
- ret += c;
- }
- else
- if (c=="*" && plib::left(line,1) == "/")
- {
- i++;
- line = line.substr(1);
- m_comment = false;
- }
- i++;
- }
- return ret;
-}
-
-pstring ppreprocessor::process_line(pstring line)
+pstring ppreprocessor::process_line(const pstring &line)
{
- bool line_cont = plib::right(line, 1) == "\\";
- if (line_cont)
- line = plib::left(line, line.size() - 1);
-
- if (m_state == LINE_CONTINUATION)
- m_line += line;
- else
- m_line = line;
-
- if (line_cont)
- {
- m_state = LINE_CONTINUATION;
- return "";
- }
- else
- m_state = PROCESS;
-
- line = process_comments(m_line);
-
- pstring lt = plib::trim(plib::replace_all(line, pstring("\t"), pstring(" ")));
+ pstring lt = line.replace_all("\t"," ").trim();
pstring ret;
+ m_lineno++;
// FIXME ... revise and extend macro handling
- if (plib::startsWith(lt, "#"))
+ if (lt.startsWith("#"))
{
std::vector<pstring> lti(psplit(lt, " ", true));
- if (lti[0] == "#if")
+ if (lti[0].equals("#if"))
{
m_level++;
std::size_t start = 0;
lt = replace_macros(lt);
- std::vector<pstring> t(psplit(replace_all(lt.substr(3), pstring(" "), pstring("")), m_expr_sep));
- auto val = static_cast<int>(expr(t, start, 255));
+ std::vector<pstring> t(psplit(lt.substr(3).replace_all(" ",""), m_expr_sep));
+ int val = static_cast<int>(expr(t, start, 0));
if (val == 0)
m_ifflag |= (1 << m_level);
}
- else if (lti[0] == "#ifdef")
+ else if (lti[0].equals("#ifdef"))
{
m_level++;
if (get_define(lti[1]) == nullptr)
m_ifflag |= (1 << m_level);
}
- else if (lti[0] == "#ifndef")
+ else if (lti[0].equals("#ifndef"))
{
m_level++;
if (get_define(lti[1]) != nullptr)
m_ifflag |= (1 << m_level);
}
- else if (lti[0] == "#else")
+ else if (lti[0].equals("#else"))
{
m_ifflag ^= (1 << m_level);
}
- else if (lti[0] == "#endif")
+ else if (lti[0].equals("#endif"))
{
m_ifflag &= ~(1 << m_level);
m_level--;
}
- else if (lti[0] == "#include")
+ else if (lti[0].equals("#include"))
{
// ignore
}
- else if (lti[0] == "#pragma")
+ else if (lti[0].equals("#pragma"))
{
- if (m_ifflag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
+ if (m_ifflag == 0 && lti.size() > 3 && lti[1].equals("NETLIST"))
{
- if (lti[2] == "warning")
+ if (lti[2].equals("warning"))
error("NETLIST: " + catremainder(lti, 3, " "));
}
}
- else if (lti[0] == "#define")
+ else if (lti[0].equals("#define"))
{
if (m_ifflag == 0)
{
@@ -514,20 +470,28 @@ pstring ppreprocessor::process_line(pstring line)
}
}
else
- {
- if (m_ifflag == 0)
- error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line)));
- }
+ error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(line));
}
else
{
lt = replace_macros(lt);
if (m_ifflag == 0)
+ {
ret += lt;
+ }
}
return ret;
}
+void ppreprocessor::process(putf8_reader &istrm, putf8_writer &ostrm)
+{
+ pstring line;
+ while (istrm.readline(line))
+ {
+ line = process_line(line);
+ ostrm.writeline(line);
+ }
+}
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h
index 1eca20e99ad..7ec517255c8 100644
--- a/src/lib/netlist/plib/pparser.h
+++ b/src/lib/netlist/plib/pparser.h
@@ -8,27 +8,20 @@
#ifndef PPARSER_H_
#define PPARSER_H_
+#include "pstring.h"
#include "plists.h"
#include "pstream.h"
-#include "pstring.h"
-#include <cstdint>
#include <unordered_map>
-
+#include <cstdint>
namespace plib {
-class ptokenizer
+class ptokenizer : nocopyassignmove
{
public:
- template <typename T>
- ptokenizer(T &&strm) // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
- : m_strm(std::forward<T>(strm)), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
- {
- }
-
- COPYASSIGNMOVE(ptokenizer, delete)
+ explicit ptokenizer(plib::putf8_reader &strm);
- virtual ~ptokenizer() = default;
+ virtual ~ptokenizer();
enum token_type
{
@@ -98,23 +91,22 @@ public:
void require_token(const token_id_t &token_num);
void require_token(const token_t &tok, const token_id_t &token_num);
- token_id_t register_token(const pstring &token)
+ token_id_t register_token(pstring token)
{
token_id_t ret(m_tokens.size());
m_tokens.emplace(token, ret);
return ret;
}
- ptokenizer & identifier_chars(pstring s) { m_identifier_chars = std::move(s); return *this; }
- ptokenizer & number_chars(pstring st, pstring rem) { m_number_chars_start = std::move(st); m_number_chars = std::move(rem); return *this; }
- ptokenizer & string_char(pstring::value_type c) { m_string = c; return *this; }
- ptokenizer & whitespace(pstring s) { m_whitespace = std::move(s); return *this; }
- ptokenizer & comment(const pstring &start, const pstring &end, const pstring &line)
+ void set_identifier_chars(pstring s) { m_identifier_chars = s; }
+ void set_number_chars(pstring st, pstring rem) { m_number_chars_start = st; m_number_chars = rem; }
+ void set_string_char(pstring::code_t c) { m_string = c; }
+ void set_whitespace(pstring s) { m_whitespace = s; }
+ void set_comment(pstring start, pstring end, pstring line)
{
m_tok_comment_start = register_token(start);
m_tok_comment_end = register_token(end);
m_tok_line_comment = register_token(line);
- return *this;
}
token_t get_token_internal();
@@ -126,17 +118,17 @@ protected:
private:
void skipeol();
- pstring::value_type getc();
- void ungetc(pstring::value_type c);
+ pstring::code_t getc();
+ void ungetc(pstring::code_t c);
bool eof() { return m_strm.eof(); }
- putf8_reader m_strm;
+ putf8_reader &m_strm;
int m_lineno;
pstring m_cur_line;
pstring::const_iterator m_px;
- pstring::value_type m_unget;
+ pstring::code_t m_unget;
/* tokenizer stuff follows ... */
@@ -145,7 +137,7 @@ private:
pstring m_number_chars_start;
std::unordered_map<pstring, token_id_t> m_tokens;
pstring m_whitespace;
- pstring::value_type m_string;
+ pstring::code_t m_string;
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
@@ -153,7 +145,7 @@ private:
};
-class ppreprocessor : public pistream
+class ppreprocessor : plib::nocopyassignmove
{
public:
@@ -166,80 +158,29 @@ public:
pstring m_replace;
};
- using defines_map_type = std::unordered_map<pstring, define_t>;
-
- explicit ppreprocessor(defines_map_type *defines = nullptr);
- ~ppreprocessor() override = default;
-
- template <typename T>
- ppreprocessor & process(T &&istrm)
- {
- putf8_reader reader(std::forward<T>(istrm));
- pstring line;
- while (reader.readline(line))
- {
- m_lineno++;
- line = process_line(line);
- m_buf += decltype(m_buf)(line.c_str()) + static_cast<char>(10);
- }
- return *this;
- }
-
- COPYASSIGN(ppreprocessor, delete)
- ppreprocessor &operator=(ppreprocessor &&src) = delete;
+ explicit ppreprocessor(std::vector<define_t> *defines = nullptr);
+ virtual ~ppreprocessor() {}
-
- ppreprocessor(ppreprocessor &&s) noexcept
- : m_defines(std::move(s.m_defines))
- , m_expr_sep(std::move(s.m_expr_sep))
- , m_ifflag(s.m_ifflag)
- , m_level(s.m_level)
- , m_lineno(s.m_lineno)
- , m_buf(std::move(s.m_buf))
- , m_pos(s.m_pos)
- , m_state(s.m_state)
- , m_comment(s.m_comment)
- {
- }
+ void process(putf8_reader &istrm, putf8_writer &ostrm);
protected:
-
- size_type vread(value_type *buf, const size_type n) override;
- void vseek(const pos_type n) override
- {
- plib::unused_var(n);
- /* FIXME throw exception - should be done in base unless implemented */
- }
- pos_type vtell() const override { return m_pos; }
-
- int expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
+ double expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
define_t *get_define(const pstring &name);
pstring replace_macros(const pstring &line);
virtual void error(const pstring &err);
private:
- enum state_e
- {
- PROCESS,
- LINE_CONTINUATION
- };
- pstring process_line(pstring line);
- pstring process_comments(pstring line);
+ pstring process_line(const pstring &line);
- defines_map_type m_defines;
+ std::unordered_map<pstring, define_t> m_defines;
std::vector<pstring> m_expr_sep;
std::uint_least64_t m_ifflag; // 31 if levels
int m_level;
int m_lineno;
- pstring_t<pu8_traits> m_buf;
- pos_type m_pos;
- state_e m_state;
- pstring m_line;
- bool m_comment;
};
-} // namespace plib
+}
#endif /* PPARSER_H_ */
diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h
index 9c5329cccde..dc151d5d6a6 100644
--- a/src/lib/netlist/plib/ppmf.h
+++ b/src/lib/netlist/plib/ppmf.h
@@ -10,8 +10,9 @@
#include "pconfig.h"
-#include <cstdint>
#include <utility>
+#include <cstdint>
+
/*
*
@@ -69,8 +70,7 @@ namespace plib {
using generic_function = void (*)();
template<typename MemberFunctionType>
- mfp(MemberFunctionType mftp) // NOLINT(cppcoreguidelines-pro-type-member-init)
-
+ mfp(MemberFunctionType mftp)
: m_function(0), m_this_delta(0), m_size(sizeof(mfp))
{
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
@@ -82,7 +82,7 @@ namespace plib {
mfp mfpo(mftp);
//return mfpo.update_after_bind<FunctionType>(object);
generic_function rfunc(nullptr);
- auto robject = reinterpret_cast<generic_class *>(object);
+ generic_class *robject = reinterpret_cast<generic_class *>(object);
mfpo.convert_to_generic(rfunc, robject);
func = reinterpret_cast<FunctionType>(rfunc);
object = reinterpret_cast<ObjectType *>(robject);
@@ -95,8 +95,7 @@ namespace plib {
if (PHAS_PMF_INTERNAL == 1)
{
// apply the "this" delta to the object first
- // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
- auto o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+ generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// if the low bit of the vtable index is clear, then it is just a raw function pointer
if (!(m_function & 1))
@@ -242,28 +241,23 @@ namespace plib {
{
public:
class generic_class;
-
- template <class C>
- using MemberFunctionType = R (C::*)(Targs...);
-
pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
- template<typename O>
- pmfp(MemberFunctionType<O> mftp, O *object)
+ template<typename MemberFunctionType, typename O>
+ pmfp(MemberFunctionType mftp, O *object)
: pmfp_base<R, Targs...>()
{
this->set(mftp, object);
}
-
- template<typename O>
- void set(MemberFunctionType<O> mftp, O *object)
+ template<typename MemberFunctionType, typename O>
+ void set(MemberFunctionType mftp, O *object)
{
this->set_base(mftp, object);
m_obj = reinterpret_cast<generic_class *>(object);
}
- inline R operator()(Targs ... args)
+ inline R operator()(Targs... args)
{
return this->call(m_obj, std::forward<Targs>(args)...);
}
@@ -275,6 +269,6 @@ namespace plib {
};
-} // namespace plib
+}
#endif /* PPMF_H_ */
diff --git a/src/lib/netlist/plib/pstate.cpp b/src/lib/netlist/plib/pstate.cpp
index 3bd93ed4f8e..043033ed1ea 100644
--- a/src/lib/netlist/plib/pstate.cpp
+++ b/src/lib/netlist/plib/pstate.cpp
@@ -9,6 +9,17 @@
#include "palloc.h"
namespace plib {
+state_manager_t::state_manager_t()
+{
+}
+
+state_manager_t::~state_manager_t()
+{
+ m_save.clear();
+ m_custom.clear();
+}
+
+
void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr)
{
@@ -18,40 +29,46 @@ void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, c
void state_manager_t::remove_save_items(const void *owner)
{
- auto i = m_save.end();
- while (i != m_save.begin())
+ for (auto i = m_save.begin(); i != m_save.end(); )
{
- i--;
if (i->get()->m_owner == owner)
i = m_save.erase(i);
+ else
+ i++;
}
- i = m_custom.end();
- while (i > m_custom.begin())
+ for (auto i = m_custom.begin(); i != m_custom.end(); )
{
- i--;
if (i->get()->m_owner == owner)
i = m_custom.erase(i);
+ else
+ i++;
}
}
void state_manager_t::pre_save()
{
for (auto & s : m_custom)
- s->m_callback->on_pre_save(*this);
+ s->m_callback->on_pre_save();
}
void state_manager_t::post_load()
{
for (auto & s : m_custom)
- s->m_callback->on_post_load(*this);
+ s->m_callback->on_post_load();
}
template<> void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname)
{
+ //save_state_ptr(stname, DT_CUSTOM, 0, 1, &state);
callback_t *state_p = &state;
auto p = plib::make_unique<entry_t>(stname, owner, state_p);
m_custom.push_back(std::move(p));
state.register_state(*this, stname);
}
-} // namespace plib
+state_manager_t::callback_t::~callback_t()
+{
+}
+
+
+}
diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h
index ac75ca6b69e..9757d6408b7 100644
--- a/src/lib/netlist/plib/pstate.h
+++ b/src/lib/netlist/plib/pstate.h
@@ -8,13 +8,11 @@
#ifndef PSTATE_H_
#define PSTATE_H_
-#include "palloc.h"
#include "pstring.h"
#include "ptypes.h"
-#include <array>
-#include <memory>
#include <vector>
+#include <memory>
// ----------------------------------------------------------------------------------------
// state saving ...
@@ -40,31 +38,32 @@ public:
const bool is_custom;
};
- template<typename T>
- static datatype_t dtype()
+ template<typename T> struct datatype_f
{
- return datatype_t(sizeof(T),
- plib::is_integral<T>::value || std::is_enum<T>::value,
- std::is_floating_point<T>::value);
- }
+ static inline const datatype_t f()
+ {
+ return datatype_t(sizeof(T),
+ plib::is_integral<T>::value || std::is_enum<T>::value,
+ std::is_floating_point<T>::value);
+ }
+ };
class callback_t
{
public:
using list_t = std::vector<callback_t *>;
+ virtual ~callback_t();
+
virtual void register_state(state_manager_t &manager, const pstring &module) = 0;
- virtual void on_pre_save(state_manager_t &manager) = 0;
- virtual void on_post_load(state_manager_t &manager) = 0;
+ virtual void on_pre_save() = 0;
+ virtual void on_post_load() = 0;
protected:
- callback_t() = default;
- ~callback_t() = default;
- COPYASSIGNMOVE(callback_t, default)
};
struct entry_t
{
- using list_t = std::vector<plib::unique_ptr<entry_t>>;
+ using list_t = std::vector<std::unique_ptr<entry_t>>;
entry_t(const pstring &stname, const datatype_t &dt, const void *owner,
const std::size_t count, void *ptr)
@@ -73,6 +72,8 @@ public:
entry_t(const pstring &stname, const void *owner, callback_t *callback)
: m_name(stname), m_dt(datatype_t(true)), m_owner(owner), m_callback(callback), m_count(0), m_ptr(nullptr) { }
+ ~entry_t() { }
+
pstring m_name;
const datatype_t m_dt;
const void * m_owner;
@@ -81,49 +82,35 @@ public:
void * m_ptr;
};
- state_manager_t() = default;
+ state_manager_t();
+ ~state_manager_t();
- template<typename C>
- void save_item(const void *owner, C &state, const pstring &stname)
+ template<typename C> void save_item(const void *owner, C &state, const pstring &stname)
{
- save_state_ptr( owner, stname, dtype<C>(), 1, &state);
+ save_state_ptr( owner, stname, datatype_f<C>::f(), 1, &state);
}
- template<typename C, std::size_t N>
- void save_item(const void *owner, C (&state)[N], const pstring &stname) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
+ template<typename C, std::size_t N> void save_item(const void *owner, C (&state)[N], const pstring &stname)
{
- save_state_ptr(owner, stname, dtype<C>(), N, &(state[0]));
+ save_state_ptr(owner, stname, datatype_f<C>::f(), N, &(state[0]));
}
- template<typename C>
- void save_item(const void *owner, C *state, const pstring &stname, const std::size_t count)
+ template<typename C> void save_item(const void *owner, C *state, const pstring &stname, const std::size_t count)
{
- save_state_ptr(owner, stname, dtype<C>(), count, state);
+ save_state_ptr(owner, stname, datatype_f<C>::f(), count, state);
}
template<typename C>
void save_item(const void *owner, std::vector<C> &v, const pstring &stname)
{
- save_state_ptr(owner, stname, dtype<C>(), v.size(), v.data());
- }
-
- template<typename C, std::size_t N>
- void save_item(const void *owner, std::array<C, N> &a, const pstring &stname)
- {
- save_state_ptr(owner, stname, dtype<C>(), N, a.data());
+ save_state(v.data(), owner, stname, v.size());
}
void pre_save();
void post_load();
void remove_save_items(const void *owner);
- const std::vector<const entry_t *> save_list() const
- {
- std::vector<const entry_t *> ret;
- for (auto &i : m_save)
- ret.push_back(i.get());
- return ret;
- }
+ const entry_t::list_t &save_list() const { return m_save; }
void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr);
@@ -137,6 +124,6 @@ private:
template<> void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname);
-} // namespace plib
+}
#endif /* PSTATE_H_ */
diff --git a/src/lib/netlist/plib/pstream.cpp b/src/lib/netlist/plib/pstream.cpp
index a7acdaafb52..420f63c9e5e 100644
--- a/src/lib/netlist/plib/pstream.cpp
+++ b/src/lib/netlist/plib/pstream.cpp
@@ -8,9 +8,9 @@
#include "pstream.h"
#include "palloc.h"
-#include <algorithm>
#include <cstdio>
#include <cstdlib>
+#include <algorithm>
// VS2015 prefers _dup
#ifdef _WIN32
@@ -21,14 +21,34 @@
namespace plib {
+pstream::~pstream()
+{
+}
+
// -----------------------------------------------------------------------------
// pistream: input stream
// -----------------------------------------------------------------------------
+pistream::~pistream()
+{
+}
+
// -----------------------------------------------------------------------------
// postream: output stream
// -----------------------------------------------------------------------------
+postream::~postream()
+{
+}
+
+void postream::write(pistream &strm)
+{
+ char buf[1024];
+ pos_type r;
+ while ((r=strm.read(buf, 1024)) > 0)
+ write(buf, r);
+}
+
// -----------------------------------------------------------------------------
// Input file stream
// -----------------------------------------------------------------------------
@@ -71,7 +91,7 @@ pifilestream::~pifilestream()
}
}
-pifilestream::pos_type pifilestream::vread(value_type *buf, const pos_type n)
+pifilestream::pos_type pifilestream::vread(void *buf, const pos_type n)
{
pos_type r = fread(buf, 1, n, static_cast<FILE *>(m_file));
if (r < n)
@@ -99,7 +119,7 @@ void pifilestream::vseek(const pos_type n)
throw file_e("Generic file operation failed: {}", m_filename);
}
-pifilestream::pos_type pifilestream::vtell() const
+pifilestream::pos_type pifilestream::vtell()
{
long ret = ftell(static_cast<FILE *>(m_file));
if (ret < 0)
@@ -120,6 +140,10 @@ pstdin::pstdin()
/* nothing to do */
}
+pstdin::~pstdin()
+{
+}
+
// -----------------------------------------------------------------------------
// Output file stream
// -----------------------------------------------------------------------------
@@ -156,11 +180,12 @@ pofilestream::~pofilestream()
}
}
-void pofilestream::vwrite(const value_type *buf, const pos_type n)
+void pofilestream::vwrite(const void *buf, const pos_type n)
{
std::size_t r = fwrite(buf, 1, n, static_cast<FILE *>(m_file));
if (r < n)
{
+ //printf("%ld %ld %s\n", r, n, strerror(errno));
if (ferror(static_cast<FILE *>(m_file)))
throw file_write_e(m_filename);
}
@@ -179,7 +204,7 @@ void pofilestream::vseek(const pos_type n)
}
}
-pstream::pos_type pofilestream::vtell() const
+pstream::pos_type pofilestream::vtell()
{
std::ptrdiff_t ret = ftell(static_cast<FILE *>(m_file));
if (ret < 0)
@@ -190,6 +215,11 @@ pstream::pos_type pofilestream::vtell() const
return static_cast<pos_type>(ret);
}
+postringstream::~postringstream()
+{
+}
+
+
// -----------------------------------------------------------------------------
// pstderr: write to stderr
// -----------------------------------------------------------------------------
@@ -203,6 +233,10 @@ pstderr::pstderr()
{
}
+pstderr::~pstderr()
+{
+}
+
// -----------------------------------------------------------------------------
// pstdout: write to stdout
// -----------------------------------------------------------------------------
@@ -216,32 +250,35 @@ pstdout::pstdout()
{
}
+pstdout::~pstdout()
+{
+}
+
// -----------------------------------------------------------------------------
// Memory stream
// -----------------------------------------------------------------------------
pimemstream::pimemstream(const void *mem, const pos_type len)
- : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast<const char *>(mem))
+ : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem(static_cast<const pstring::mem_t *>(mem))
{
}
-pimemstream::pimemstream()
- : pistream(FLAG_SEEKABLE), m_pos(0), m_len(0), m_mem(static_cast<const char *>(nullptr))
+pimemstream::pimemstream(const pomemstream &ostrm)
+: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast<pstring::mem_t *>(ostrm.memory()))
{
}
-pimemstream::pimemstream(const pomemstream &ostrm)
-: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem(reinterpret_cast<const char *>(ostrm.memory()))
+pimemstream::~pimemstream()
{
}
-pimemstream::pos_type pimemstream::vread(value_type *buf, const pos_type n)
+pimemstream::pos_type pimemstream::vread(void *buf, const pos_type n)
{
pos_type ret = (m_pos + n <= m_len) ? n : m_len - m_pos;
if (ret > 0)
{
- std::copy(m_mem + m_pos, m_mem + m_pos + ret, reinterpret_cast<char *>(buf));
+ std::copy(m_mem + m_pos, m_mem + m_pos + ret, static_cast<char *>(buf));
m_pos += ret;
}
@@ -258,45 +295,78 @@ void pimemstream::vseek(const pos_type n)
}
-pimemstream::pos_type pimemstream::vtell() const
+pimemstream::pos_type pimemstream::vtell()
{
return m_pos;
}
+pistringstream::~pistringstream()
+{
+}
+
// -----------------------------------------------------------------------------
// Output memory stream
// -----------------------------------------------------------------------------
pomemstream::pomemstream()
-: postream(FLAG_SEEKABLE), m_pos(0), m_mem(1024)
+: postream(FLAG_SEEKABLE), m_pos(0), m_capacity(1024), m_size(0)
+{
+ m_mem = palloc_array<char>(m_capacity);
+}
+
+pomemstream::~pomemstream()
{
- m_mem.clear();
+ pfree_array(m_mem);
}
-void pomemstream::vwrite(const value_type *buf, const pos_type n)
+void pomemstream::vwrite(const void *buf, const pos_type n)
{
- if (m_pos + n >= m_mem.size())
- m_mem.resize(m_pos + n);
+ if (m_pos + n >= m_capacity)
+ {
+ while (m_pos + n >= m_capacity)
+ m_capacity *= 2;
+ char *o = m_mem;
+ m_mem = palloc_array<char>(m_capacity);
+ if (m_mem == nullptr)
+ {
+ throw out_of_mem_e("pomemstream::vwrite");
+ }
+ std::copy(o, o + m_pos, m_mem);
+ pfree_array(o);
+ }
- std::copy(buf, buf + n, &m_mem[0] + m_pos);
+ std::copy(static_cast<const char *>(buf), static_cast<const char *>(buf) + n, m_mem + m_pos);
m_pos += n;
+ m_size = std::max(m_pos, m_size);
}
void pomemstream::vseek(const pos_type n)
{
m_pos = n;
- if (m_pos>=m_mem.size())
- m_mem.resize(m_pos);
+ m_size = std::max(m_pos, m_size);
+ if (m_size >= m_capacity)
+ {
+ while (m_size >= m_capacity)
+ m_capacity *= 2;
+ char *o = m_mem;
+ m_mem = palloc_array<char>(m_capacity);
+ if (m_mem == nullptr)
+ {
+ throw out_of_mem_e("pomemstream::vseek");
+ }
+ std::copy(o, o + m_pos, m_mem);
+ pfree_array(o);
+ }
}
-pstream::pos_type pomemstream::vtell() const
+pstream::pos_type pomemstream::vtell()
{
return m_pos;
}
bool putf8_reader::readline(pstring &line)
{
- putf8string::code_t c = 0;
+ pstring::code_t c = 0;
m_linebuf = "";
if (!this->readcode(c))
{
@@ -308,14 +378,23 @@ bool putf8_reader::readline(pstring &line)
if (c == 10)
break;
else if (c != 13) /* ignore CR */
- m_linebuf += putf8string(c);
+ m_linebuf += pstring(c);
if (!this->readcode(c))
break;
}
- line = m_linebuf.c_str();
+ line = m_linebuf;
return true;
}
+putf8_fmt_writer::putf8_fmt_writer(postream &strm)
+: pfmt_writer_t()
+, putf8_writer(strm)
+{
+}
+
+putf8_fmt_writer::~putf8_fmt_writer()
+{
+}
void putf8_fmt_writer::vdowrite(const pstring &ls) const
{
@@ -324,4 +403,4 @@ void putf8_fmt_writer::vdowrite(const pstring &ls) const
-} // namespace plib
+}
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index 93497eb1423..3e9ee99cba0 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -7,76 +7,46 @@
#ifndef PSTREAM_H_
#define PSTREAM_H_
-
-#include "palloc.h"
#include "pconfig.h"
-#include "pexception.h"
-#include "pfmtlog.h"
#include "pstring.h"
+#include "pfmtlog.h"
+#include "pexception.h"
-#define USE_CSTREAM (0)
-
-#include <array>
-#include <type_traits>
#include <vector>
-#if USE_CSTREAM
-#include <fstream>
-//#include <strstream>
-#include <sstream>
-#endif
-
namespace plib {
-
-#if USE_CSTREAM
-typedef std::ostream postream;
-typedef std::ofstream pofilestream;
-typedef std::ostringstream postringstream;
-typedef std::ostringstream pomemstream;
-
-#endif
-
// -----------------------------------------------------------------------------
// pstream: things common to all streams
// -----------------------------------------------------------------------------
-class pstream
+class pstream : nocopyassignmove
{
public:
using pos_type = std::size_t;
- using size_type = std::size_t;
static constexpr pos_type SEEK_EOF = static_cast<pos_type>(-1);
- COPYASSIGN(pstream, delete)
- pstream &operator=(pstream &&) noexcept = delete;
-
bool seekable() const { return ((m_flags & FLAG_SEEKABLE) != 0); }
- void seekp(const pos_type n)
+ void seek(const pos_type n)
{
- vseek(n);
+ return vseek(n);
}
- pos_type tellp() const
+ pos_type tell()
{
return vtell();
}
protected:
- pstream() : m_flags(0)
- {
- }
explicit pstream(const unsigned flags) : m_flags(flags)
{
}
- pstream(pstream &&src) noexcept = default;
-
- virtual ~pstream() = default;
+ ~pstream();
virtual void vseek(const pos_type n) = 0;
- virtual pos_type vtell() const = 0;
+ virtual pos_type vtell() = 0;
static constexpr unsigned FLAG_EOF = 0x01;
static constexpr unsigned FLAG_SEEKABLE = 0x04;
@@ -99,71 +69,51 @@ private:
// pistream: input stream
// -----------------------------------------------------------------------------
-template <typename T>
-class pistream_base : public pstream
+class pistream : public pstream
{
public:
- using value_type = T;
-
- ~pistream_base() noexcept override = default;
-
- COPYASSIGN(pistream_base, delete)
- pistream_base &operator=(pistream_base &&src) noexcept = delete;
+ virtual ~pistream();
bool eof() const { return ((flags() & FLAG_EOF) != 0); }
- pos_type read(T *buf, const pos_type n)
+ pos_type read(void *buf, const pos_type n)
{
return vread(buf, n);
}
protected:
- pistream_base() : pstream(0) {}
- explicit pistream_base(const unsigned flags) : pstream(flags) {}
- pistream_base(pistream_base &&src) noexcept : pstream(std::move(src)) {}
-
+ explicit pistream(const unsigned flags) : pstream(flags) {}
/* read up to n bytes from stream */
- virtual size_type vread(T *buf, const size_type n) = 0;
-};
+ virtual pos_type vread(void *buf, const pos_type n) = 0;
-using pistream = pistream_base<char>;
+};
// -----------------------------------------------------------------------------
// postream: output stream
// -----------------------------------------------------------------------------
-#if !USE_CSTREAM
-template <typename T>
-class postream_base : public pstream
+class postream : public pstream
{
public:
- using value_type = T;
-
- postream_base() = default;
- ~postream_base() noexcept override = default;
-
- COPYASSIGN(postream_base, delete)
- postream_base &operator=(postream_base &&src) noexcept = delete;
+ virtual ~postream();
- void write(const T *buf, const size_type n)
+ void write(const void *buf, const pos_type n)
{
vwrite(buf, n);
}
-protected:
- explicit postream_base(unsigned flags) : pstream(flags) {}
- postream_base(postream_base &&src) noexcept : pstream(std::move(src)) {}
+ void write(pistream &strm);
+protected:
+ explicit postream(unsigned flags) : pstream(flags) {}
/* write n bytes to stream */
- virtual void vwrite(const T *buf, const size_type n) = 0;
+ virtual void vwrite(const void *buf, const pos_type n) = 0;
private:
};
-using postream = postream_base<char>;
-
// -----------------------------------------------------------------------------
// pomemstream: output string stream
// -----------------------------------------------------------------------------
@@ -173,31 +123,22 @@ class pomemstream : public postream
public:
pomemstream();
+ virtual ~pomemstream() override;
- COPYASSIGN(pomemstream, delete)
-
- pomemstream(pomemstream &&src) noexcept
- : postream(std::move(src))
- , m_pos(src.m_pos)
- , m_mem(std::move(src.m_mem))
- {
- }
- pomemstream &operator=(pomemstream &&src) = delete;
-
- ~pomemstream() override = default;
-
- const char *memory() const { return m_mem.data(); }
- pos_type size() const { return m_mem.size(); }
+ char *memory() const { return m_mem; }
+ pos_type size() const { return m_size; }
protected:
/* write n bytes to stream */
- void vwrite(const value_type *buf, const pos_type) override;
- void vseek(const pos_type n) override;
- pos_type vtell() const override;
+ virtual void vwrite(const void *buf, const pos_type) override;
+ virtual void vseek(const pos_type n) override;
+ virtual pos_type vtell() override;
private:
pos_type m_pos;
- std::vector<char> m_mem;
+ pos_type m_capacity;
+ pos_type m_size;
+ char *m_mem;
};
class postringstream : public postream
@@ -205,26 +146,18 @@ class postringstream : public postream
public:
postringstream() : postream(0) { }
- postringstream(postringstream &&src) noexcept
- : postream(std::move(src))
- , m_buf(std::move(src.m_buf))
- { src.m_buf = ""; }
-
- COPYASSIGN(postringstream, delete)
- postringstream &operator=(postringstream &&src) = delete;
-
- ~postringstream() override = default;
+ virtual ~postringstream() override;
const pstring &str() { return m_buf; }
protected:
/* write n bytes to stream */
- void vwrite(const value_type *buf, const pos_type n) override
+ virtual void vwrite(const void *buf, const pos_type n) override
{
- m_buf += pstring(reinterpret_cast<const pstring::mem_t *>(buf), n);
+ m_buf += pstring(static_cast<const pstring::mem_t *>(buf), n, pstring::UTF8);
}
- void vseek(const pos_type n) override { unused_var(n); }
- pos_type vtell() const override { return m_buf.size(); }
+ virtual void vseek(const pos_type n) override { }
+ virtual pos_type vtell() override { return m_buf.mem_t_size(); }
private:
pstring m_buf;
@@ -238,28 +171,15 @@ class pofilestream : public postream
{
public:
- pofilestream(const pstring &fname);
- pofilestream(pofilestream &&src) noexcept
- : postream(std::move(src))
- , m_file(src.m_file)
- , m_pos(src.m_pos)
- , m_actually_close(src.m_actually_close)
- , m_filename(std::move(src.m_filename))
- {
- src.m_file = nullptr;
- src.m_actually_close = false;
- }
- COPYASSIGN(pofilestream, delete)
- pofilestream &operator=(pofilestream &&src) = delete;
-
- ~pofilestream() override;
+ explicit pofilestream(const pstring &fname);
+ virtual ~pofilestream() override;
protected:
pofilestream(void *file, const pstring &name, const bool do_close);
/* write n bytes to stream */
- void vwrite(const value_type *buf, const pos_type n) override;
- void vseek(const pos_type n) override;
- pos_type vtell() const override;
+ virtual void vwrite(const void *buf, const pos_type n) override;
+ virtual void vseek(const pos_type n) override;
+ virtual pos_type vtell() override;
private:
void *m_file;
@@ -273,17 +193,12 @@ private:
// -----------------------------------------------------------------------------
// pstderr: write to stderr
// -----------------------------------------------------------------------------
-#endif
class pstderr : public pofilestream
{
public:
pstderr();
- pstderr(pstderr &&src) noexcept = default;
- pstderr &operator=(pstderr &&src) = delete;
- COPYASSIGN(pstderr, delete)
-
- ~pstderr() noexcept override= default;
+ virtual ~pstderr();
};
// -----------------------------------------------------------------------------
@@ -294,11 +209,7 @@ class pstdout : public pofilestream
{
public:
pstdout();
- pstdout(pstdout &&src) noexcept = default;
- pstdout &operator=(pstdout &&src) = delete;
- COPYASSIGN(pstdout, delete)
-
- ~pstdout() noexcept override = default;
+ virtual ~pstdout();
};
// -----------------------------------------------------------------------------
@@ -309,29 +220,16 @@ class pifilestream : public pistream
{
public:
- pifilestream(const pstring &fname);
- ~pifilestream() override;
-
- pifilestream(pifilestream &&src) noexcept
- : pistream(std::move(src))
- , m_file(src.m_file)
- , m_pos(src.m_pos)
- , m_actually_close(src.m_actually_close)
- , m_filename(std::move(src.m_filename))
- {
- src.m_actually_close = false;
- src.m_file = nullptr;
- }
- COPYASSIGN(pifilestream, delete)
- pifilestream &operator=(pifilestream &&src) = delete;
+ explicit pifilestream(const pstring &fname);
+ virtual ~pifilestream() override;
protected:
pifilestream(void *file, const pstring &name, const bool do_close);
/* read up to n bytes from stream */
- pos_type vread(value_type *buf, const pos_type n) override;
- void vseek(const pos_type n) override;
- pos_type vtell() const override;
+ virtual pos_type vread(void *buf, const pos_type n) override;
+ virtual void vseek(const pos_type n) override;
+ virtual pos_type vtell() override;
private:
void *m_file;
@@ -351,10 +249,7 @@ class pstdin : public pifilestream
public:
pstdin();
- pstdin(pstdin &&src) noexcept = default;
- pstdin &operator=(pstdin &&src) = delete;
- COPYASSIGN(pstdin, delete)
- ~pstdin() override = default;
+ virtual ~pstdin() override;
};
// -----------------------------------------------------------------------------
@@ -366,36 +261,15 @@ class pimemstream : public pistream
public:
pimemstream(const void *mem, const pos_type len);
- pimemstream();
-
- pimemstream(pimemstream &&src) noexcept
- : pistream(std::move(src))
- , m_pos(src.m_pos)
- , m_len(src.m_len)
- , m_mem(src.m_mem)
- {
- src.m_mem = nullptr;
- }
- COPYASSIGN(pimemstream, delete)
- pimemstream &operator=(pimemstream &&src) = delete;
-
explicit pimemstream(const pomemstream &ostrm);
-
- ~pimemstream() override = default;
+ virtual ~pimemstream() override;
pos_type size() const { return m_len; }
protected:
-
- void set_mem(const void *mem, const pos_type len)
- {
- m_mem = static_cast<const char *>(mem);
- m_len = len;
- }
-
/* read up to n bytes from stream */
- pos_type vread(value_type *buf, const pos_type n) override;
- void vseek(const pos_type n) override;
- pos_type vtell() const override;
+ virtual pos_type vread(void *buf, const pos_type n) override;
+ virtual void vseek(const pos_type n) override;
+ virtual pos_type vtell() override;
private:
pos_type m_pos;
@@ -410,25 +284,12 @@ private:
class pistringstream : public pimemstream
{
public:
- pistringstream(const pstring &str)
- : pimemstream()
- , m_str(str)
- {
- set_mem(m_str.c_str(), std::strlen(m_str.c_str()));
- }
- pistringstream(pistringstream &&src) noexcept
- : pimemstream(std::move(src)), m_str(src.m_str)
- {
- set_mem(m_str.c_str(), std::strlen(m_str.c_str()));
- }
- COPYASSIGN(pistringstream, delete)
- pistringstream &operator=(pistringstream &&src) = delete;
-
- ~pistringstream() override = default;
+ explicit pistringstream(const pstring &str) : pimemstream(str.c_str(), str.mem_t_size()), m_str(str) { }
+ virtual ~pistringstream() override;
private:
/* only needed for a reference till destruction */
- const pstring m_str;
+ pstring m_str;
};
// -----------------------------------------------------------------------------
@@ -437,84 +298,47 @@ private:
/* this digests linux & dos/windows text files */
-
-template <typename T>
-struct constructor_helper
-{
- plib::unique_ptr<pistream> operator()(T &&s) { return std::move(plib::make_unique<T>(std::move(s))); }
-};
-
-// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
-class putf8_reader
+class putf8_reader : plib::nocopyassignmove
{
public:
+ explicit putf8_reader(pistream &strm) : m_strm(strm) {}
+ virtual ~putf8_reader() {}
- COPYASSIGN(putf8_reader, delete)
- putf8_reader &operator=(putf8_reader &&src) = delete;
- virtual ~putf8_reader() = default;
-
- template <typename T>
- friend struct constructor_helper;
-
- template <typename T>
- putf8_reader(T &&strm) // NOLINT(cppcoreguidelines-special-member-functions, misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
- : m_strm(std::move(constructor_helper<T>()(std::move(strm)))) // NOLINT(bugprone-move-forwarding-reference)
- {}
-
- bool eof() const { return m_strm->eof(); }
+ bool eof() const { return m_strm.eof(); }
bool readline(pstring &line);
- bool readbyte1(pistream::value_type &b)
+ bool readbyte1(char &b)
{
- return (m_strm->read(&b, 1) == 1);
+ return (m_strm.read(&b, 1) == 1);
}
- bool readcode(putf8string::traits_type::code_t &c)
+ bool readcode(pstring::code_t &c)
{
- std::array<pistream::value_type, 4> b{0};
- if (m_strm->read(&b[0], 1) != 1)
+ char b[4];
+ if (m_strm.read(&b[0], 1) != 1)
return false;
- const std::size_t l = putf8string::traits_type::codelen(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
+ const std::size_t l = pstring::traits_type::codelen(b);
for (std::size_t i = 1; i < l; i++)
- if (m_strm->read(&b[i], 1) != 1)
+ if (m_strm.read(&b[i], 1) != 1)
return false;
- c = putf8string::traits_type::code(reinterpret_cast<putf8string::traits_type::mem_t *>(&b));
+ c = pstring::traits_type::code(b);
return true;
}
private:
- plib::unique_ptr<pistream> m_strm;
- putf8string m_linebuf;
-};
-
-template <>
-struct constructor_helper<putf8_reader>
-{
- plib::unique_ptr<pistream> operator()(putf8_reader &&s) { return std::move(s.m_strm); }
-};
-
-template <>
-struct constructor_helper<plib::unique_ptr<pistream>>
-{
- plib::unique_ptr<pistream> operator()(plib::unique_ptr<pistream> &&s) { return std::move(s); }
+ pistream &m_strm;
+ pstring m_linebuf;
};
-
// -----------------------------------------------------------------------------
// putf8writer_t: writer on top of ostream
// -----------------------------------------------------------------------------
-class putf8_writer
+class putf8_writer : plib::nocopyassignmove
{
public:
- explicit putf8_writer(postream *strm) : m_strm(strm) {}
-
- putf8_writer(putf8_writer &&src) noexcept : m_strm(src.m_strm) {}
-
- COPYASSIGN(putf8_writer, delete)
- putf8_writer &operator=(putf8_writer &&src) = delete;
-
- virtual ~putf8_writer() = default;
+ explicit putf8_writer(postream &strm) : m_strm(strm) {}
+ virtual ~putf8_writer() {}
void writeline(const pstring &line) const
{
@@ -524,34 +348,24 @@ public:
void write(const pstring &text) const
{
- // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
- const putf8string conv_utf8(text);
- m_strm->write(reinterpret_cast<const pistream::value_type *>(conv_utf8.c_str()), conv_utf8.mem_t_size());
+ m_strm.write(text.c_str(), text.mem_t_size());
}
- void write(const pstring::value_type c) const
+ void write(const pstring::code_t c) const
{
- pstring t = pstring("") + c;
- write(t);
+ write(pstring(c));
}
private:
- postream *m_strm;
+ postream &m_strm;
};
class putf8_fmt_writer : public pfmt_writer_t<putf8_fmt_writer>, public putf8_writer
{
public:
- explicit putf8_fmt_writer(postream *strm)
- : pfmt_writer_t()
- , putf8_writer(strm)
- {
- }
-
- COPYASSIGNMOVE(putf8_fmt_writer, delete)
-
- ~putf8_fmt_writer() override = default;
+ explicit putf8_fmt_writer(postream &strm);
+ virtual ~putf8_fmt_writer() override;
//protected:
void vdowrite(const pstring &ls) const;
@@ -563,29 +377,22 @@ private:
// pbinary_writer_t: writer on top of ostream
// -----------------------------------------------------------------------------
-class pbinary_writer
+class pbinary_writer : plib::nocopyassignmove
{
public:
explicit pbinary_writer(postream &strm) : m_strm(strm) {}
- pbinary_writer(pbinary_writer &&src) noexcept : m_strm(src.m_strm) {}
-
- COPYASSIGN(pbinary_writer, delete)
- postringstream &operator=(pbinary_writer &&src) = delete;
-
- virtual ~pbinary_writer() = default;
+ virtual ~pbinary_writer() {}
template <typename T>
- void write(const T &val)
+ void write(const T val)
{
- m_strm.write(reinterpret_cast<const postream::value_type *>(&val), sizeof(T));
+ m_strm.write(&val, sizeof(T));
}
void write(const pstring &s)
{
- const auto sm = reinterpret_cast<const postream::value_type *>(s.c_str());
- const std::size_t sl = std::strlen(s.c_str());
- write(sl);
- m_strm.write(sm, sl);
+ write(s.mem_t_size());
+ m_strm.write(s.c_str(), s.mem_t_size());
}
template <typename T>
@@ -593,38 +400,34 @@ public:
{
std::size_t sz = val.size();
write(sz);
- m_strm.write(reinterpret_cast<const postream::value_type *>(val.data()), sizeof(T) * sz);
+ m_strm.write(val.data(), sizeof(T) * sz);
}
private:
postream &m_strm;
};
-class pbinary_reader
+class pbinary_reader : plib::nocopyassignmove
{
public:
explicit pbinary_reader(pistream &strm) : m_strm(strm) {}
- pbinary_reader(pbinary_reader &&src) noexcept : m_strm(src.m_strm) { }
-
- COPYASSIGN(pbinary_reader, delete)
- pbinary_reader &operator=(pbinary_reader &&src) = delete;
-
- virtual ~pbinary_reader() = default;
+ virtual ~pbinary_reader() {}
template <typename T>
void read(T &val)
{
- m_strm.read(reinterpret_cast<pistream::value_type *>(&val), sizeof(T));
+ m_strm.read(&val, sizeof(T));
}
void read( pstring &s)
{
std::size_t sz = 0;
read(sz);
- std::vector<plib::string_info<pstring>::mem_t> buf(sz+1);
- m_strm.read(buf.data(), sz);
+ pstring::mem_t *buf = new pstring::mem_t[sz+1];
+ m_strm.read(buf, sz);
buf[sz] = 0;
- s = pstring(buf.data());
+ s = pstring(buf, pstring::UTF8);
+ delete [] buf;
}
template <typename T>
@@ -633,38 +436,13 @@ public:
std::size_t sz = 0;
read(sz);
val.resize(sz);
- m_strm.read(reinterpret_cast<pistream::value_type *>(val.data()), sizeof(T) * sz);
+ m_strm.read(val.data(), sizeof(T) * sz);
}
private:
pistream &m_strm;
};
-inline void copystream(postream &dest, pistream &src)
-{
- std::array<postream::value_type, 1024> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
- pstream::pos_type r;
- while ((r=src.read(buf.data(), 1024)) > 0)
- dest.write(buf.data(), r);
}
-struct perrlogger
-{
- template <typename ... Args>
- explicit perrlogger(Args&& ... args)
- {
- h()(std::forward<Args>(args)...);
- }
-private:
- static putf8_fmt_writer &h()
- {
- static plib::pstderr perr_strm;
- static plib::putf8_fmt_writer perr(&perr_strm);
- return perr;
- }
-};
-
-
-} // namespace plib
-
#endif /* PSTREAM_H_ */
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index c304f11d1fd..47d35d7c82f 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -10,8 +10,17 @@
#include "plists.h"
#include <algorithm>
-#include <atomic>
#include <stack>
+#include <atomic>
+
+template <typename T>
+std::size_t strlen_mem(const T *s)
+{
+ std::size_t len(0);
+ while (*s++)
+ ++len;
+ return len;
+}
template<typename F>
int pstring_t<F>::compare(const pstring_t &right) const
@@ -58,6 +67,18 @@ pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const
}
template<typename F>
+pstring_t<F> pstring_t<F>::ucase() const
+{
+ pstring_t ret;
+ for (const auto &c : *this)
+ if (c >= 'a' && c <= 'z')
+ ret += (c - 'a' + 'A');
+ else
+ ret += c;
+ return ret;
+}
+
+template<typename F>
typename pstring_t<F>::size_type pstring_t<F>::find_first_not_of(const pstring_t &no) const
{
size_type pos = 0;
@@ -129,6 +150,114 @@ typename pstring_t<F>::size_type pstring_t<F>::find(code_t search, size_type sta
return find(ss, start);
}
+
+template<typename F>
+pstring_t<F> pstring_t<F>::replace_all(const pstring_t &search, const pstring_t &replace) const
+{
+ pstring_t ret;
+ const size_type slen = search.length();
+
+ size_type last_s = 0;
+ size_type s = find(search, last_s);
+ while (s != npos)
+ {
+ ret += substr(last_s, s - last_s);
+ ret += replace;
+ last_s = s + slen;
+ s = find(search, last_s);
+ }
+ ret += substr(last_s);
+ return ret;
+}
+
+template<typename F>
+pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const size_type cnt) const
+{
+ // FIXME: pstringbuffer ret(*this);
+
+ pstring_t ret(*this);
+ size_type wsl = ws.length();
+ for (auto i = ret.length(); i < cnt; i+=wsl)
+ ret += ws;
+ return ret;
+}
+
+static double pstod(const pstring_t<pu8_traits> &str, std::size_t *e)
+{
+ return std::stod(str.cpp_string(), e);
+}
+
+static double pstod(const pstring &str, std::size_t *e)
+{
+ return std::stod(str.cpp_string(), e);
+}
+
+static double pstod(const pwstring &str, std::size_t *e)
+{
+ return std::stod(str.cpp_string(), e);
+}
+
+static double pstod(const pu16string &str, std::size_t *e)
+{
+ pstring c;
+ c = str;
+ return std::stod(c.cpp_string(), e);
+}
+
+static long pstol(const pstring_t<pu8_traits> &str, std::size_t *e, int base = 10)
+{
+ return std::stol(str.cpp_string(), e, base);
+}
+
+static long pstol(const pstring &str, std::size_t *e, int base = 10)
+{
+ return std::stol(str.cpp_string(), e, base);
+}
+
+static long pstol(const pwstring &str, std::size_t *e, int base = 10)
+{
+ return std::stol(str.cpp_string(), e, base);
+}
+
+static long pstol(const pu16string &str, std::size_t *e, int base = 10)
+{
+ pstring c;
+ c = str;
+ return std::stol(c.cpp_string(), e, base);
+}
+
+template<typename F>
+double pstring_t<F>::as_double(bool *error) const
+{
+ std::size_t e = 0;
+ if (error != nullptr)
+ *error = false;
+ double ret = pstod(*this, &e);
+ if (e != mem_t_size())
+ if (error != nullptr)
+ *error = true;
+ return ret;
+}
+
+template<typename F>
+long pstring_t<F>::as_long(bool *error) const
+{
+ static pstring_t prefix(pstring("0x"));
+ long ret;
+ std::size_t e = 0;
+
+ if (error != nullptr)
+ *error = false;
+ if (startsWith(prefix))
+ ret = pstol(substr(2), &e, 16);
+ else
+ ret = pstol(*this, &e, 10);
+ if (e != mem_t_size())
+ if (error != nullptr)
+ *error = true;
+ return ret;
+}
+
// ----------------------------------------------------------------------------------------
// template stuff ...
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index c4caeab8e8f..cabce0e7b93 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -7,50 +7,45 @@
#ifndef PSTRING_H_
#define PSTRING_H_
-#include "ptypes.h"
-
-#include <cstring>
-#include <exception>
#include <iterator>
-#include <limits>
-#include <stdexcept>
+#include <exception>
#include <string>
-#include <type_traits>
// ----------------------------------------------------------------------------------------
// pstring: semi-immutable strings ...
//
// The only reason this class exists is the absence of support for multi-byte
-// strings in std:: which I would consider sub-optimal for the use-cases I encounter.
+// strings in std:: which I would consider usuable for the use-cases I encounter.
// ----------------------------------------------------------------------------------------
-// enable this to use std::string instead of pstring globally.
-
-#define PSTRING_USE_STD_STRING (0)
-
template <typename T>
class pstring_const_iterator final
{
public:
- using value_type = typename T::ref_value_type;
+ typedef typename T::ref_value_type value_type;
- using pointer = value_type const *;
- using reference = value_type const &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- using string_type = typename T::string_type;
- using traits_type = typename T::traits_type;
+ typedef value_type const *pointer;
+ typedef value_type const &reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef typename T::string_type string_type;
+ typedef typename T::traits_type traits_type;
- constexpr pstring_const_iterator() noexcept : p() { }
+ pstring_const_iterator() noexcept : p() { }
explicit constexpr pstring_const_iterator(const typename string_type::const_iterator &x) noexcept : p(x) { }
+#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (0 == _ITERATOR_DEBUG_LEVEL) // debug iterators are broken
+ pstring_const_iterator(const pstring_const_iterator &rhs) noexcept = default;
+ pstring_const_iterator(pstring_const_iterator &&rhs) noexcept = default;
+ pstring_const_iterator &operator=(const pstring_const_iterator &rhs) noexcept = default;
+ pstring_const_iterator &operator=(pstring_const_iterator &&rhs) noexcept = default;
+#endif
pstring_const_iterator& operator++() noexcept { p += static_cast<difference_type>(traits_type::codelen(&(*p))); return *this; }
- // NOLINTNEXTLINE(cert-dcl21-cpp)
- pstring_const_iterator operator++(int) & noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; }
+ pstring_const_iterator operator++(int) noexcept { pstring_const_iterator tmp(*this); operator++(); return tmp; }
- constexpr bool operator==(const pstring_const_iterator& rhs) const noexcept { return p == rhs.p; }
- constexpr bool operator!=(const pstring_const_iterator& rhs) const noexcept { return p != rhs.p; }
+ bool operator==(const pstring_const_iterator& rhs) const noexcept { return p == rhs.p; }
+ bool operator!=(const pstring_const_iterator& rhs) const noexcept { return p != rhs.p; }
reference operator*() const noexcept { return *reinterpret_cast<pointer>(&(*p)); }
pointer operator->() const noexcept { return reinterpret_cast<pointer>(&(*p)); }
@@ -65,21 +60,18 @@ template <typename F>
struct pstring_t
{
public:
- using traits_type = F;
+ typedef F traits_type;
- using mem_t = typename traits_type::mem_t;
- using code_t = typename traits_type::code_t;
- using value_type = typename traits_type::code_t;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using string_type = typename traits_type::string_type;
+ typedef typename traits_type::mem_t mem_t;
+ typedef typename traits_type::code_t code_t;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef typename traits_type::string_type string_type;
- // FIXME: this is ugly
- struct ref_value_type final
+ class ref_value_type final
{
public:
ref_value_type() = delete;
- ~ref_value_type() = delete;
ref_value_type(const ref_value_type &) = delete;
ref_value_type(ref_value_type &&) = delete;
ref_value_type &operator=(const ref_value_type &) = delete;
@@ -88,27 +80,37 @@ public:
private:
const mem_t m;
};
- using const_reference = const ref_value_type &;
- using reference = const_reference;
+ typedef const ref_value_type& const_reference;
+ typedef const_reference reference;
+
+ enum enc_t
+ {
+ UTF8,
+ UTF16
+ };
// simple construction/destruction
- pstring_t() = default;
- ~pstring_t() noexcept = default;
+ pstring_t()
+ {
+ }
+ ~pstring_t()
+ {
+ }
// FIXME: Do something with encoding
- pstring_t(const mem_t *string)
+ pstring_t(const mem_t *string, const enc_t enc)
: m_str(string)
{
}
- pstring_t(const mem_t *string, const size_type len)
+ pstring_t(const mem_t *string, const size_type len, const enc_t enc)
: m_str(string, len)
{
}
template<typename C, std::size_t N,
class = typename std::enable_if<std::is_same<C, const mem_t>::value>::type>
- pstring_t(C (&string)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
+ pstring_t(C (&string)[N])
{
static_assert(N > 0,"pstring from array of length 0");
if (string[N-1] != 0)
@@ -116,15 +118,17 @@ public:
m_str.assign(string, N - 1);
}
+ pstring_t(const pstring_t &string)
+ : m_str(string.m_str)
+ { }
- explicit pstring_t(const string_type &string)
+ explicit pstring_t(const string_type &string, const enc_t enc)
: m_str(string)
{ }
- pstring_t(const pstring_t &string) = default;
- pstring_t(pstring_t &&string) noexcept = default;
- pstring_t &operator=(const pstring_t &string) = default;
- pstring_t &operator=(pstring_t &&string) noexcept = default;
+ pstring_t(pstring_t &&string)
+ : m_str(string.m_str)
+ { }
explicit pstring_t(code_t code)
{
@@ -140,8 +144,7 @@ public:
*this += static_cast<code_t>(c); // FIXME: codepage conversion for u8
}
- operator string_type () const { return m_str; }
-
+ pstring_t &operator=(const pstring_t &string) { m_str = string.m_str; return *this; }
template <typename T,
class = typename std::enable_if<!std::is_same<T, pstring_t::traits_type>::value>::type>
@@ -154,8 +157,8 @@ public:
}
// no non-const const_iterator for now
- using iterator = pstring_const_iterator<pstring_t<F> >;
- using const_iterator = pstring_const_iterator<pstring_t<F> >;
+ typedef pstring_const_iterator<pstring_t> iterator;
+ typedef pstring_const_iterator<pstring_t> const_iterator;
iterator begin() { return iterator(m_str.begin()); }
iterator end() { return iterator(m_str.end()); }
@@ -198,26 +201,67 @@ public:
const_reference at(const size_type pos) const { return *reinterpret_cast<const ref_value_type *>(F::nthcode(m_str.c_str(),pos)); }
+ /* The following is not compatible to std::string */
+
+ bool equals(const pstring_t &string) const { return (compare(string) == 0); }
+
+ bool startsWith(const pstring_t &arg) const { return arg.mem_t_size() > mem_t_size() ? false : m_str.compare(0, arg.mem_t_size(), arg.m_str) == 0; }
+ bool endsWith(const pstring_t &arg) const { return arg.mem_t_size() > mem_t_size() ? false : m_str.compare(mem_t_size()-arg.mem_t_size(), arg.mem_t_size(), arg.m_str) == 0; }
+
+ pstring_t replace_all(const pstring_t &search, const pstring_t &replace) const;
+ pstring_t cat(const pstring_t &s) const { return *this + s; }
+ pstring_t cat(code_t c) const { return *this + c; }
+
+ // conversions
+
+ double as_double(bool *error = nullptr) const;
+ long as_long(bool *error = nullptr) const;
+
/* the following are extensions to <string> */
size_type mem_t_size() const { return m_str.size(); }
+ pstring_t left(size_type len) const { return substr(0, len); }
+ pstring_t right(size_type nlen) const
+ {
+ return nlen >= length() ? *this : substr(length() - nlen, nlen);
+ }
+
+ pstring_t ltrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
+ {
+ return substr(find_first_not_of(ws));
+ }
+
+ pstring_t rtrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
+ {
+ auto f = find_last_not_of(ws);
+ return f == npos ? pstring_t() : substr(0, f + 1);
+ }
+
+ pstring_t trim(const pstring_t &ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
+
+ pstring_t rpad(const pstring_t &ws, const size_type cnt) const;
+
+ pstring_t ucase() const;
+
const string_type &cpp_string() const { return m_str; }
- static constexpr const size_type npos = static_cast<size_type>(-1);
+ static const size_type npos = static_cast<size_type>(-1);
-private:
+protected:
string_type m_str;
+
+private:
};
struct pu8_traits
{
- using mem_t = char;
- using code_t = char;
- using string_type = std::string;
+ typedef char mem_t;
+ typedef char code_t;
+ typedef std::string string_type;
static std::size_t len(const string_type &p) { return p.size(); }
- static std::size_t codelen(const mem_t *p) { plib::unused_var(p); return 1; }
- static std::size_t codelen(const code_t c) { plib::unused_var(c); return 1; }
+ static std::size_t codelen(const mem_t *p) { return 1; }
+ static std::size_t codelen(const code_t c) { return 1; }
static code_t code(const mem_t *p) { return *p; }
static void encode(const code_t c, string_type &s) { s += static_cast<mem_t>(c); }
static const mem_t *nthcode(const mem_t *p, const std::size_t n) { return &(p[n]); }
@@ -226,9 +270,9 @@ struct pu8_traits
/* No checking, this may deliver invalid codes */
struct putf8_traits
{
- using mem_t = char;
- using code_t = char32_t;
- using string_type = std::string;
+ typedef char mem_t;
+ typedef char32_t code_t;
+ typedef std::string string_type;
static std::size_t len(const string_type &p)
{
std::size_t ret = 0;
@@ -241,7 +285,7 @@ struct putf8_traits
}
static std::size_t codelen(const mem_t *p)
{
- const auto p1 = reinterpret_cast<const unsigned char *>(p);
+ const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p);
if ((*p1 & 0x80) == 0x00)
return 1;
else if ((*p1 & 0xE0) == 0xC0)
@@ -268,7 +312,7 @@ struct putf8_traits
}
static code_t code(const mem_t *p)
{
- const auto p1 = reinterpret_cast<const unsigned char *>(p);
+ const unsigned char *p1 = reinterpret_cast<const unsigned char *>(p);
if ((*p1 & 0x80) == 0x00)
return *p1;
else if ((*p1 & 0xE0) == 0xC0)
@@ -317,9 +361,9 @@ struct putf8_traits
struct putf16_traits
{
- using mem_t = char16_t;
- using code_t = char32_t;
- using string_type = std::u16string;
+ typedef char16_t mem_t;
+ typedef char32_t code_t;
+ typedef std::u16string string_type;
static std::size_t len(const string_type &p)
{
std::size_t ret = 0;
@@ -327,7 +371,7 @@ struct putf16_traits
while (i != p.end())
{
// FIXME: check that size is equal
- auto c = static_cast<uint16_t>(*i++);
+ uint16_t c = static_cast<uint16_t>(*i++);
if (!((c & 0xd800) == 0xd800))
ret++;
}
@@ -335,7 +379,7 @@ struct putf16_traits
}
static std::size_t codelen(const mem_t *p)
{
- auto c = static_cast<uint16_t>(*p);
+ uint16_t c = static_cast<uint16_t>(*p);
return ((c & 0xd800) == 0xd800) ? 2 : 1;
}
static std::size_t codelen(const code_t c)
@@ -347,7 +391,7 @@ struct putf16_traits
}
static code_t code(const mem_t *p)
{
- auto c = static_cast<uint32_t>(*p++);
+ uint32_t c = static_cast<uint32_t>(*p++);
if ((c & 0xd800) == 0xd800)
{
c = (c - 0xd800) << 10;
@@ -357,7 +401,7 @@ struct putf16_traits
}
static void encode(code_t c, string_type &s)
{
- auto cu = static_cast<uint32_t>(c);
+ uint32_t cu = static_cast<uint32_t>(c);
if (c > 0xffff)
{ //make a surrogate pair
uint32_t t = ((cu - 0x10000) >> 10) + 0xd800;
@@ -381,9 +425,9 @@ struct putf16_traits
struct pwchar_traits
{
- using mem_t = wchar_t;
- using code_t = char32_t;
- using string_type = std::wstring;
+ typedef wchar_t mem_t;
+ typedef char32_t code_t;
+ typedef std::wstring string_type;
static std::size_t len(const string_type &p)
{
if (sizeof(wchar_t) == 2)
@@ -393,7 +437,7 @@ struct pwchar_traits
while (i != p.end())
{
// FIXME: check that size is equal
- auto c = static_cast<uint32_t>(*i++);
+ uint32_t c = static_cast<uint32_t>(*i++);
if (!((c & 0xd800) == 0xd800))
ret++;
}
@@ -407,7 +451,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- auto c = static_cast<uint16_t>(*p);
+ uint16_t c = static_cast<uint16_t>(*p);
return ((c & 0xd800) == 0xd800) ? 2 : 1;
}
else
@@ -426,7 +470,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- auto c = static_cast<uint32_t>(*p++);
+ uint32_t c = static_cast<uint32_t>(*p++);
if ((c & 0xd800) == 0xd800)
{
c = (c - 0xd800) << 10;
@@ -442,7 +486,7 @@ struct pwchar_traits
{
if (sizeof(wchar_t) == 2)
{
- auto cu = static_cast<uint32_t>(c);
+ uint32_t cu = static_cast<uint32_t>(c);
if (c > 0xffff)
{ //make a surrogate pair
uint32_t t = ((cu - 0x10000) >> 10) + 0xd800;
@@ -475,280 +519,41 @@ extern template struct pstring_t<putf8_traits>;
extern template struct pstring_t<putf16_traits>;
extern template struct pstring_t<pwchar_traits>;
-#if (PSTRING_USE_STD_STRING)
-typedef std::string pstring;
-#else
-using pstring = pstring_t<putf8_traits>;
-#endif
-using putf8string = pstring_t<putf8_traits>;
-using pu16string = pstring_t<putf16_traits>;
-using pwstring = pstring_t<pwchar_traits>;
+typedef pstring_t<putf8_traits> pstring;
+typedef pstring_t<putf16_traits> pu16string;
+typedef pstring_t<pwchar_traits> pwstring;
namespace plib
{
- template<class T>
- struct string_info
- {
- using mem_t = typename T::mem_t;
- };
-
- template<>
- struct string_info<std::string>
- {
- using mem_t = char;
- };
-
template<typename T>
pstring to_string(const T &v)
{
- return pstring(std::to_string(v));
+ return pstring(std::to_string(v), pstring::UTF8);
}
template<typename T>
pwstring to_wstring(const T &v)
{
- return pwstring(std::to_wstring(v));
- }
-
- template <typename T, typename E = void>
- struct pstonum_helper;
-
- template<typename T>
- struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
- && std::is_signed<T>::value>::type>
- {
- template <typename S>
- long long operator()(const S &arg, std::size_t *idx)
- {
- return std::stoll(arg, idx);
- }
- };
-
- template<typename T>
- struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
- && !std::is_signed<T>::value>::type>
- {
- template <typename S>
- unsigned long long operator()(const S &arg, std::size_t *idx)
- {
- return std::stoull(arg, idx);
- }
- };
-
- template<typename T>
- struct pstonum_helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
- {
- template <typename S>
- long double operator()(const S &arg, std::size_t *idx)
- {
- return std::stold(arg, idx);
- }
- };
-
- template<typename T, typename S>
- T pstonum(const S &arg)
- {
- decltype(arg.c_str()) cstr = arg.c_str();
- std::size_t idx(0);
- auto ret = pstonum_helper<T>()(cstr, &idx);
- using ret_type = decltype(ret);
- if (ret >= static_cast<ret_type>(std::numeric_limits<T>::lowest())
- && ret <= static_cast<ret_type>(std::numeric_limits<T>::max()))
- //&& (ret == T(0) || std::abs(ret) >= std::numeric_limits<T>::min() ))
- {
- if (cstr[idx] != 0)
- throw std::invalid_argument(std::string("Continuation after numeric value ends: ") + cstr);
- }
- else
- {
- throw std::out_of_range(std::string("Out of range: ") + cstr);
- }
- return static_cast<T>(ret);
- }
-
- template<typename R, typename T>
- R pstonum_ne(const T &str, bool &err) noexcept
- {
- try
- {
- err = false;
- return pstonum<R>(str);
- }
- catch (...)
- {
- err = true;
- return R(0);
- }
- }
-
- template<typename T>
- typename T::size_type find_first_not_of(const T &str, const T &no)
- {
- typename T::size_type pos = 0;
- for (auto it = str.begin(); it != str.end(); ++it, ++pos)
- {
- bool f = true;
- for (typename T::value_type const jt : no)
- {
- if (*it == jt)
- {
- f = false;
- break;
- }
- }
- if (f)
- return pos;
- }
- return T::npos;
- }
-
- template<typename T>
- typename T::size_type find_last_not_of(const T &str, const T &no)
- {
- /* FIXME: reverse iterator */
- typename T::size_type last_found = T::npos;
- typename T::size_type pos = 0;
- for (auto it = str.begin(); it != str.end(); ++it, ++pos)
- {
- bool f = true;
- for (typename T::value_type const jt : no)
- {
- if (*it == jt)
- {
- f = false;
- break;
- }
- }
- if (f)
- last_found = pos;
- }
- return last_found;
- }
-
- template<typename T>
- T ltrim(const T &str, const T &ws = T(" \t\n\r"))
- {
- auto f = find_first_not_of(str, ws);
- return (f == T::npos) ? T() : str.substr(f);
+ return pwstring(std::to_wstring(v), pwstring::UTF16);
}
-
- template<typename T>
- T rtrim(const T &str, const T &ws = T(" \t\n\r"))
- {
- auto f = find_last_not_of(str, ws);
- return (f == T::npos) ? T() : str.substr(0, f + 1);
- }
-
- template<typename T>
- T trim(const T &str, const T &ws = T(" \t\n\r"))
- {
- return rtrim(ltrim(str, ws), ws);
- }
-
- template<typename T>
- T left(const T &str, typename T::size_type len)
- {
- return str.substr(0, len);
- }
-
- template<typename T>
- T right(const T &str, typename T::size_type nlen)
- {
- return nlen >= str.length() ? str : str.substr(str.length() - nlen, nlen);
- }
-
- template<typename T>
- bool startsWith(const T &str, const T &arg)
- {
- return (arg == left(str, arg.length()));
- }
-
- template<typename T>
- bool endsWith(const T &str, const T &arg)
- {
- return (right(str, arg.length()) == arg);
- }
-
- template<typename T>
- bool startsWith(const T &str, const char *arg)
- {
- return (left(str, std::strlen(arg)) == arg);
- }
-
- template<typename T>
- bool endsWith(const T &str, const char *arg)
- {
- return (right(str, std::strlen(arg)) == arg);
- }
-
- template<typename T>
- T ucase(const T &str)
- {
- T ret;
- for (const auto &c : str)
- if (c >= 'a' && c <= 'z')
- ret += (c - 'a' + 'A');
- else
- ret += c;
- return ret;
- }
-
- template<typename T>
- T rpad(const T &str, const T &ws, const typename T::size_type cnt)
- {
- // FIXME: pstringbuffer ret(*this);
-
- T ret(str);
- typename T::size_type wsl = ws.length();
- for (auto i = ret.length(); i < cnt; i+=wsl)
- ret += ws;
- return ret;
- }
-
- template<typename T>
- T replace_all(const T &str, const T &search, const T &replace)
- {
- T ret;
- const typename T::size_type slen = search.length();
-
- typename T::size_type last_s = 0;
- typename T::size_type s = str.find(search, last_s);
- while (s != T::npos)
- {
- ret += str.substr(last_s, s - last_s);
- ret += replace;
- last_s = s + slen;
- s = str.find(search, last_s);
- }
- ret += str.substr(last_s);
- return ret;
- }
-
- template<typename T, typename T1, typename T2>
- T replace_all(const T &str, const T1 &search, const T2 &replace)
- {
- return replace_all(str, static_cast<T>(search), static_cast<T>(replace));
- }
-
-} // namespace plib
+}
// custom specialization of std::hash can be injected in namespace std
namespace std
{
-
template<typename T> struct hash<pstring_t<T>>
{
- using argument_type = pstring_t<T>;
- using result_type = std::size_t;
+ typedef pstring_t<T> argument_type;
+ typedef std::size_t result_type;
result_type operator()(argument_type const& s) const
{
- const typename argument_type::mem_t *string = s.c_str();
+ const pstring::mem_t *string = s.c_str();
result_type result = 5381;
- for (typename argument_type::mem_t c = *string; c != 0; c = *string++)
+ for (pstring::mem_t c = *string; c != 0; c = *string++)
result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ static_cast<result_type>(c);
return result;
}
};
-} // namespace std
+}
#endif /* PSTRING_H_ */
diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h
deleted file mode 100644
index 32ccc4f7b0d..00000000000
--- a/src/lib/netlist/plib/ptime.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * ptime.h
- */
-
-#ifndef PTIME_H_
-#define PTIME_H_
-
-#include "pconfig.h"
-#include "ptypes.h"
-
-#include <cstdint>
-
-// ----------------------------------------------------------------------------------------
-// netlist_time
-// ----------------------------------------------------------------------------------------
-
-namespace plib
-{
-
- template <typename TYPE, TYPE RES>
- struct ptime final
- {
- public:
-
- using internal_type = TYPE;
- using mult_type = TYPE;
-
- constexpr ptime() noexcept : m_time(0) {}
-
- ~ptime() noexcept = default;
-
- constexpr ptime(const ptime &rhs) noexcept = default;
- constexpr ptime(ptime &&rhs) noexcept = default;
- constexpr explicit ptime(const internal_type &time) noexcept : m_time(time) {}
- constexpr explicit ptime(internal_type &&time) noexcept : m_time(time) {}
- C14CONSTEXPR ptime &operator=(const ptime &rhs) noexcept = default;
- C14CONSTEXPR ptime &operator=(ptime &&rhs) noexcept = default;
-
- constexpr explicit ptime(const double t) = delete;
- //: m_time((internal_type) ( t * (double) resolution)) { }
- constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept
- : m_time(nom * (RES / den)) { }
-
- C14CONSTEXPR ptime &operator+=(const ptime rhs) noexcept { m_time += rhs.m_time; return *this; }
- C14CONSTEXPR ptime &operator-=(const ptime rhs) noexcept { m_time -= rhs.m_time; return *this; }
- C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast<internal_type>(factor); return *this; }
-
- friend constexpr const ptime operator-(ptime lhs, const ptime rhs) noexcept
- {
- return ptime(lhs.m_time - rhs.m_time);
- }
-
- friend constexpr const ptime operator+(ptime lhs, const ptime rhs) noexcept
- {
- return ptime(lhs.m_time + rhs.m_time);
- }
-
- friend constexpr const ptime operator*(ptime lhs, const mult_type &factor) noexcept
- {
- return ptime(lhs.m_time * factor);
- }
-
- friend constexpr mult_type operator/(const ptime lhs, const ptime rhs) noexcept
- {
- return static_cast<mult_type>(lhs.m_time / rhs.m_time);
- }
-
- friend constexpr bool operator<(const ptime lhs, const ptime rhs) noexcept
- {
- return (lhs.m_time < rhs.m_time);
- }
-
- friend constexpr bool operator>(const ptime lhs, const ptime rhs) noexcept
- {
- return (rhs < lhs);
- }
-
- friend constexpr bool operator<=(const ptime lhs, const ptime rhs) noexcept
- {
- return !(lhs > rhs);
- }
-
- friend constexpr bool operator>=(const ptime lhs, const ptime rhs) noexcept
- {
- return !(lhs < rhs);
- }
-
- friend constexpr bool operator==(const ptime lhs, const ptime rhs) noexcept
- {
- return lhs.m_time == rhs.m_time;
- }
-
- friend constexpr bool operator!=(const ptime lhs, const ptime rhs) noexcept
- {
- return !(lhs == rhs);
- }
-
- constexpr internal_type as_raw() const noexcept { return m_time; }
- constexpr double as_double() const noexcept
- {
- return static_cast<double>(m_time) * inv_res;
- }
-
- // for save states ....
- C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; }
-
- static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
- static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C( 1000000)); }
- static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C( 1000)); }
- static constexpr ptime from_sec(const internal_type s) noexcept { return ptime(s, UINT64_C( 1)); }
- static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); }
- static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
- static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(RES)), RES); }
-
- static constexpr ptime zero() noexcept { return ptime(0, RES); }
- static constexpr ptime quantum() noexcept { return ptime(1, RES); }
- static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), RES); }
- static constexpr internal_type resolution() noexcept { return RES; }
-
- constexpr internal_type in_nsec() const noexcept { return m_time / (RES / UINT64_C(1000000000)); }
- constexpr internal_type in_usec() const noexcept { return m_time / (RES / UINT64_C( 1000000)); }
- constexpr internal_type in_msec() const noexcept { return m_time / (RES / UINT64_C( 1000)); }
- constexpr internal_type in_sec() const noexcept { return m_time / (RES / UINT64_C( 1)); }
-
- private:
- static constexpr const double inv_res = 1.0 / static_cast<double>(RES);
- internal_type m_time;
- };
-
-
-} // namespace plib
-
-
-#endif /* PTIME_H_ */
diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h
index bda62099150..0934a86fdf2 100644
--- a/src/lib/netlist/plib/ptypes.h
+++ b/src/lib/netlist/plib/ptypes.h
@@ -9,20 +9,10 @@
#define PTYPES_H_
#include "pconfig.h"
+#include "pstring.h"
-#include <limits>
-#include <string>
#include <type_traits>
-
-#define COPYASSIGNMOVE(name, def) \
- name(const name &) = def; \
- name(name &&) noexcept = def; \
- name &operator=(const name &) = def; \
- name &operator=(name &&) noexcept = def;
-
-#define COPYASSIGN(name, def) \
- name(const name &) = def; \
- name &operator=(const name &) = def; \
+#include <limits>
namespace plib
{
@@ -35,14 +25,14 @@ namespace plib
template<> struct is_integral<INT128> { static constexpr bool value = true; };
template<> struct numeric_limits<UINT128>
{
- static constexpr UINT128 max()
+ static inline constexpr UINT128 max()
{
return ~((UINT128)0);
}
};
template<> struct numeric_limits<INT128>
{
- static constexpr INT128 max()
+ static inline constexpr INT128 max()
{
return (~((UINT128)0)) >> 1;
}
@@ -55,98 +45,56 @@ namespace plib
struct nocopyassignmove
{
+ protected:
+ nocopyassignmove() = default;
+ ~nocopyassignmove() = default;
+ private:
nocopyassignmove(const nocopyassignmove &) = delete;
nocopyassignmove(nocopyassignmove &&) = delete;
nocopyassignmove &operator=(const nocopyassignmove &) = delete;
nocopyassignmove &operator=(nocopyassignmove &&) = delete;
- protected:
- nocopyassignmove() = default;
- ~nocopyassignmove() = default;
};
struct nocopyassign
{
- nocopyassign(const nocopyassign &) = delete;
- nocopyassign &operator=(const nocopyassign &) = delete;
protected:
nocopyassign() = default;
~nocopyassign() = default;
- nocopyassign(nocopyassign &&) = default;
- nocopyassign &operator=(nocopyassign &&) = default;
+ private:
+ nocopyassign(const nocopyassign &) = delete;
+ nocopyassign &operator=(const nocopyassign &) = delete;
};
//============================================================
- // Avoid unused variable warnings
+ // penum - strongly typed enumeration
//============================================================
- template<typename... Ts>
- inline void unused_var(Ts&&...) {}
- //============================================================
- // is_pow2
- //============================================================
- template <typename T>
- constexpr bool is_pow2(T v) noexcept
+ struct penum_base
{
- static_assert(is_integral<T>::value, "is_pow2 needs integer arguments");
- return !(v & (v-1));
- }
-
-
- //============================================================
- // abs, lcd, gcm
- //============================================================
-
- template<typename T>
- constexpr
- typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
- abs(T v)
- {
- return v < 0 ? -v : v;
- }
-
- template<typename T>
- constexpr
- typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
- abs(T v)
- {
- return v;
- }
-
- template<typename M, typename N>
- constexpr typename std::common_type<M, N>::type
- gcd(M m, N n)
- {
- static_assert(std::is_integral<M>::value, "gcd: M must be an integer");
- static_assert(std::is_integral<N>::value, "gcd: N must be an integer");
-
- return m == 0 ? plib::abs(n)
- : n == 0 ? plib::abs(m)
- : gcd(n, m % n);
- }
-
- template<typename M, typename N>
- constexpr typename std::common_type<M, N>::type
- lcm(M m, N n)
- {
- static_assert(std::is_integral<M>::value, "lcm: M must be an integer");
- static_assert(std::is_integral<N>::value, "lcm: N must be an integer");
-
- return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0;
- }
-
-} // namespace plib
+ protected:
+ static int from_string_int(const char *str, const char *x);
+ static pstring nthstr(int n, const char *str);
+ };
-//============================================================
-// Define a "has member" trait.
-//============================================================
+}
+
+#define P_ENUM(ename, ...) \
+ struct ename : public plib::penum_base { \
+ enum E { __VA_ARGS__ }; \
+ ename (E v) : m_v(v) { } \
+ bool set_from_string (const pstring &s) { \
+ static char const *const strings = # __VA_ARGS__; \
+ int f = from_string_int(strings, s.c_str()); \
+ if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
+ } \
+ operator E() const {return m_v;} \
+ bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
+ bool operator==(const E &rhs) const {return m_v == rhs;} \
+ const pstring name() const { \
+ static char const *const strings = # __VA_ARGS__; \
+ return nthstr(static_cast<int>(m_v), strings); \
+ } \
+ private: E m_v; };
-#define PDEFINE_HAS_MEMBER(name, member) \
- template <typename T> class name \
- { \
- template <typename U> static long test(decltype(&U:: member)); \
- template <typename U> static char test(...); \
- public: \
- static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long); \
- }
#endif /* PTYPES_H_ */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index b62cbf60865..c34102417ec 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -2,13 +2,13 @@
// copyright-holders:Couriersud
#include "putil.h"
-#include "plists.h"
#include "ptypes.h"
+#include "plists.h"
-#include <algorithm>
#include <cstdlib>
-#include <cstring>
+#include <algorithm>
#include <initializer_list>
+#include <cstring>
namespace plib
{
@@ -17,7 +17,7 @@ namespace plib
const pstring buildpath(std::initializer_list<pstring> list )
{
pstring ret = "";
- for( const auto &elem : list )
+ for( auto elem : list )
{
if (ret == "")
ret = elem;
@@ -33,12 +33,12 @@ namespace plib
const pstring environment(const pstring &var, const pstring &default_val)
{
- if (std::getenv(var.c_str()) == nullptr)
+ if (getenv(var.c_str()) == nullptr)
return default_val;
else
- return pstring(std::getenv(var.c_str()));
+ return pstring(getenv(var.c_str()), pstring::UTF8);
}
- } // namespace util
+ }
std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty)
{
@@ -64,36 +64,6 @@ namespace plib
return ret;
}
- std::vector<std::string> psplit_r(const std::string &stri,
- const std::string &token,
- const std::size_t maxsplit)
- {
- std::string str(stri);
- std::vector<std::string> result;
- std::size_t splits = 0;
-
- while(str.size())
- {
- std::size_t index = str.rfind(token);
- bool found = index!=std::string::npos;
- if (found)
- splits++;
- if ((splits <= maxsplit || maxsplit == 0) && found)
- {
- result.push_back(str.substr(index+token.size()));
- str = str.substr(0, index);
- if (str.size()==0)
- result.push_back(str);
- }
- else
- {
- result.push_back(str);
- str = "";
- }
- }
- return result;
- }
-
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl)
{
pstring col = "";
@@ -102,7 +72,7 @@ namespace plib
auto i = str.begin();
while (i != str.end())
{
- auto p = static_cast<std::size_t>(-1);
+ std::size_t p = static_cast<std::size_t>(-1);
for (std::size_t j=0; j < onstrl.size(); j++)
{
if (std::equal(onstrl[j].begin(), onstrl[j].end(), i))
@@ -122,7 +92,7 @@ namespace plib
}
else
{
- pstring::value_type c = *i;
+ pstring::code_t c = *i;
col += c;
i++;
}
@@ -161,8 +131,31 @@ namespace plib
return cnt;
return -1;
}
- std::string penum_base::nthstr(int n, const char *str)
+ pstring penum_base::nthstr(int n, const char *str)
{
- return psplit(str, ",", false)[static_cast<std::size_t>(n)];
+ char buf[64];
+ char *bufp = buf;
+ int cur = 0;
+ while (*str)
+ {
+ if (cur == n)
+ {
+ if (*str == ',')
+ {
+ *bufp = 0;
+ return pstring(buf, pstring::UTF8);
+ }
+ else if (*str != ' ')
+ *bufp++ = *str;
+ }
+ else
+ {
+ if (*str == ',')
+ cur++;
+ }
+ str++;
+ }
+ *bufp = 0;
+ return pstring(buf, pstring::UTF8);
}
} // namespace plib
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index e8145361d9d..8d59c0357e2 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -5,32 +5,27 @@
*
*/
-#ifndef PUTIL_H_
-#define PUTIL_H_
+#ifndef P_UTIL_H_
+#define P_UTIL_H_
#include "pstring.h"
-#include <algorithm>
#include <initializer_list>
-#include <vector>
-
-#define PSTRINGIFY_HELP(y) # y
-#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)
-
+#include <algorithm>
+#include <vector> // <<= needed by windows build
namespace plib
{
-
namespace util
{
const pstring buildpath(std::initializer_list<pstring> list );
const pstring environment(const pstring &var, const pstring &default_val);
- } // namespace util
+ }
namespace container
{
- template <class C, class T>
- bool contains(C &con, const T &elem)
+ template <class C>
+ bool contains(C &con, const typename C::value_type &elem)
{
return std::find(con.begin(), con.end(), elem) != con.end();
}
@@ -56,51 +51,7 @@ namespace plib
{
con.erase(std::remove(con.begin(), con.end(), elem), con.end());
}
- } // namespace container
-
- /* May be further specialized .... This is the generic version */
- template <typename T>
- struct constants
- {
- static constexpr T zero() noexcept { return static_cast<T>(0); }
- static constexpr T one() noexcept { return static_cast<T>(1); }
- static constexpr T two() noexcept { return static_cast<T>(2); }
-
- /*!
- * \brief Electric constant of vacuum
- */
- static constexpr T eps_0() noexcept { return static_cast<T>(8.854187817e-12); }
- /*!
- * \brief Relative permittivity of Silicon dioxide
- */
- static constexpr T eps_SiO2() noexcept { return static_cast<T>(3.9); }
- /*!
- * \brief Relative permittivity of Silicon
- */
- static constexpr T eps_Si() noexcept { return static_cast<T>(11.7); }
- /*!
- * \brief Boltzmann constant
- */
- static constexpr T k_b() noexcept { return static_cast<T>(1.38064852e-23); }
- /*!
- * \brief room temperature (gives VT = 0.02585 at T=300)
- */
- static constexpr T T0() noexcept { return static_cast<T>(300); }
- /*!
- * \brief Elementary charge
- */
- static constexpr T Q_e() noexcept { return static_cast<T>(1.6021765314e-19); }
- /*!
- * \brief Intrinsic carrier concentration in 1/m^3 of Silicon
- */
- static constexpr T NiSi() noexcept { return static_cast<T>(1.45e16); }
-
- template <typename V>
- static constexpr const T cast(V &&v) noexcept { return static_cast<T>(v); }
- };
-
- static_assert(noexcept(constants<double>::one()) == true, "Not evaluated as constexpr");
-
+ }
template <class C>
struct indexed_compare
@@ -118,41 +69,7 @@ namespace plib
std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty = false);
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl);
- std::vector<std::string> psplit_r(const std::string &stri,
- const std::string &token,
- const std::size_t maxsplit);
-
-
- //============================================================
- // penum - strongly typed enumeration
- //============================================================
-
- struct penum_base
- {
- protected:
- static int from_string_int(const char *str, const char *x);
- static std::string nthstr(int n, const char *str);
- };
-
-} // namespace plib
-
-#define P_ENUM(ename, ...) \
- struct ename : public plib::penum_base { \
- enum E { __VA_ARGS__ }; \
- ename (E v) : m_v(v) { } \
- bool set_from_string (const std::string &s) { \
- static char const *const strings = # __VA_ARGS__; \
- int f = from_string_int(strings, s.c_str()); \
- if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
- } \
- operator E() const {return m_v;} \
- bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
- bool operator==(const E &rhs) const {return m_v == rhs;} \
- std::string name() const { \
- static char const *const strings = # __VA_ARGS__; \
- return nthstr(static_cast<int>(m_v), strings); \
- } \
- private: E m_v; };
+}
-#endif /* PUTIL_H_ */
+#endif /* P_UTIL_H_ */
diff --git a/src/lib/netlist/plib/vector_ops.h b/src/lib/netlist/plib/vector_ops.h
deleted file mode 100644
index 8043c48f61c..00000000000
--- a/src/lib/netlist/plib/vector_ops.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * vector_ops.h
- *
- * Base vector operations
- *
- */
-
-#ifndef PLIB_VECTOR_OPS_H_
-#define PLIB_VECTOR_OPS_H_
-
-#include "pconfig.h"
-
-#include <algorithm>
-#include <cmath>
-#include <type_traits>
-
-#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-#endif
-
-namespace plib
-{
- template<typename VT, typename T>
- void vec_set_scalar(const std::size_t n, VT &v, T && scalar)
- {
- const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
- for ( std::size_t i = 0; i < n; i++ )
- v[i] = s;
- }
-
- template<typename VT, typename VS>
- void vec_set(const std::size_t n, VT &v, const VS & source)
- {
- for ( std::size_t i = 0; i < n; i++ )
- v[i] = source[i];
- }
-
- template<typename T, typename V1, typename V2>
- T vec_mult(const std::size_t n, const V1 & v1, const V2 & v2 )
- {
- using b8 = T[8];
- PALIGNAS_VECTOROPT() b8 value = {0};
- for (std::size_t i = 0; i < n ; i++ )
- {
- value[i & 7] += v1[i] * v2[i];
- }
- return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
- }
-
- template<typename T, typename VT>
- T vec_mult2(const std::size_t n, const VT &v)
- {
- using b8 = T[8];
- PALIGNAS_VECTOROPT() b8 value = {0};
- for (std::size_t i = 0; i < n ; i++ )
- {
- value[i & 7] += v[i] * v[i];
- }
- return value[0] + value[1] + value[2] + value[3] + value[4] + value[5] + value[6] + value[7];
- }
-
- template<typename T, typename VT>
- T vec_sum(const std::size_t n, const VT &v)
- {
- if (n<8)
- {
- T value(0);
- for (std::size_t i = 0; i < n ; i++ )
- value += v[i];
-
- return value;
- }
- else
- {
- using b8 = T[8];
- PALIGNAS_VECTOROPT() b8 value = {0};
- for (std::size_t i = 0; i < n ; i++ )
- value[i & 7] += v[i];
-
- return ((value[0] + value[1]) + (value[2] + value[3])) + ((value[4] + value[5]) + (value[6] + value[7]));
- }
- }
-
- template<typename VV, typename T, typename VR>
- void vec_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
- {
- const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
- for ( std::size_t i = 0; i < n; i++ )
- result[i] = s * v[i];
- }
-
- template<typename VR, typename VV, typename T>
- void vec_add_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
- {
- const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
- for ( std::size_t i = 0; i < n; i++ )
- result[i] += s * v[i];
- }
-
- template<typename T>
- void vec_add_mult_scalar_p(const std::size_t n, T * result, const T * v, T scalar)
- {
- for ( std::size_t i = 0; i < n; i++ )
- result[i] += scalar * v[i];
- }
-
- template<typename R, typename V>
- void vec_add_ip(const std::size_t n, R & result, const V & v)
- {
- for ( std::size_t i = 0; i < n; i++ )
- result[i] += v[i];
- }
-
- template<typename VR, typename V1, typename V2>
- void vec_sub(const std::size_t n, VR & result, const V1 &v1, const V2 & v2)
- {
- for ( std::size_t i = 0; i < n; i++ )
- result[i] = v1[i] - v2[i];
- }
-
- template<typename V, typename T>
- void vec_scale(const std::size_t n, V & v, T &&scalar)
- {
- const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
- for ( std::size_t i = 0; i < n; i++ )
- v[i] *= s;
- }
-
- template<typename T, typename V>
- T vec_maxabs(const std::size_t n, const V & v)
- {
- T ret = 0.0;
- for ( std::size_t i = 0; i < n; i++ )
- ret = std::max(ret, std::abs(v[i]));
-
- return ret;
- }
-} // namespace plib
-
-#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-#if !(__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 3))
-#pragma GCC diagnostic pop
-#endif
-#endif
-
-#endif /* PLIB_VECTOR_OPS_H_ */
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 4a1c8ac0315..a1d53d6792d 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -9,23 +9,21 @@
****************************************************************************/
#include "netlist/plib/pmain.h"
-#include "netlist/devices/net_lib.h"
-#include "netlist/nl_parser.h"
#include "netlist/nl_setup.h"
-#include "netlist/solver/nld_solver.h"
+#include "netlist/nl_parser.h"
+#include "netlist/devices/net_lib.h"
#include "netlist/tools/nl_convert.h"
+#include "netlist/solver/nld_solver.h"
#include <cstring>
-#define NLTOOL_VERSION 20190202
-
class tool_app_t : public plib::app
{
public:
tool_app_t() :
plib::app(),
opt_grp1(*this, "General options", "The following options apply to all commands."),
- opt_cmd (*this, "c", "cmd", 0, std::vector<pstring>({"run","convert","listdevices","static","header","docheader"}), "run|convert|listdevices|static|header|docheader"),
+ opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static:header:docheader", "run|convert|listdevices|static|header"),
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
opt_rfolders(*this, "r", "rom", "where to look for data files"),
@@ -33,34 +31,25 @@ public:
opt_quiet(*this, "q", "quiet", "be quiet - no warnings"),
opt_version(*this, "", "version", "display version and exit"),
opt_help(*this, "h", "help", "display help and exit"),
-
opt_grp2(*this, "Options for run and static commands", "These options apply to run and static commands."),
opt_name(*this, "n", "name", "", "the netlist in file specified by ""-f"" option to run; default is first one"),
-
opt_grp3(*this, "Options for run command", "These options are only used by the run command."),
- opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)\n\n abc def\n\n xyz"),
+ opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)"),
opt_logs(*this, "l", "log" , "define terminal to log. This option may be specified repeatedly."),
opt_inp(*this, "i", "input", "", "input file to process (default is none)"),
opt_loadstate(*this,"", "loadstate", "", "load state from file and continue from there"),
opt_savestate(*this,"", "savestate", "", "save state to file at end of run"),
-
opt_grp4(*this, "Options for convert command", "These options are only used by the convert command."),
- opt_type(*this, "y", "type", 0, std::vector<pstring>({"spice","eagle","rinf"}), "type of file to be converted: spice,eagle,rinf"),
-
- opt_grp5(*this, "Options for header command", "These options are only used by the header command."),
- opt_tabwidth(*this, "", "tab-width", 4, "Tab width for output."),
- opt_linewidth(*this,"", "line-width", 72, "Line width for output."),
+ opt_type(*this, "y", "type", "spice", "spice:eagle:rinf", "type of file to be converted: spice,eagle,rinf"),
opt_ex1(*this, "nltool -c run -t 3.5 -f nl_examples/cdelay.c -n cap_delay",
"Run netlist \"cap_delay\" from file nl_examples/cdelay.c for 3.5 seconds"),
opt_ex2(*this, "nltool --cmd=listdevices",
- "List all known devices."),
- opt_ex3(*this, "nltool --cmd=header --tab-width=8 --line-width=80",
- "Create the header file needed for including netlists as code.")
+ "List all known devices.")
{}
plib::option_group opt_grp1;
- plib::option_str_limit<unsigned> opt_cmd;
+ plib::option_str_limit opt_cmd;
plib::option_str opt_file;
plib::option_vec opt_defines;
plib::option_vec opt_rfolders;
@@ -71,22 +60,18 @@ public:
plib::option_group opt_grp2;
plib::option_str opt_name;
plib::option_group opt_grp3;
- plib::option_num<double> opt_ttr;
+ plib::option_double opt_ttr;
plib::option_vec opt_logs;
plib::option_str opt_inp;
plib::option_str opt_loadstate;
plib::option_str opt_savestate;
plib::option_group opt_grp4;
- plib::option_str_limit<unsigned> opt_type;
- plib::option_group opt_grp5;
- plib::option_num<unsigned> opt_tabwidth;
- plib::option_num<unsigned> opt_linewidth;
+ plib::option_str_limit opt_type;
plib::option_example opt_ex1;
plib::option_example opt_ex2;
- plib::option_example opt_ex3;
- int execute() override;
- pstring usage() override;
+ int execute();
+ pstring usage();
private:
void run();
@@ -101,8 +86,6 @@ private:
void listdevices();
- std::vector<pstring> m_options;
-
};
static NETLIST_START(dummy)
@@ -120,62 +103,51 @@ NETLIST_END()
class netlist_data_folder_t : public netlist::source_t
{
public:
- netlist_data_folder_t(const pstring &folder)
- : netlist::source_t(netlist::source_t::DATA)
+ netlist_data_folder_t(netlist::setup_t &setup,
+ pstring folder)
+ : netlist::source_t(setup, netlist::source_t::DATA)
, m_folder(folder)
{
}
- plib::unique_ptr<plib::pistream> stream(const pstring &file) override;
+ virtual std::unique_ptr<plib::pistream> stream(const pstring &file) override;
private:
pstring m_folder;
};
-plib::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &file)
+std::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &file)
{
pstring name = m_folder + "/" + file;
try
{
- auto strm = plib::make_unique<plib::pifilestream>(name);
- return std::move(strm);
+ auto strm = plib::make_unique_base<plib::pistream, plib::pifilestream>(name);
+ return strm;
}
catch (const plib::pexception &e)
{
if (dynamic_cast<const plib::file_open_e *>(&e) == nullptr )
throw;
}
- return plib::unique_ptr<plib::pistream>(nullptr);
+ return std::unique_ptr<plib::pistream>(nullptr);
}
-class netlist_tool_callbacks_t : public netlist::callbacks_t
-{
-public:
- netlist_tool_callbacks_t(tool_app_t &app)
- : netlist::callbacks_t()
- , m_app(app)
- { }
-
- void vlog(const plib::plog_level &l, const pstring &ls) const override;
-
-private:
- tool_app_t &m_app;
-};
-
class netlist_tool_t : public netlist::netlist_t
{
public:
netlist_tool_t(tool_app_t &app, const pstring &aname)
- : netlist::netlist_t(aname, plib::make_unique<netlist_tool_callbacks_t>(app))
+ : netlist::netlist_t(aname), m_app(app)
{
}
- void init()
+ virtual ~netlist_tool_t() override
{
}
- netlist::setup_t &setup() { return nlstate().setup(); }
+ void init()
+ {
+ }
void read_netlist(const pstring &filename, const pstring &name,
const std::vector<pstring> &logs,
@@ -185,22 +157,23 @@ public:
// read the netlist ...
for (auto & d : defines)
- setup().add_define(d);
+ setup().register_define(d);
for (auto & r : roms)
- setup().register_source(plib::make_unique<netlist_data_folder_t>(r));
+ setup().register_source(plib::make_unique_base<netlist::source_t, netlist_data_folder_t>(setup(), r));
- setup().register_source(plib::make_unique<netlist::source_file_t>(filename));
+ setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_file_t>(setup(), filename));
setup().include(name);
- create_dynamic_logs(logs);
+ log_setup(logs);
// start devices
- setup().prepare_to_run();
+ this->start();
// reset
this->reset();
}
- void create_dynamic_logs(const std::vector<pstring> &logs)
+ void log_setup(const std::vector<pstring> &logs)
{
log().debug("Creating dynamic logs ...\n");
for (auto & log : logs)
@@ -213,15 +186,15 @@ public:
std::vector<char> save_state()
{
- run_state_manager().pre_save();
+ state().pre_save();
std::size_t size = 0;
- for (auto const & s : run_state_manager().save_list())
+ for (auto const & s : state().save_list())
size += s->m_dt.size * s->m_count;
std::vector<char> buf(size);
char *p = buf.data();
- for (auto const & s : run_state_manager().save_list())
+ for (auto const & s : state().save_list())
{
std::size_t sz = s->m_dt.size * s->m_count;
if (s->m_dt.is_float || s->m_dt.is_integral)
@@ -237,7 +210,7 @@ public:
void load_state(std::vector<char> &buf)
{
std::size_t size = 0;
- for (auto const & s : run_state_manager().save_list())
+ for (auto const & s : state().save_list())
size += s->m_dt.size * s->m_count;
if (buf.size() != size)
@@ -245,7 +218,7 @@ public:
char *p = buf.data();
- for (auto const & s : run_state_manager().save_list())
+ for (auto const & s : state().save_list())
{
std::size_t sz = s->m_dt.size * s->m_count;
if (s->m_dt.is_float || s->m_dt.is_integral)
@@ -254,16 +227,19 @@ public:
log().fatal("found unsupported save element {1}\n", s->m_name);
p += sz;
}
- run_state_manager().post_load();
- nlstate().rebuild_lists();
+ state().post_load();
+ rebuild_lists();
}
protected:
+ void vlog(const plib::plog_level &l, const pstring &ls) const override;
+
private:
+ tool_app_t &m_app;
};
-void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls) const
+void netlist_tool_t::vlog(const plib::plog_level &l, const pstring &ls) const
{
pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str());
// FIXME: ...
@@ -272,19 +248,18 @@ void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls
throw netlist::nl_exception(err);
}
+
struct input_t
{
input_t(const netlist::setup_t &setup, const pstring &line)
- : m_value(0.0)
{
- std::array<char, 400> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
+ char buf[400];
double t;
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
- int e = sscanf(line.c_str(), "%lf,%[^,],%lf", &t, buf.data(), &m_value);
+ int e = sscanf(line.c_str(), "%lf,%[^,],%lf", &t, buf, &m_value);
if (e != 3)
throw netlist::nl_exception(plib::pfmt("error {1} scanning line {2}\n")(e)(line));
m_time = netlist::netlist_time::from_double(t);
- m_param = setup.find_param(pstring(buf.data()), true);
+ m_param = setup.find_param(pstring(buf, pstring::UTF8), true);
}
void setparam()
@@ -311,12 +286,13 @@ struct input_t
double m_value;
};
-static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstring &fname)
+static std::vector<input_t> read_input(const netlist::setup_t &setup, pstring fname)
{
std::vector<input_t> ret;
if (fname != "")
{
- plib::putf8_reader r = plib::putf8_reader(plib::pifilestream(fname));
+ plib::pifilestream f(fname);
+ plib::putf8_reader r(f);
pstring l;
while (r.readline(l))
{
@@ -333,82 +309,78 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstr
void tool_app_t::run()
{
plib::chrono::timer<plib::chrono::system_ticks> t;
- std::vector<input_t> inps;
- netlist::netlist_time ttr;
- netlist_tool_t nt(*this, "netlist");
+ t.start();
- {
- auto t_guard(t.guard());
- //plib::perftime_t<plib::exact_ticks> t;
+ netlist_tool_t nt(*this, "netlist");
+ //plib::perftime_t<plib::exact_ticks> t;
- nt.init();
+ nt.init();
- if (!opt_verb())
- nt.log().verbose.set_enabled(false);
- if (opt_quiet())
- nt.log().warning.set_enabled(false);
+ if (!opt_verb())
+ nt.log().verbose.set_enabled(false);
+ if (opt_quiet())
+ nt.log().warning.set_enabled(false);
- nt.read_netlist(opt_file(), opt_name(),
- opt_logs(),
- m_options, opt_rfolders());
+ nt.read_netlist(opt_file(), opt_name(),
+ opt_logs(),
+ opt_defines(), opt_rfolders());
- inps = read_input(nt.setup(), opt_inp());
- ttr = netlist::netlist_time::from_double(opt_ttr());
- }
+ std::vector<input_t> inps = read_input(nt.setup(), opt_inp());
+ netlist::netlist_time ttr = netlist::netlist_time::from_double(opt_ttr());
+ t.stop();
pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
t.reset();
+ t.start();
- netlist::netlist_time nlt = nt.time();
+ // FIXME: error handling
+ if (opt_loadstate.was_specified())
{
- auto t_guard(t.guard());
-
- // FIXME: error handling
- if (opt_loadstate.was_specified())
- {
- plib::pifilestream strm(opt_loadstate());
- plib::pbinary_reader reader(strm);
- std::vector<char> loadstate;
- reader.read(loadstate);
- nt.load_state(loadstate);
- pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double());
- }
+ plib::pifilestream strm(opt_loadstate());
+ plib::pbinary_reader reader(strm);
+ std::vector<char> loadstate;
+ reader.read(loadstate);
+ nt.load_state(loadstate);
+ pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double());
+ }
- unsigned pos = 0;
+ unsigned pos = 0;
+ netlist::netlist_time nlt = nt.time();
- while (pos < inps.size()
- && inps[pos].m_time < ttr
- && inps[pos].m_time >= nlt)
- {
- nt.process_queue(inps[pos].m_time - nlt);
- inps[pos].setparam();
- nlt = inps[pos].m_time;
- pos++;
- }
+ while (pos < inps.size()
+ && inps[pos].m_time < ttr
+ && inps[pos].m_time >= nlt)
+ {
+ nt.process_queue(inps[pos].m_time - nlt);
+ inps[pos].setparam();
+ nlt = inps[pos].m_time;
+ pos++;
+ }
- pout("runnning ...\n");
+ pout("runnning ...\n");
- if (ttr > nlt)
- nt.process_queue(ttr - nlt);
- else
- {
- pout("end time {1:.6f} less than saved time {2:.6f}\n",
- ttr.as_double(), nlt.as_double());
- ttr = nlt;
- }
+ if (ttr > nlt)
+ nt.process_queue(ttr - nlt);
+ else
+ {
+ pout("end time {1:.6f} less than saved time {2:.6f}\n",
+ ttr.as_double(), nlt.as_double());
+ ttr = nlt;
+ }
- if (opt_savestate.was_specified())
- {
- auto savestate = nt.save_state();
- plib::pofilestream strm(opt_savestate());
- plib::pbinary_writer writer(strm);
- writer.write(savestate);
- }
- nt.stop();
+ if (opt_savestate.was_specified())
+ {
+ auto savestate = nt.save_state();
+ plib::pofilestream strm(opt_savestate());
+ plib::pbinary_writer writer(strm);
+ writer.write(savestate);
}
+ nt.stop();
+
+ t.stop();
double emutime = t.as_seconds();
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n",
@@ -427,9 +399,9 @@ void tool_app_t::static_compile()
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
- m_options, opt_rfolders());
+ opt_defines(), opt_rfolders());
- plib::putf8_writer w(&pout_strm);
+ plib::putf8_writer w(pout_strm);
std::map<pstring, pstring> mp;
nt.solver()->create_solver_code(mp);
@@ -445,26 +417,13 @@ void tool_app_t::static_compile()
void tool_app_t::mac_out(const pstring &s, const bool cont)
{
+ static constexpr unsigned RIGHT = 72;
if (cont)
{
- unsigned pos = 0;
- pstring r;
+ unsigned adj = 0;
for (const auto &x : s)
- {
- if (x == '\t')
- {
- auto pos_mod_4 = pos % opt_tabwidth();
- auto tab_adj = opt_tabwidth() - pos_mod_4;
- r += plib::rpad(pstring(""), pstring(" "), tab_adj);
- pos += tab_adj;
- }
- else
- {
- r += x;
- pos++;
- }
- }
- pout("{1}\\\n", plib::rpad(r, pstring(" "), opt_linewidth()-1));
+ adj += (x == '\t' ? 3 : 0);
+ pout("{1}\\\n", s.rpad(" ", RIGHT-1-adj));
}
else
pout("{1}\n", s);
@@ -474,15 +433,15 @@ void tool_app_t::cmac(const netlist::factory::element_t *e)
{
auto v = plib::psplit(e->param_desc(), ",");
pstring vs;
- for (const auto &s : v)
- vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
+ for (auto s : v)
+ vs += ", p" + s.replace_all("+", "").replace_all(".", "_");
mac_out("#define " + e->name() + "(name" + vs + ")");
mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)");
- for (const auto &s : v)
+ for (auto s : v)
{
- pstring r(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"));
- if (plib::startsWith(s, "+"))
+ pstring r(s.replace_all("+", "").replace_all(".", "_"));
+ if (s.startsWith("+"))
mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")");
else
mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")");
@@ -494,18 +453,18 @@ void tool_app_t::mac(const netlist::factory::element_t *e)
{
auto v = plib::psplit(e->param_desc(), ",");
pstring vs;
- for (const auto &s : v)
+ for (auto s : v)
{
- vs += ", " + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
+ vs += ", " + s.replace_all("+", "").replace_all(".", "_");
}
pout("{1}(name{2})\n", e->name(), vs);
if (v.size() > 0)
{
pout("/*\n");
- for (const auto &s : v)
+ for (auto s : v)
{
- pstring r(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"));
- if (plib::startsWith(s, "+"))
+ pstring r(s.replace_all("+", "").replace_all(".", "_"));
+ if (s.startsWith("+"))
pout("{1:10}: Terminal\n",r);
else
pout("{1:10}: Parameter\n", r);
@@ -523,7 +482,8 @@ void tool_app_t::create_header()
nt.log().verbose.set_enabled(false);
nt.log().warning.set_enabled(false);
- nt.setup().register_source(plib::make_unique<netlist::source_proc_t>("dummy", &netlist_dummy));
+ nt.setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_proc_t>(nt.setup(), "dummy", &netlist_dummy));
nt.setup().include("dummy");
pout("// license:GPL-2.0+\n");
@@ -546,9 +506,9 @@ void tool_app_t::create_header()
if (last_source != e->sourcefile())
{
last_source = e->sourcefile();
- pout("{1}\n", plib::rpad(pstring("// "), pstring("-"), opt_linewidth()));
- pout("{1}{2}\n", pstring("// Source: "), plib::replace_all(e->sourcefile(), "../", ""));
- pout("{1}\n", plib::rpad(pstring("// "), pstring("-"), opt_linewidth()));
+ pout("{1}\n", pstring("// ").rpad("-", 72));
+ pout("{1}{2}\n", pstring("// Source: "), e->sourcefile().replace_all("../", ""));
+ pout("{1}\n", pstring("// ").rpad("-", 72));
}
cmac(e.get());
}
@@ -567,7 +527,8 @@ void tool_app_t::create_docheader()
nt.log().verbose.set_enabled(false);
nt.log().warning.set_enabled(false);
- nt.setup().register_source(plib::make_unique<netlist::source_proc_t>("dummy", &netlist_dummy));
+ nt.setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_proc_t>(nt.setup(), "dummy", &netlist_dummy));
nt.setup().include("dummy");
std::vector<pstring> devs;
@@ -619,42 +580,73 @@ void tool_app_t::listdevices()
netlist::factory::list_t &list = nt.setup().factory();
- nt.setup().register_source(plib::make_unique<netlist::source_proc_t>("dummy", &netlist_dummy));
+ nt.setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_proc_t>(nt.setup(), "dummy", &netlist_dummy));
nt.setup().include("dummy");
- nt.setup().prepare_to_run();
+ nt.start();
- std::vector<netlist::pool_owned_ptr<netlist::core_device_t>> devs;
+ std::vector<plib::owned_ptr<netlist::core_device_t>> devs;
for (auto & f : list)
{
pstring out = plib::pfmt("{1:-20} {2}(<id>")(f->classname())(f->name());
+ std::vector<pstring> terms;
- f->macro_actions(nt.setup(), f->name() + "_lc");
- auto d = f->Create(nt.nlstate(), f->name() + "_lc");
+ f->macro_actions(nt.setup().netlist(), f->name() + "_lc");
+ auto d = f->Create(nt.setup().netlist(), f->name() + "_lc");
// get the list of terminals ...
- std::vector<pstring> terms(nt.setup().get_terminals_for_device_name(d->name()));
+ for (auto & t : nt.setup().m_terminals)
+ {
+ if (t.second->name().startsWith(d->name()))
+ {
+ pstring tn(t.second->name().substr(d->name().length()+1));
+ if (tn.find(".") == pstring::npos)
+ terms.push_back(tn);
+ }
+ }
+
+ for (auto & t : nt.setup().m_alias)
+ {
+ if (t.first.startsWith(d->name()))
+ {
+ pstring tn(t.first.substr(d->name().length()+1));
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), tn.c_str());
+ if (tn.find(".") == pstring::npos)
+ {
+ terms.push_back(tn);
+ pstring resolved = nt.setup().resolve_alias(t.first);
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), resolved.c_str());
+ if (resolved != t.first)
+ {
+ auto found = std::find(terms.begin(), terms.end(), resolved.substr(d->name().length()+1));
+ if (found!=terms.end())
+ terms.erase(found);
+ }
+ }
+ }
+ }
out += "," + f->param_desc();
- for (const auto &p : plib::psplit(f->param_desc(),",") )
+ for (auto p : plib::psplit(f->param_desc(),",") )
{
- if (plib::startsWith(p, "+"))
+ if (p.startsWith("+"))
{
plib::container::remove(terms, p.substr(1));
}
}
out += ")";
- pout("{}\n", out);
+ printf("%s\n", out.c_str());
if (terms.size() > 0)
{
pstring t = "";
for (auto & j : terms)
t += "," + j;
- pout("\tTerminals: {}\n", t.substr(1));
+ printf("\tTerminals: %s\n", t.substr(1).c_str());
}
- devs.emplace_back(std::move(d));
+ devs.push_back(std::move(d));
}
}
@@ -689,6 +681,10 @@ int tool_app_t::execute()
plib::fpsignalenabler::global_enable(true);
plib::fpsignalenabler sigen(plib::FP_ALL & ~plib::FP_INEXACT & ~plib::FP_UNDERFLOW);
+ //perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
+ //perr("Update dispatching using method {}\n", pmf_verbose[NL_PMF_TYPE]);
+ //printf("test2 %f\n", std::exp(-14362.38064713));
+
if (opt_help())
{
pout(usage());
@@ -698,8 +694,8 @@ int tool_app_t::execute()
if (opt_version())
{
pout(
- "nltool (netlist) " PSTRINGIFY(NLTOOL_VERSION) "\n"
- "Copyright (C) 2019 Couriersud\n"
+ "nltool (netlist) 0.1\n"
+ "Copyright (C) 2018 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
@@ -707,12 +703,9 @@ int tool_app_t::execute()
return 0;
}
- m_options = opt_defines();
- m_options.emplace_back("NLTOOL_VERSION=" PSTRINGIFY(NLTOOL_VERSION));
-
try
{
- pstring cmd = opt_cmd.as_string();
+ pstring cmd = opt_cmd();
if (cmd == "listdevices")
listdevices();
else if (cmd == "run")
@@ -730,29 +723,29 @@ int tool_app_t::execute()
if (opt_file() == "-")
{
plib::pstdin f;
- plib::copystream(ostrm, f);
+ ostrm.write(f);
}
else
{
plib::pifilestream f(opt_file());
- plib::copystream(ostrm, f);
+ ostrm.write(f);
}
contents = ostrm.str();
pstring result;
- if (opt_type.as_string() == "spice")
+ if (opt_type().equals("spice"))
{
nl_convert_spice_t c;
c.convert(contents);
result = c.result();
}
- else if (opt_type.as_string() == "eagle")
+ else if (opt_type().equals("eagle"))
{
nl_convert_eagle_t c;
c.convert(contents);
result = c.result();
}
- else if (opt_type.as_string() == "rinf")
+ else if (opt_type().equals("rinf"))
{
nl_convert_rinf_t c;
c.convert(contents);
@@ -778,6 +771,13 @@ int tool_app_t::execute()
perr("plib exception caught: {}\n", e.text());
}
+#if 0
+#define str(x) # x
+#define strx(x) str(x)
+#define ttt strx(__cplusplus)
+ printf("%s\n", ttt);
+#endif
+
return 0;
}
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
index 683bb8a1c55..23491e88349 100644
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -1,13 +1,45 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include "plib/pstring.h"
-#include "netlist/nl_setup.h"
-#include "plib/plists.h"
-#include "plib/pmain.h"
-#include "plib/ppmf.h"
-#include "plib/pstream.h"
-
#include <cstring>
+#include "../plib/pstring.h"
+#include "../plib/plists.h"
+#include "../plib/pstream.h"
+#include "../plib/pmain.h"
+#include "../plib/ppmf.h"
+#include "../nl_setup.h"
+
+class nlwav_app : public plib::app
+{
+public:
+ nlwav_app() :
+ plib::app(),
+ opt_inp(*this, "i", "input", "-", "input file"),
+ opt_out(*this, "o", "output", "-", "output file"),
+ opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"),
+ opt_rate(*this, "r", "rate", 48000, "sample rate of output file"),
+ opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
+ opt_quiet(*this,"q", "quiet", "be quiet - no warnings"),
+ opt_version(*this, "", "version", "display version and exit"),
+ opt_help(*this, "h", "help", "display help and exit")
+ {}
+ plib::option_str opt_inp;
+ plib::option_str opt_out;
+ plib::option_double opt_amp;
+ plib::option_long opt_rate;
+ plib::option_bool opt_verb;
+ plib::option_bool opt_quiet;
+ plib::option_bool opt_version;
+ plib::option_bool opt_help;
+
+ int execute();
+ pstring usage();
+
+ plib::pstdin pin_strm;
+private:
+ void convert1(long sample_rate);
+ void convert(long sample_rate);
+};
+
/* From: https://ffmpeg.org/pipermail/ffmpeg-devel/2007-October/038122.html
* The most compatible way to make a wav header for unknown length is to put
@@ -19,470 +51,324 @@
* and data chunk length to the file.
*/
/* http://de.wikipedia.org/wiki/RIFF_WAVE */
-
class wav_t
{
public:
- // XXNOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
- wav_t(plib::postream &strm, std::size_t sr, std::size_t channels)
- : m_f(strm)
- /* force "play" to play and warn about eof instead of being silent */
- , m_fmt(static_cast<std::uint16_t>(channels), static_cast<std::uint32_t>(sr))
- , m_data(m_f.seekable() ? 0 : 0xffffffff)
+ wav_t(plib::postream &strm, unsigned sr) : m_f(strm)
{
-
- write(m_fh);
- write(m_fmt);
- write(m_data);
+ initialize(sr);
+ m_f.write(&m_fh, sizeof(m_fh));
+ m_f.write(&m_fmt, sizeof(m_fmt));
+ m_f.write(&m_data, sizeof(m_data));
}
-
- COPYASSIGNMOVE(wav_t, delete)
-
~wav_t()
{
if (m_f.seekable())
{
m_fh.filelen = m_data.len + sizeof(m_data) + sizeof(m_fh) + sizeof(m_fmt) - 8;
- m_f.seekp(0);
- write(m_fh);
- write(m_fmt);
+ m_f.seek(0);
+ m_f.write(&m_fh, sizeof(m_fh));
+ m_f.write(&m_fmt, sizeof(m_fmt));
//data.len = fmt.block_align * n;
- write(m_data);
+ m_f.write(&m_data, sizeof(m_data));
}
}
- std::size_t channels() { return m_fmt.channels; }
- std::size_t sample_rate() { return m_fmt.sample_rate; }
-
- template <typename T>
- void write(const T &val)
- {
- m_f.write(reinterpret_cast<const plib::postream::value_type *>(&val), sizeof(T));
- }
+ unsigned channels() { return m_fmt.channels; }
+ unsigned sample_rate() { return m_fmt.sample_rate; }
- void write_sample(int *sample)
+ void write_sample(int sample)
{
m_data.len += m_fmt.block_align;
- for (std::size_t i = 0; i < channels(); i++)
- {
- auto ps = static_cast<int16_t>(sample[i]); /* 16 bit sample, FIXME: Endianess? */
- write(ps);
- }
+ int16_t ps = static_cast<int16_t>(sample); /* 16 bit sample, FIXME: Endianess? */
+ m_f.write(&ps, sizeof(ps));
}
private:
struct riff_chunk_t
{
- uint8_t group_id[4] = {'R','I','F','F'};
- uint32_t filelen = 0;
- uint8_t rifftype[4] = {'W','A','V','E'};
+ uint8_t group_id[4];
+ uint32_t filelen;
+ uint8_t rifftype[4];
};
struct riff_format_t
{
- riff_format_t(uint16_t achannels, uint32_t asample_rate)
- {
- channels = achannels;
- sample_rate = asample_rate;
- block_align = channels * ((bits_sample + 7) / 8);
- bytes_per_second = sample_rate * block_align;
- }
- uint8_t signature[4] = {'f','m','t',' '};
- uint32_t fmt_length = 16;
- uint16_t format_tag = 0x0001; // PCM
+ uint8_t signature[4];
+ uint32_t fmt_length;
+ uint16_t format_tag;
uint16_t channels;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t block_align;
- uint16_t bits_sample = 16;
+ uint16_t bits_sample;
};
struct riff_data_t
{
- riff_data_t(uint32_t alen) : len(alen) {}
- uint8_t signature[4] = {'d','a','t','a'};
+ uint8_t signature[4];
uint32_t len;
// data follows
};
- plib::postream &m_f;
+ void initialize(unsigned sr)
+ {
+ std::memcpy(m_fh.group_id, "RIFF", 4);
+ m_fh.filelen = 0x0; // Fixme
+ std::memcpy(m_fh.rifftype, "WAVE", 4);
+
+ std::memcpy(m_fmt.signature, "fmt ", 4);
+ m_fmt.fmt_length = 16;
+ m_fmt.format_tag = 0x0001; //PCM
+ m_fmt.channels = 1;
+ m_fmt.sample_rate = sr;
+ m_fmt.bits_sample = 16;
+ m_fmt.block_align = m_fmt.channels * ((m_fmt.bits_sample + 7) / 8);
+ m_fmt.bytes_per_second = m_fmt.sample_rate * m_fmt.block_align;
+
+ std::memcpy(m_data.signature, "data", 4);
+ //m_data.len = m_fmt.bytes_per_second * 2 * 0;
+ /* force "play" to play and warn about eof instead of being silent */
+ m_data.len = (m_f.seekable() ? 0 : 0xffffffff);
+
+ }
riff_chunk_t m_fh;
riff_format_t m_fmt;
riff_data_t m_data;
+ plib::postream &m_f;
+
};
class log_processor
{
public:
- using callback_type = plib::pmfp<void, std::size_t, double, double>;
-
- struct elem
- {
- elem() : t(0), v(0), eof(false), need_more(true) { }
- double t;
- double v;
- bool eof;
- bool need_more;
- };
-
- log_processor(std::size_t channels, callback_type &cb)
- : m_cb(cb)
- , m_e(channels)
- { }
-
- bool readmore(std::vector<plib::putf8_reader> &r)
- {
- bool success = false;
- for (std::size_t i = 0; i< r.size(); i++)
- {
- if (m_e[i].need_more)
- {
- pstring line;
- m_e[i].eof = !r[i].readline(line);
- if (!m_e[i].eof)
- {
- // sscanf is very fast ...
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
- sscanf(line.c_str(), "%lf %lf", &m_e[i].t, &m_e[i].v);
- m_e[i].need_more = false;
- }
- }
- success |= !m_e[i].eof;
- }
- return success;
- }
+ typedef plib::pmfp<void, double, double> callback_type;
+ log_processor(plib::pistream &is, callback_type cb) : m_is(is), m_cb(cb) { }
- void process(std::vector<plib::unique_ptr<plib::pistream>> &is)
+ void process()
{
- std::vector<plib::putf8_reader> readers;
- for (auto &i : is)
- {
- plib::putf8_reader r(std::move(i));
- readers.push_back(std::move(r));
- }
-
+ plib::putf8_reader reader(m_is);
pstring line;
- bool more = readmore(readers);
- while (more)
+ while(reader.readline(line))
{
- double mint = 1e200;
- std::size_t mini = 0;
- for (std::size_t i = 0; i<readers.size(); i++)
- if (!m_e[i].need_more)
- {
- if (m_e[i].t < mint)
- {
- mint = m_e[i].t;
- mini = i;
- }
- }
-
- m_e[mini].need_more = true;
- m_cb(mini, mint, m_e[mini].v);
- more = readmore(readers);
+ double t = 0.0; double v = 0.0;
+ sscanf(line.c_str(), "%lf %lf", &t, &v);
+ m_cb(t, v);
}
}
private:
+ plib::pistream &m_is;
callback_type m_cb;
- std::vector<elem> m_e;
};
struct aggregator
{
- using callback_type = plib::pmfp<void, std::size_t, double, double>;
+ typedef plib::pmfp<void, double, double> callback_type;
- aggregator(std::size_t channels, double quantum, callback_type cb)
- : m_channels(channels)
- , m_quantum(quantum)
+ aggregator(double quantum, callback_type cb)
+ : m_quantum(quantum)
, m_cb(cb)
, ct(0.0)
, lt(0.0)
- , outsam(channels, 0.0)
- , cursam(channels, 0.0)
+ , outsam(0.0)
+ , cursam(0.0)
{ }
- void process(std::size_t chan, double time, double val)
+ void process(double time, double val)
{
- while (time >= ct + m_quantum)
+ while (time >= ct)
{
- for (std::size_t i=0; i< m_channels; i++)
- {
- outsam[i] += (ct - lt) * cursam[i];
- outsam[i] = outsam[i] / m_quantum;
- m_cb(i, ct, outsam[i]);
- outsam[i] = 0.0;
- }
+ outsam += (ct - lt) * cursam;
+ outsam = outsam / m_quantum;
+ m_cb(ct, outsam);
+ outsam = 0.0;
lt = ct;
ct += m_quantum;
}
- for (std::size_t i=0; i< m_channels; i++)
- outsam[i] += (time-lt)*cursam[i];
+ outsam += (time-lt)*cursam;
lt = time;
- cursam[chan] = val;
+ cursam = val;
}
private:
- std::size_t m_channels;
double m_quantum;
callback_type m_cb;
double ct;
double lt;
- std::vector<double> outsam;
- std::vector<double> cursam;
+ double outsam;
+ double cursam;
};
class wavwriter
{
public:
- wavwriter(plib::postream &fo, std::size_t channels, std::size_t sample_rate, double ampa)
- : mean(channels, 0.0)
- , means(channels, 0.0)
- , maxsam(channels, -1e9)
- , minsam(channels, 1e9)
- , m_n(channels, 0)
- , m_samples(channels, 0)
- , m_last_time(0)
+ wavwriter(plib::postream &fo, unsigned sample_rate, double ampa)
+ : mean(0.0)
+ , means(0.0)
+ , maxsam(-1e9)
+ , minsam(1e9)
+ , n(0)
, m_fo(fo)
- , m_amp(ampa)
- , m_wo(m_fo, sample_rate, channels)
+ , amp(ampa)
+ , m_wo(m_fo, sample_rate)
{ }
- void process(std::size_t chan, double time, double outsam)
+ void process(double time, double outsam)
{
- if (time > m_last_time)
- m_wo.write_sample(m_samples.data());
- m_last_time = time;
- means[chan] += outsam;
- maxsam[chan] = std::max(maxsam[chan], outsam);
- minsam[chan] = std::min(minsam[chan], outsam);
- m_n[chan]++;
- //mean = means / (double) m_n;
- mean[chan] += 5.0 / static_cast<double>(m_wo.sample_rate()) * (outsam - mean[chan]);
-
- outsam = (outsam - mean[chan]) * m_amp;
+ means += outsam;
+ maxsam = std::max(maxsam, outsam);
+ minsam = std::min(minsam, outsam);
+ n++;
+ //mean = means / (double) n;
+ mean += 5.0 / static_cast<double>(m_wo.sample_rate()) * (outsam - mean);
+
+ outsam = (outsam - mean) * amp;
outsam = std::max(-32000.0, outsam);
outsam = std::min(32000.0, outsam);
- m_samples[chan] = static_cast<int>(outsam);
+ m_wo.write_sample(static_cast<int>(outsam));
}
- std::vector<double> mean;
- std::vector<double> means;
- std::vector<double> maxsam;
- std::vector<double> minsam;
- std::vector<std::size_t> m_n;
- std::vector<int> m_samples;
- double m_last_time;
+ double mean;
+ double means;
+ double maxsam;
+ double minsam;
+ std::size_t n;
private:
-
plib::postream &m_fo;
- double m_amp;
+ double amp;
wav_t m_wo;
};
-class vcdwriter
+void nlwav_app::convert(long sample_rate)
{
-public:
-
- enum format_e
- {
- DIGITAL,
- ANALOG
- };
-
- vcdwriter(plib::postream &fo, const std::vector<pstring> &channels,
- format_e format, double high_level = 2.0, double low_level = 1.0)
- : m_channels(channels.size())
- , m_last_time(0)
- , m_fo(fo)
- , m_high_level(high_level)
- , m_low_level(low_level)
- , m_format(format)
- {
- for (pstring::value_type c = 64; c < 64+26; c++)
- m_ids.emplace_back(pstring(c));
- write("$date Sat Jan 19 14:14:17 2019\n");
- write("$end\n");
- write("$version Netlist nlwav 0.1\n");
- write("$end\n");
- write("$timescale 1 ns\n");
- write("$end\n");
- std::size_t i = 0;
- for (const auto &ch : channels)
- {
- // $var real 64 N1X1 N1X1 $end
- if (format == ANALOG)
- write(pstring("$var real 64 ") + m_ids[i++] + " " + ch + " $end\n");
- else if (format == DIGITAL)
- write(pstring("$var wire 1 ") + m_ids[i++] + " " + ch + " $end\n");
- }
- write("$enddefinitions $end\n");
- if (format == ANALOG)
- {
- write("$dumpvars\n");
- //r0.0 N1X1
- for (i = 0; i < channels.size(); i++)
- write(pstring("r0.0 ") + m_ids[i] + "\n");
- write("$end\n");
- }
-
- }
-
- void process(std::size_t chan, double time, double outsam)
+ plib::postream *fo = (opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opt_out()));
+ plib::pistream *fin = (opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opt_inp()));
+ plib::putf8_reader reader(*fin);
+ wav_t *wo = plib::palloc<wav_t>(*fo, static_cast<unsigned>(sample_rate));
+
+ double dt = 1.0 / static_cast<double>(wo->sample_rate());
+ double ct = dt;
+ //double mean = 2.4;
+ double amp = opt_amp();
+ double mean = 0.0;
+ double means = 0.0;
+ double cursam = 0.0;
+ double outsam = 0.0;
+ double lt = 0.0;
+ double maxsam = -1e9;
+ double minsam = 1e9;
+ int n = 0;
+ //short sample = 0;
+ pstring line;
+
+ while(reader.readline(line))
{
- if (time > m_last_time)
+#if 1
+ double t = 0.0; double v = 0.0;
+ sscanf(line.c_str(), "%lf %lf", &t, &v);
+ while (t >= ct)
{
- write(pstring("#") + plib::to_string(static_cast<std::int64_t>(m_last_time * 1e9)) + " ");
- write(m_buf + "\n");
- m_buf = "";
- m_last_time = time;
+ outsam += (ct - lt) * cursam;
+ outsam = outsam / dt;
+ if (t>0.0)
+ {
+ means += outsam;
+ maxsam = std::max(maxsam, outsam);
+ minsam = std::min(minsam, outsam);
+ n++;
+ //mean = means / (double) n;
+ mean += 5.0 / static_cast<double>(wo->sample_rate()) * (outsam - mean);
+ }
+ outsam = (outsam - mean) * amp;
+ outsam = std::max(-32000.0, outsam);
+ outsam = std::min(32000.0, outsam);
+ wo->write_sample(static_cast<int>(outsam));
+ outsam = 0.0;
+ lt = ct;
+ ct += dt;
}
- if (m_format == ANALOG)
- m_buf += "r" + plib::to_string(outsam)+ " " + m_ids[chan] + " ";
- else
+ outsam += (t-lt)*cursam;
+ lt = t;
+ cursam = v;
+#else
+ float t = 0.0; float v = 0.0;
+ fscanf(FIN, "%f %f", &t, &v);
+ while (ct <= t)
{
- if (outsam >= m_high_level)
- m_buf += pstring("1") + m_ids[chan] + " ";
- else if (outsam <= m_low_level)
- m_buf += pstring("0") + m_ids[chan] + " ";
+ wo.write_sample(sample);
+ n++;
+ ct += dt;
}
+ means += v;
+ mean = means / (double) n;
+ v = v - mean;
+ v = v * amp;
+ if (v>32000.0)
+ v = 32000.0;
+ else if (v<-32000.0)
+ v = -32000.0;
+ sample = v;
+ //printf("%f %f\n", t, v);
+#endif
}
-
-private:
- void write(const pstring &line)
- {
- auto p = static_cast<const char *>(line.c_str());
- std::size_t len = std::strlen(p);
- m_fo.write(p, len);
- }
-
- std::size_t m_channels;
- double m_last_time;
-
- plib::postream &m_fo;
- std::vector<pstring> m_ids;
- pstring m_buf;
- double m_high_level;
- double m_low_level;
- format_e m_format;
-};
-
-class nlwav_app : public plib::app
-{
-public:
- nlwav_app() :
- plib::app(),
- opt_fmt(*this, "f", "format", 0, std::vector<pstring>({"wav","vcda","vcdd"}),
- "output format. Available options are wav|vcda|vcdd."
- " wav : multichannel wav output"
- " vcda : analog VCD output"
- " vcdd : digital VCD output"
- " Digital signals are created using the --high and --low options"
- ),
- opt_out(*this, "o", "output", "-", "output file"),
- opt_rate(*this, "r", "rate", 48000, "sample rate of output file"),
- opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction (wav only)"),
- opt_high(*this, "u", "high", 2.0, "minimum input for high level (vcdd only)"),
- opt_low(*this, "l", "low", 1.0, "maximum input for low level (vcdd only)"),
- opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
- opt_quiet(*this,"q", "quiet", "be quiet - no warnings"),
- opt_args(*this, "input file(s)"),
- opt_version(*this, "", "version", "display version and exit"),
- opt_help(*this, "h", "help", "display help and exit"),
- opt_ex1(*this, "./nlwav -f vcdd -o x.vcd log_V*",
- "convert all files starting with \"log_V\" into a digital vcd file"),
- opt_ex2(*this, "./nlwav -f wav -o x.wav log_V*",
- "convert all files starting with \"log_V\" into a multichannel wav file"),
- m_outstrm(nullptr)
- {}
-
- int execute() override;
- pstring usage() override;
-
-private:
- void convert_wav();
- void convert_vcd(vcdwriter::format_e format);
-
- plib::option_str_limit<unsigned> opt_fmt;
- plib::option_str opt_out;
- plib::option_num<std::size_t> opt_rate;
- plib::option_num<double> opt_amp;
- plib::option_num<double> opt_high;
- plib::option_num<double> opt_low;
- plib::option_bool opt_verb;
- plib::option_bool opt_quiet;
- plib::option_args opt_args;
- plib::option_bool opt_version;
- plib::option_bool opt_help;
- plib::option_example opt_ex1;
- plib::option_example opt_ex2;
- plib::pstdin pin_strm;
-
- std::vector<plib::unique_ptr<plib::pistream>> m_instrms;
- plib::postream *m_outstrm;
-};
-
-void nlwav_app::convert_wav()
-{
-
- double dt = 1.0 / static_cast<double>(opt_rate());
-
- plib::unique_ptr<wavwriter> wo = plib::make_unique<wavwriter>(*m_outstrm, m_instrms.size(), opt_rate(), opt_amp());
- plib::unique_ptr<aggregator> ago = plib::make_unique<aggregator>(m_instrms.size(), dt, aggregator::callback_type(&wavwriter::process, wo.get()));
- aggregator::callback_type agcb = log_processor::callback_type(&aggregator::process, ago.get());
-
- log_processor lp(m_instrms.size(), agcb);
-
- lp.process(m_instrms);
+ plib::pfree(wo);
+ if (opt_inp() != "-")
+ plib::pfree(fin);
+ if (opt_out() != "-")
+ plib::pfree(fo);
if (!opt_quiet())
{
-#if 0
- perr("Mean (low freq filter): {}\n", wo->mean);
- perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->m_n));
- perr("Amp + {}\n", 32000.0 / (wo->maxsam - wo->mean));
- perr("Amp - {}\n", -32000.0 / (wo->minsam - wo->mean));
-#endif
+ perr("Mean (low freq filter): {}\n", mean);
+ perr("Mean (static): {}\n", means / static_cast<double>(n));
+ perr("Amp + {}\n", 32000.0 / (maxsam- mean));
+ perr("Amp - {}\n", -32000.0 / (minsam- mean));
}
}
-void nlwav_app::convert_vcd(vcdwriter::format_e format)
+void nlwav_app::convert1(long sample_rate)
{
+ plib::postream *fo = (opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opt_out()));
+ plib::pistream *fin = (opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opt_inp()));
- plib::unique_ptr<vcdwriter> wo = plib::make_unique<vcdwriter>(*m_outstrm, opt_args(),
- format, opt_high(), opt_low());
- log_processor::callback_type agcb = log_processor::callback_type(&vcdwriter::process, wo.get());
+ double dt = 1.0 / static_cast<double>(sample_rate);
- log_processor lp(m_instrms.size(), agcb);
+ wavwriter *wo = plib::palloc<wavwriter>(*fo, static_cast<unsigned>(sample_rate), opt_amp());
+ aggregator ag(dt, aggregator::callback_type(&wavwriter::process, wo));
+ log_processor lp(*fin, log_processor::callback_type(&aggregator::process, &ag));
- lp.process(m_instrms);
+ lp.process();
if (!opt_quiet())
{
-#if 0
perr("Mean (low freq filter): {}\n", wo->mean);
- perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->m_n));
+ perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->n));
perr("Amp + {}\n", 32000.0 / (wo->maxsam - wo->mean));
perr("Amp - {}\n", -32000.0 / (wo->minsam - wo->mean));
-#endif
}
+
+ plib::pfree(wo);
+ if (opt_inp() != "-")
+ plib::pfree(fin);
+ if (opt_out() != "-")
+ plib::pfree(fo);
+
}
pstring nlwav_app::usage()
{
return help("Convert netlist log files into wav files.\n",
- "nlwav [OPTION] ... [FILE] ...");
+ "nltool [options]");
}
int nlwav_app::execute()
{
- for (auto &i : opt_args())
- pout(pstring("Hello : ") + i + "\n");
if (opt_help())
{
pout(usage());
@@ -493,7 +379,7 @@ int nlwav_app::execute()
{
pout(
"nlwav (netlist) 0.1\n"
- "Copyright (C) 2019 Couriersud\n"
+ "Copyright (C) 2018 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
@@ -501,31 +387,10 @@ int nlwav_app::execute()
return 0;
}
- m_outstrm = (opt_out() == "-" ? &pout_strm : plib::pnew<plib::pofilestream>(opt_out()));
-
- for (auto &oi: opt_args())
- {
- plib::unique_ptr<plib::pistream> fin = (oi == "-" ?
- plib::make_unique<plib::pstdin>()
- : plib::make_unique<plib::pifilestream>(oi));
- m_instrms.push_back(std::move(fin));
- }
-
- switch (opt_fmt())
- {
- case 0:
- convert_wav(); break;
- case 1:
- convert_vcd(vcdwriter::ANALOG); break;
- case 2:
- convert_vcd(vcdwriter::DIGITAL); break;
- default:
- // tease compiler - can't happen
- break;
- }
-
- if (opt_out() != "-")
- plib::pdelete(m_outstrm);
+ if ((1))
+ convert1(opt_rate());
+ else
+ convert(opt_rate());
return 0;
}
diff --git a/src/lib/netlist/solver/mat_cr.h b/src/lib/netlist/solver/mat_cr.h
new file mode 100644
index 00000000000..8693c49c3e1
--- /dev/null
+++ b/src/lib/netlist/solver/mat_cr.h
@@ -0,0 +1,175 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * mat_cr.h
+ *
+ * Compressed row format matrices
+ *
+ */
+
+#ifndef MAT_CR_H_
+#define MAT_CR_H_
+
+#include <algorithm>
+#include "../plib/pconfig.h"
+#include "../plib/palloc.h"
+
+template<std::size_t N, typename C = uint16_t, typename T = double>
+struct mat_cr_t
+{
+ typedef C index_type;
+ typedef T value_type;
+
+ C diag[N]; // diagonal index pointer n
+ C ia[N+1]; // row index pointer n + 1
+ C ja[N*N]; // column index array nz_num, initially (n * n)
+ T A[N*N]; // Matrix elements nz_num, initially (n * n)
+
+ std::size_t size;
+ std::size_t nz_num;
+
+ explicit mat_cr_t(const std::size_t n)
+ : size(n)
+ , nz_num(0)
+ {
+#if 0
+#if 0
+ ia = plib::palloc_array<C>(n + 1);
+ ja = plib::palloc_array<C>(n * n);
+ diag = plib::palloc_array<C>(n);
+#else
+ diag = plib::palloc_array<C>(n + (n + 1) + n * n);
+ ia = diag + n;
+ ja = ia + (n+1);
+ A = plib::palloc_array<T>(n * n);
+#endif
+#endif
+ }
+
+ ~mat_cr_t()
+ {
+#if 0
+ plib::pfree_array(diag);
+#if 0
+ plib::pfree_array(ia);
+ plib::pfree_array(ja);
+#endif
+ plib::pfree_array(A);
+#endif
+ }
+
+ void set_scalar(const T scalar)
+ {
+ for (std::size_t i=0, e=nz_num; i<e; i++)
+ A[i] = scalar;
+ }
+
+ void mult_vec(const T * RESTRICT x, T * RESTRICT res)
+ {
+ /*
+ * res = A * x
+ */
+
+ std::size_t i = 0;
+ std::size_t k = 0;
+ const std::size_t oe = nz_num;
+
+ while (k < oe)
+ {
+ T tmp = 0.0;
+ const std::size_t e = ia[i+1];
+ for (; k < e; k++)
+ tmp += A[k] * x[ja[k]];
+ res[i++] = tmp;
+ }
+ }
+
+ void incomplete_LU_factorization(T * RESTRICT LU)
+ {
+ /*
+ * incomplete LU Factorization according to http://de.wikipedia.org/wiki/ILU-Zerlegung
+ *
+ * Result is stored in matrix LU
+ *
+ */
+
+ const std::size_t lnz = nz_num;
+
+ for (std::size_t k = 0; k < lnz; k++)
+ LU[k] = A[k];
+
+ for (std::size_t i = 1; ia[i] < lnz; i++) // row i
+ {
+ const std::size_t iai1 = ia[i + 1];
+ const std::size_t pke = diag[i];
+ for (std::size_t pk = ia[i]; pk < pke; pk++) // all columns left of diag in row i
+ {
+ // pk == (i, k)
+ const std::size_t k = ja[pk];
+ const std::size_t iak1 = ia[k + 1];
+ const T LUpk = LU[pk] = LU[pk] / LU[diag[k]];
+
+ std::size_t pt = ia[k];
+
+ for (std::size_t pj = pk + 1; pj < iai1; pj++) // pj = (i, j)
+ {
+ // we can assume that within a row ja increases continuously */
+ const std::size_t ej = ja[pj];
+ while (ja[pt] < ej && pt < iak1)
+ pt++;
+ if (pt < iak1 && ja[pt] == ej)
+ LU[pj] = LU[pj] - LUpk * LU[pt];
+ }
+ }
+ }
+ }
+
+ void solveLUx (const T * RESTRICT LU, T * RESTRICT r)
+ {
+ /*
+ * Solve a linear equation Ax = r
+ * where
+ * A = L*U
+ *
+ * L unit lower triangular
+ * U upper triangular
+ *
+ * ==> LUx = r
+ *
+ * ==> Ux = L⁻¹ r = w
+ *
+ * ==> r = Lw
+ *
+ * This can be solved for w using backwards elimination in L.
+ *
+ * Now Ux = w
+ *
+ * This can be solved for x using backwards elimination in U.
+ *
+ */
+
+ for (std::size_t i = 1; ia[i] < nz_num; ++i )
+ {
+ T tmp = 0.0;
+ const std::size_t j1 = ia[i];
+ const std::size_t j2 = diag[i];
+
+ for (std::size_t j = j1; j < j2; ++j )
+ tmp += LU[j] * r[ja[j]];
+
+ r[i] -= tmp;
+ }
+ // i now is equal to n;
+ for (std::size_t i = size; i-- > 0; )
+ {
+ T tmp = 0.0;
+ const std::size_t di = diag[i];
+ const std::size_t j2 = ia[i+1];
+ for (std::size_t j = di + 1; j < j2; j++ )
+ tmp += LU[j] * r[ja[j]];
+ r[i] = (r[i] - tmp) / LU[di];
+ }
+ }
+};
+
+#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index 1fe14b0f5e1..87c9b46ba21 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -6,623 +6,552 @@
*/
#include "nld_matrix_solver.h"
-#include "plib/putil.h"
+#include "../plib/putil.h"
#include <cmath> // <<= needed by windows build
namespace netlist
{
-namespace devices
+ namespace devices
+ {
+
+proxied_analog_output_t::~proxied_analog_output_t()
{
+}
- terms_for_net_t::terms_for_net_t()
- : m_railstart(0)
- , m_last_V(0.0)
- , m_DD_n_m_1(0.0)
- , m_h_n_m_1(1e-9)
- {
- }
+terms_for_net_t::terms_for_net_t()
+ : m_railstart(0)
+ , m_last_V(0.0)
+ , m_DD_n_m_1(0.0)
+ , m_h_n_m_1(1e-9)
+{
+}
- void terms_for_net_t::add(terminal_t *term, int net_other, bool sorted)
- {
- if (sorted)
- for (std::size_t i=0; i < m_connected_net_idx.size(); i++)
+void terms_for_net_t::clear()
+{
+ m_terms.clear();
+ m_connected_net_idx.clear();
+ m_gt.clear();
+ m_go.clear();
+ m_Idr.clear();
+ m_connected_net_V.clear();
+}
+
+void terms_for_net_t::add(terminal_t *term, int net_other, bool sorted)
+{
+ if (sorted)
+ for (unsigned i=0; i < m_connected_net_idx.size(); i++)
+ {
+ if (m_connected_net_idx[i] > net_other)
{
- if (m_connected_net_idx[i] > net_other)
- {
- plib::container::insert_at(m_terms, i, term);
- plib::container::insert_at(m_connected_net_idx, i, net_other);
- return;
- }
+ plib::container::insert_at(m_terms, i, term);
+ plib::container::insert_at(m_connected_net_idx, i, net_other);
+ plib::container::insert_at(m_gt, i, 0.0);
+ plib::container::insert_at(m_go, i, 0.0);
+ plib::container::insert_at(m_Idr, i, 0.0);
+ plib::container::insert_at(m_connected_net_V, i, nullptr);
+ return;
}
- m_terms.push_back(term);
- m_connected_net_idx.push_back(net_other);
- }
-
- // ----------------------------------------------------------------------------------------
- // matrix_solver
- // ----------------------------------------------------------------------------------------
-
- matrix_solver_t::matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
- const eSortType sort, const solver_parameters_t *params)
- : device_t(anetlist, name)
- , m_params(*params)
- , m_stat_calculations(*this, "m_stat_calculations", 0)
- , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0)
- , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
- , m_iterative_fail(*this, "m_iterative_fail", 0)
- , m_iterative_total(*this, "m_iterative_total", 0)
- , m_last_step(*this, "m_last_step", netlist_time::zero())
- , m_fb_sync(*this, "FB_sync")
- , m_Q_sync(*this, "Q_sync")
- , m_ops(0)
- , m_sort(sort)
+ }
+ m_terms.push_back(term);
+ m_connected_net_idx.push_back(net_other);
+ m_gt.push_back(0.0);
+ m_go.push_back(0.0);
+ m_Idr.push_back(0.0);
+ m_connected_net_V.push_back(nullptr);
+}
+
+void terms_for_net_t::set_pointers()
+{
+ for (unsigned i = 0; i < count(); i++)
{
- connect_post_start(m_fb_sync, m_Q_sync);
+ m_terms[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]);
+ m_connected_net_V[i] = m_terms[i]->m_otherterm->net().Q_Analog_state_ptr();
}
+}
+
+// ----------------------------------------------------------------------------------------
+// matrix_solver
+// ----------------------------------------------------------------------------------------
+
+matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name,
+ const eSortType sort, const solver_parameters_t *params)
+ : device_t(anetlist, name)
+ , m_params(*params)
+ , m_stat_calculations(*this, "m_stat_calculations", 0)
+ , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0)
+ , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0)
+ , m_iterative_fail(*this, "m_iterative_fail", 0)
+ , m_iterative_total(*this, "m_iterative_total", 0)
+ , m_last_step(*this, "m_last_step", netlist_time::zero())
+ , m_fb_sync(*this, "FB_sync")
+ , m_Q_sync(*this, "Q_sync")
+ , m_ops(0)
+ , m_sort(sort)
+{
+ connect_post_start(m_fb_sync, m_Q_sync);
+}
- void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
- {
+matrix_solver_t::~matrix_solver_t()
+{
+}
- log().debug("New solver setup\n");
+void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
+{
- m_nets.clear();
- m_terms.clear();
+ log().debug("New solver setup\n");
- for (auto & net : nets)
- {
- m_nets.push_back(net);
- m_terms.push_back(plib::make_unique<terms_for_net_t>());
- m_rails_temp.push_back(plib::make_unique<terms_for_net_t>());
- }
+ m_nets.clear();
+ m_terms.clear();
- for (std::size_t k = 0; k < nets.size(); k++)
- {
- analog_net_t *net = nets[k];
+ for (auto & net : nets)
+ {
+ m_nets.push_back(net);
+ m_terms.push_back(plib::make_unique<terms_for_net_t>());
+ m_rails_temp.push_back(plib::palloc<terms_for_net_t>());
+ }
- log().debug("setting up net\n");
+ for (std::size_t k = 0; k < nets.size(); k++)
+ {
+ analog_net_t *net = nets[k];
- net->set_solver(this);
+ log().debug("setting up net\n");
- for (auto &p : net->core_terms())
- {
- log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
- switch (p->type())
- {
- case detail::terminal_type::TERMINAL:
- if (p->device().is_timestep())
- if (!plib::container::contains(m_step_devices, &p->device()))
- m_step_devices.push_back(&p->device());
- if (p->device().is_dynamic())
- if (!plib::container::contains(m_dynamic_devices, &p->device()))
- m_dynamic_devices.push_back(&p->device());
- {
- auto *pterm = dynamic_cast<terminal_t *>(p);
- add_term(k, pterm);
- }
- log().debug("Added terminal {1}\n", p->name());
- break;
- case detail::terminal_type::INPUT:
- {
- proxied_analog_output_t *net_proxy_output = nullptr;
- for (auto & input : m_inps)
- if (input->proxied_net() == &p->net())
- {
- net_proxy_output = input.get();
- break;
- }
-
- if (net_proxy_output == nullptr)
- {
- pstring nname = this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()));
- nl_assert(p->net().is_analog());
- auto net_proxy_output_u = pool().make_poolptr<proxied_analog_output_t>(*this, nname, static_cast<analog_net_t *>(&p->net()));
- net_proxy_output = net_proxy_output_u.get();
- m_inps.push_back(std::move(net_proxy_output_u));
- }
- net_proxy_output->net().add_terminal(*p);
- // FIXME: repeated calling - kind of brute force
- net_proxy_output->net().rebuild_list();
- log().debug("Added input\n");
- }
- break;
- case detail::terminal_type::OUTPUT:
- log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
- p->name());
- break;
- }
- }
- log().debug("added net with {1} populated connections\n", net->core_terms().size());
- }
+ net->set_solver(this);
- /* now setup the matrix */
- setup_matrix();
- }
-
- void matrix_solver_t::sort_terms(eSortType 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_nets.size();
-
- switch (sort)
+ for (auto &p : net->m_core_terms)
{
- case PREFER_BAND_MATRIX:
- {
- for (std::size_t k = 0; k < iN - 1; k++)
+ log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
+ switch (p->type())
+ {
+ case detail::terminal_type::TERMINAL:
+ if (p->device().is_timestep())
+ if (!plib::container::contains(m_step_devices, &p->device()))
+ m_step_devices.push_back(&p->device());
+ if (p->device().is_dynamic())
+ if (!plib::container::contains(m_dynamic_devices, &p->device()))
+ m_dynamic_devices.push_back(&p->device());
{
- auto pk = get_weight_around_diag(k,k);
- for (std::size_t i = k+1; i < iN; i++)
- {
- auto pi = get_weight_around_diag(i,k);
- if (pi < pk)
- {
- std::swap(m_terms[i], m_terms[k]);
- std::swap(m_nets[i], m_nets[k]);
- pk = get_weight_around_diag(k,k);
- }
- }
+ terminal_t *pterm = dynamic_cast<terminal_t *>(p);
+ add_term(k, pterm);
}
- }
- break;
- case PREFER_IDENTITY_TOP_LEFT:
- {
- for (std::size_t k = 0; k < iN - 1; k++)
+ log().debug("Added terminal {1}\n", p->name());
+ break;
+ case detail::terminal_type::INPUT:
{
- auto pk = get_left_right_of_diag(k,k);
- for (std::size_t i = k+1; i < iN; i++)
- {
- auto pi = get_left_right_of_diag(i,k);
- if (pi.first <= pk.first && pi.second >= pk.second)
+ proxied_analog_output_t *net_proxy_output = nullptr;
+ for (auto & input : m_inps)
+ if (input->m_proxied_net == &p->net())
{
- std::swap(m_terms[i], m_terms[k]);
- std::swap(m_nets[i], m_nets[k]);
- pk = get_left_right_of_diag(k,k);
+ net_proxy_output = input.get();
+ break;
}
- }
- }
- }
- break;
- case ASCENDING:
- case DESCENDING:
- {
- int sort_order = (m_sort == DESCENDING ? 1 : -1);
- for (std::size_t k = 0; k < iN - 1; k++)
- for (std::size_t i = k+1; i < iN; i++)
+ if (net_proxy_output == nullptr)
{
- if ((static_cast<int>(m_terms[k]->m_railstart) - static_cast<int>(m_terms[i]->m_railstart)) * sort_order < 0)
- {
- std::swap(m_terms[i], m_terms[k]);
- std::swap(m_nets[i], m_nets[k]);
- }
+ pstring nname = this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()));
+ auto net_proxy_output_u = plib::make_unique<proxied_analog_output_t>(*this, nname);
+ net_proxy_output = net_proxy_output_u.get();
+ m_inps.push_back(std::move(net_proxy_output_u));
+ nl_assert(p->net().is_analog());
+ net_proxy_output->m_proxied_net = static_cast<analog_net_t *>(&p->net());
}
- }
- break;
- case NOSORT:
- break;
- }
- /* rebuild */
- for (auto &term : m_terms)
- {
- int *other = term->m_connected_net_idx.data();
- for (std::size_t i = 0; i < term->count(); i++)
- //FIXME: this is weird
- if (other[i] != -1)
- other[i] = get_net_idx(&term->terms()[i]->connected_terminal()->net());
+ net_proxy_output->net().add_terminal(*p);
+ // FIXME: repeated calling - kind of brute force
+ net_proxy_output->net().rebuild_list();
+ log().debug("Added input\n");
+ }
+ break;
+ case detail::terminal_type::OUTPUT:
+ log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
+ p->name());
+ break;
+ }
}
+ log().debug("added net with {1} populated connections\n", net->m_core_terms.size());
}
- void matrix_solver_t::setup_matrix()
- {
- const std::size_t iN = m_nets.size();
+ /* now setup the matrix */
+ setup_matrix();
+}
- for (std::size_t k = 0; k < iN; k++)
- {
- m_terms[k]->m_railstart = m_terms[k]->count();
- for (std::size_t i = 0; i < m_rails_temp[k]->count(); i++)
- this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->m_connected_net_idx.data()[i], false);
- }
-
- // free all - no longer needed
- m_rails_temp.clear();
-
- sort_terms(m_sort);
-
- this->set_pointers();
+void matrix_solver_t::setup_matrix()
+{
+ const std::size_t iN = m_nets.size();
- /* create a list of non zero elements. */
- for (unsigned k = 0; k < iN; k++)
- {
- terms_for_net_t * t = m_terms[k].get();
- /* pretty brutal */
- int *other = t->m_connected_net_idx.data();
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ m_terms[k]->m_railstart = m_terms[k]->count();
+ for (std::size_t 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);
- t->m_nz.clear();
+ m_terms[k]->set_pointers();
+ }
- for (std::size_t i = 0; i < t->m_railstart; i++)
- if (!plib::container::contains(t->m_nz, static_cast<unsigned>(other[i])))
- t->m_nz.push_back(static_cast<unsigned>(other[i]));
+ for (terms_for_net_t *rt : m_rails_temp)
+ {
+ rt->clear(); // no longer needed
+ plib::pfree(rt); // no longer needed
+ }
- t->m_nz.push_back(k); // add diagonal
+ m_rails_temp.clear();
- /* and sort */
- std::sort(t->m_nz.begin(), t->m_nz.end());
- }
+ /* 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.
+ *
+ */
- /* create a list of non zero elements right of the diagonal
- * These list anticipate the population of array elements by
- * Gaussian elimination.
- */
- for (std::size_t k = 0; k < iN; k++)
- {
- terms_for_net_t * t = m_terms[k].get();
- /* pretty brutal */
- int *other = t->m_connected_net_idx.data();
+ if (m_sort != NOSORT)
+ {
+ int sort_order = (m_sort == DESCENDING ? 1 : -1);
- if (k==0)
- t->m_nzrd.clear();
- else
+ for (unsigned k = 0; k < iN - 1; k++)
+ for (unsigned i = k+1; i < iN; i++)
{
- t->m_nzrd = m_terms[k-1]->m_nzrd;
- for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); )
+ if ((static_cast<int>(m_terms[k]->m_railstart) - static_cast<int>(m_terms[i]->m_railstart)) * sort_order < 0)
{
- if (*j < k + 1)
- j = t->m_nzrd.erase(j);
- else
- ++j;
+ std::swap(m_terms[i], m_terms[k]);
+ std::swap(m_nets[i], m_nets[k]);
}
}
- for (std::size_t i = 0; i < t->m_railstart; 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]));
-
- /* and sort */
- std::sort(t->m_nzrd.begin(), t->m_nzrd.end());
- }
-
- /* create a list of non zero elements below diagonal k
- * This should reduce cache misses ...
- */
-
- std::vector<std::vector<bool>> touched(iN, std::vector<bool>(iN));
-
- for (std::size_t k = 0; k < iN; k++)
- {
- for (std::size_t j = 0; j < iN; j++)
- touched[k][j] = false;
- for (std::size_t j = 0; j < m_terms[k]->m_nz.size(); j++)
- touched[k][m_terms[k]->m_nz[j]] = true;
- }
-
- m_ops = 0;
- for (unsigned k = 0; k < iN; k++)
- {
- m_ops++; // 1/A(k,k)
- for (unsigned row = k + 1; row < iN; row++)
- {
- if (touched[row][k])
- {
- m_ops++;
- if (!plib::container::contains(m_terms[k]->m_nzbd, row))
- m_terms[k]->m_nzbd.push_back(row);
- for (std::size_t col = k + 1; col < iN; col++)
- if (touched[k][col])
- {
- touched[row][col] = true;
- m_ops += 2;
- }
- }
- }
- }
- log().verbose("Number of mults/adds for {1}: {2}", name(), m_ops);
-
- if ((false))
- for (std::size_t k = 0; k < iN; k++)
- {
- pstring line = plib::pfmt("{1:3}")(k);
- for (const auto & nzrd : m_terms[k]->m_nzrd)
- line += plib::pfmt(" {1:3}")(nzrd);
- log().verbose("{1}", line);
- }
-
- /*
- * save states
- */
- for (std::size_t k = 0; k < iN; k++)
+ for (auto &term : m_terms)
{
- pstring num = plib::pfmt("{1}")(k);
-
- state().save(*this, m_terms[k]->m_last_V, this->name(), "lastV." + num);
- state().save(*this, m_terms[k]->m_DD_n_m_1, this->name(), "m_DD_n_m_1." + num);
- state().save(*this, m_terms[k]->m_h_n_m_1, this->name(), "m_h_n_m_1." + num);
-
- // FIXME: This shouldn't be necessary, recalculate on each entry ...
- state().save(*this, m_gonn[k],"GO" + num, this->name(), m_terms[k]->count());
- state().save(*this, m_gtn[k],"GT" + num, this->name(), m_terms[k]->count());
- state().save(*this, m_Idrn[k],"IDR" + num, this->name(), m_terms[k]->count());
+ int *other = term->connected_net_idx();
+ for (unsigned i = 0; i < term->count(); i++)
+ if (other[i] != -1)
+ other[i] = get_net_idx(&term->terms()[i]->m_otherterm->net());
}
}
- void matrix_solver_t::update_inputs()
+ /* create a list of non zero elements. */
+ for (unsigned k = 0; k < iN; k++)
{
- // avoid recursive calls. Inputs are updated outside this call
- for (auto &inp : m_inps)
- inp->push(inp->proxied_net()->Q_Analog());
- }
+ terms_for_net_t * t = m_terms[k].get();
+ /* pretty brutal */
+ int *other = t->connected_net_idx();
- void matrix_solver_t::update_dynamic()
- {
- /* update all non-linear devices */
- for (auto &dyn : m_dynamic_devices)
- dyn->update_terminals();
- }
+ t->m_nz.clear();
- void matrix_solver_t::reset()
- {
- m_last_step = netlist_time::zero();
- }
+ for (unsigned i = 0; i < t->m_railstart; i++)
+ if (!plib::container::contains(t->m_nz, static_cast<unsigned>(other[i])))
+ t->m_nz.push_back(static_cast<unsigned>(other[i]));
- void matrix_solver_t::update() NL_NOEXCEPT
- {
- const netlist_time new_timestep = solve(exec().time());
- update_inputs();
+ t->m_nz.push_back(k); // add diagonal
- if (m_params.m_dynamic_ts && has_timestep_devices() && new_timestep > netlist_time::zero())
- {
- m_Q_sync.net().toggle_and_push_to_queue(new_timestep);
- }
+ /* and sort */
+ std::sort(t->m_nz.begin(), t->m_nz.end());
}
- /* update_forced is called from within param_update
- *
- * this should only occur outside of execution and thus
- * using time should be safe.
- *
+ /* create a list of non zero elements right of the diagonal
+ * These list anticipate the population of array elements by
+ * Gaussian elimination.
*/
- void matrix_solver_t::update_forced()
+ for (unsigned k = 0; k < iN; k++)
{
- const netlist_time new_timestep = solve(exec().time());
- plib::unused_var(new_timestep);
-
- update_inputs();
+ terms_for_net_t * t = m_terms[k].get();
+ /* pretty brutal */
+ int *other = t->connected_net_idx();
- if (m_params.m_dynamic_ts && has_timestep_devices())
+ if (k==0)
+ t->m_nzrd.clear();
+ else
{
- m_Q_sync.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_min_timestep));
+ t->m_nzrd = m_terms[k-1]->m_nzrd;
+ for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); )
+ {
+ if (*j < k + 1)
+ j = t->m_nzrd.erase(j);
+ else
+ ++j;
+ }
}
+
+ for (unsigned i = 0; i < t->m_railstart; 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]));
+
+ /* and sort */
+ std::sort(t->m_nzrd.begin(), t->m_nzrd.end());
}
- void matrix_solver_t::step(const netlist_time &delta)
+ /* create a list of non zero elements below diagonal k
+ * This should reduce cache misses ...
+ */
+
+ bool **touched = plib::palloc_array<bool *>(iN);
+ for (unsigned k=0; k<iN; k++)
+ touched[k] = plib::palloc_array<bool>(iN);
+
+ for (unsigned k = 0; k < iN; k++)
{
- const nl_double dd = delta.as_double();
- for (auto &d : m_step_devices)
- d->timestep(dd);
+ for (unsigned j = 0; j < iN; j++)
+ touched[k][j] = false;
+ for (unsigned j = 0; j < m_terms[k]->m_nz.size(); j++)
+ touched[k][m_terms[k]->m_nz[j]] = true;
}
- void matrix_solver_t::solve_base()
+ m_ops = 0;
+ for (unsigned k = 0; k < iN; k++)
{
- ++m_stat_vsolver_calls;
- if (has_dynamic_devices())
+ m_ops++; // 1/A(k,k)
+ for (unsigned row = k + 1; row < iN; row++)
{
- std::size_t this_resched;
- std::size_t newton_loops = 0;
- do
- {
- update_dynamic();
- // Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
- this_resched = this->vsolve_non_dynamic(true);
- newton_loops++;
- } while (this_resched > 1 && newton_loops < m_params.m_nr_loops);
-
- m_stat_newton_raphson += newton_loops;
- // reschedule ....
- if (this_resched > 1 && !m_Q_sync.net().is_queued())
+ if (touched[row][k])
{
- log().warning(MW_1_NEWTON_LOOPS_EXCEEDED_ON_NET_1, this->name());
- m_Q_sync.net().toggle_and_push_to_queue(m_params.m_nr_recalc_delay);
+ m_ops++;
+ if (!plib::container::contains(m_terms[k]->m_nzbd, row))
+ m_terms[k]->m_nzbd.push_back(row);
+ for (unsigned col = k + 1; col < iN; col++)
+ if (touched[k][col])
+ {
+ touched[row][col] = true;
+ m_ops += 2;
+ }
}
}
- else
+ }
+ log().verbose("Number of mults/adds for {1}: {2}", name(), m_ops);
+
+ if ((0))
+ for (unsigned k = 0; k < iN; k++)
{
- this->vsolve_non_dynamic(false);
+ pstring line = plib::pfmt("{1:3}")(k);
+ for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
+ line += plib::pfmt(" {1:3}")(m_terms[k]->m_nzrd[j]);
+ log().verbose("{1}", line);
}
- }
- const netlist_time matrix_solver_t::solve(netlist_time now)
+ /*
+ * save states
+ */
+ for (unsigned k = 0; k < iN; k++)
{
- const netlist_time delta = now - m_last_step;
-
- // We are already up to date. Avoid oscillations.
- // FIXME: Make this a parameter!
- if (delta < netlist_time::quantum())
- return netlist_time::zero();
+ pstring num = plib::pfmt("{1}")(k);
- /* update all terminals for new time step */
- m_last_step = now;
- step(delta);
- solve_base();
- const netlist_time next_time_step = compute_next_timestep(delta.as_double());
+ netlist().save(*this, m_terms[k]->m_last_V, "lastV." + num);
+ netlist().save(*this, m_terms[k]->m_DD_n_m_1, "m_DD_n_m_1." + num);
+ netlist().save(*this, m_terms[k]->m_h_n_m_1, "m_h_n_m_1." + num);
- return next_time_step;
+ netlist().save(*this, m_terms[k]->go(),"GO" + num, m_terms[k]->count());
+ netlist().save(*this, m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
+ netlist().save(*this, m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count());
}
- int matrix_solver_t::get_net_idx(detail::net_t *net)
- {
- for (std::size_t k = 0; k < m_nets.size(); k++)
- if (m_nets[k] == net)
- return static_cast<int>(k);
- return -1;
- }
+ for (unsigned k=0; k<iN; k++)
+ plib::pfree_array(touched[k]);
+ plib::pfree_array(touched);
+}
- std::pair<int, int> matrix_solver_t::get_left_right_of_diag(std::size_t irow, std::size_t idiag)
- {
- /*
- * return the maximum column left of the diagonal (-1 if no cols found)
- * return the minimum column right of the diagonal (999999 if no cols found)
- */
+void matrix_solver_t::update_inputs()
+{
+ // avoid recursive calls. Inputs are updated outside this call
+ for (auto &inp : m_inps)
+ inp->push(inp->m_proxied_net->Q_Analog());
+}
- const auto row = static_cast<int>(irow);
- const auto diag = static_cast<int>(idiag);
+void matrix_solver_t::update_dynamic()
+{
+ /* update all non-linear devices */
+ for (auto &dyn : m_dynamic_devices)
+ dyn->update_terminals();
+}
- int colmax = -1;
- int colmin = 999999;
+void matrix_solver_t::reset()
+{
+ m_last_step = netlist_time::zero();
+}
- auto &term = m_terms[irow];
+void matrix_solver_t::update() NL_NOEXCEPT
+{
+ const netlist_time new_timestep = solve();
+ update_inputs();
- for (std::size_t i = 0; i < term->count(); i++)
- {
- auto col = get_net_idx(&term->terms()[i]->connected_terminal()->net());
- if (col != -1)
- {
- if (col==row) col = diag;
- else if (col==diag) col = row;
+ if (m_params.m_dynamic_ts && has_timestep_devices() && new_timestep > netlist_time::zero())
+ {
+ m_Q_sync.net().toggle_and_push_to_queue(new_timestep);
+ }
+}
- if (col > diag && col < colmin)
- colmin = col;
- else if (col < diag && col > colmax)
- colmax = col;
- }
- }
- return {colmax, colmin};
+void matrix_solver_t::update_forced()
+{
+ ATTR_UNUSED const netlist_time new_timestep = solve();
+ update_inputs();
+
+ if (m_params.m_dynamic_ts && has_timestep_devices())
+ {
+ m_Q_sync.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_min_timestep));
}
+}
- double matrix_solver_t::get_weight_around_diag(std::size_t row, std::size_t diag)
+void matrix_solver_t::step(const netlist_time &delta)
+{
+ const nl_double dd = delta.as_double();
+ for (std::size_t k=0; k < m_step_devices.size(); k++)
+ m_step_devices[k]->timestep(dd);
+}
+
+void matrix_solver_t::solve_base()
+{
+ ++m_stat_vsolver_calls;
+ if (has_dynamic_devices())
{
+ unsigned this_resched;
+ unsigned newton_loops = 0;
+ do
{
- /*
- * return average absolute distance
- */
+ update_dynamic();
+ // Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
+ this_resched = this->vsolve_non_dynamic(true);
+ newton_loops++;
+ } while (this_resched > 1 && newton_loops < m_params.m_nr_loops);
+
+ m_stat_newton_raphson += newton_loops;
+ // reschedule ....
+ if (this_resched > 1 && !m_Q_sync.net().is_queued())
+ {
+ log().warning(MW_1_NEWTON_LOOPS_EXCEEDED_ON_NET_1, this->name());
+ m_Q_sync.net().toggle_and_push_to_queue(m_params.m_nr_recalc_delay);
+ }
+ }
+ else
+ {
+ this->vsolve_non_dynamic(false);
+ }
+}
- std::vector<bool> touched(1024, false); // FIXME!
+const netlist_time matrix_solver_t::solve()
+{
+ const netlist_time now = netlist().time();
+ const netlist_time delta = now - m_last_step;
- double weight = 0.0;
- auto &term = m_terms[row];
- for (std::size_t i = 0; i < term->count(); i++)
- {
- auto col = get_net_idx(&term->terms()[i]->connected_terminal()->net());
- if (col >= 0)
- {
- auto colu = static_cast<std::size_t>(col);
- if (!touched[colu])
- {
- if (colu==row) colu = static_cast<unsigned>(diag);
- else if (colu==diag) colu = static_cast<unsigned>(row);
+ // We are already up to date. Avoid oscillations.
+ // FIXME: Make this a parameter!
+ if (delta < netlist_time::quantum())
+ return netlist_time::zero();
- weight = weight + std::abs(static_cast<double>(colu) - static_cast<double>(diag));
- touched[colu] = true;
- }
- }
- }
- return weight; // / static_cast<double>(term->m_railstart);
- }
- }
+ /* update all terminals for new time step */
+ m_last_step = now;
+ step(delta);
+ solve_base();
+ const netlist_time next_time_step = compute_next_timestep(delta.as_double());
+
+ return next_time_step;
+}
- void matrix_solver_t::add_term(std::size_t k, terminal_t *term)
+int matrix_solver_t::get_net_idx(detail::net_t *net)
+{
+ for (std::size_t k = 0; k < m_nets.size(); k++)
+ if (m_nets[k] == net)
+ return static_cast<int>(k);
+ return -1;
+}
+
+void matrix_solver_t::add_term(std::size_t k, terminal_t *term)
+{
+ if (term->m_otherterm->net().isRailNet())
{
- if (term->connected_terminal()->net().isRailNet())
+ m_rails_temp[k]->add(term, -1, false);
+ }
+ else
+ {
+ int ot = get_net_idx(&term->m_otherterm->net());
+ if (ot>=0)
{
- m_rails_temp[k]->add(term, -1, false);
+ m_terms[k]->add(term, ot, true);
}
- else
+ /* Should this be allowed ? */
+ else // if (ot<0)
{
- int ot = get_net_idx(&term->connected_terminal()->net());
- if (ot>=0)
- {
- m_terms[k]->add(term, ot, true);
- }
- /* Should this be allowed ? */
- else // if (ot<0)
- {
- m_rails_temp[k]->add(term, ot, true);
- log().fatal(MF_1_FOUND_TERM_WITH_MISSING_OTHERNET, term->name());
- }
+ m_rails_temp[k]->add(term, ot, true);
+ log().fatal(MF_1_FOUND_TERM_WITH_MISSING_OTHERNET, term->name());
}
}
+}
- netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
- {
- nl_double new_solver_timestep = m_params.m_max_timestep;
+netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
+{
+ nl_double new_solver_timestep = m_params.m_max_timestep;
- if (m_params.m_dynamic_ts)
+ if (m_params.m_dynamic_ts)
+ {
+ for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
{
- for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
- {
- analog_net_t *n = m_nets[k];
- terms_for_net_t *t = m_terms[k].get();
+ analog_net_t *n = m_nets[k];
+ terms_for_net_t *t = m_terms[k].get();
- const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
- const nl_double hn = cur_ts;
+ const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
+ const nl_double hn = cur_ts;
- nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1);
- nl_double new_net_timestep;
+ //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1);
+ nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1);
+ nl_double new_net_timestep;
- t->m_h_n_m_1 = hn;
- t->m_DD_n_m_1 = DD_n;
- if (std::fabs(DD2) > plib::constants<nl_double>::cast(1e-60)) // avoid div-by-zero
- new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(plib::constants<nl_double>::cast(0.5)*DD2));
- else
- new_net_timestep = m_params.m_max_timestep;
+ t->m_h_n_m_1 = hn;
+ t->m_DD_n_m_1 = DD_n;
+ if (std::fabs(DD2) > NL_FCONST(1e-60)) // avoid div-by-zero
+ new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(NL_FCONST(0.5)*DD2));
+ else
+ new_net_timestep = m_params.m_max_timestep;
- if (new_net_timestep < new_solver_timestep)
- new_solver_timestep = new_net_timestep;
+ if (new_net_timestep < new_solver_timestep)
+ new_solver_timestep = new_net_timestep;
- t->m_last_V = n->Q_Analog();
- }
- if (new_solver_timestep < m_params.m_min_timestep)
- {
- //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6);
- new_solver_timestep = m_params.m_min_timestep;
- }
+ t->m_last_V = n->Q_Analog();
+ }
+ if (new_solver_timestep < m_params.m_min_timestep)
+ {
+ //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6);
+ new_solver_timestep = m_params.m_min_timestep;
}
- //if (new_solver_timestep > 10.0 * hn)
- // new_solver_timestep = 10.0 * hn;
- /*
- * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
- */
- return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2);
}
+ //if (new_solver_timestep > 10.0 * hn)
+ // new_solver_timestep = 10.0 * hn;
+ /*
+ * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
+ */
+ return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2);
+}
- void matrix_solver_t::log_stats()
+
+
+void matrix_solver_t::log_stats()
+{
+ if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats)
{
- if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats)
- {
- log().verbose("==============================================");
- log().verbose("Solver {1}", this->name());
- log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name());
- log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic");
- log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep");
- log().verbose(" {1:6.3} average newton raphson loops",
- static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(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",
- this->m_stat_calculations,
- static_cast<double>(this->m_stat_calculations) / this->exec().time().as_double(),
- this->m_iterative_fail,
- 100.0 * static_cast<double>(this->m_iterative_fail)
- / static_cast<double>(this->m_stat_calculations),
- static_cast<double>(this->m_iterative_total) / static_cast<double>(this->m_stat_calculations));
- }
+ log().verbose("==============================================");
+ log().verbose("Solver {1}", this->name());
+ log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name());
+ log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic");
+ log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep");
+ log().verbose(" {1:6.3} average newton raphson loops",
+ static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(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",
+ this->m_stat_calculations,
+ static_cast<double>(this->m_stat_calculations) / this->netlist().time().as_double(),
+ this->m_iterative_fail,
+ 100.0 * static_cast<double>(this->m_iterative_fail)
+ / static_cast<double>(this->m_stat_calculations),
+ static_cast<double>(this->m_iterative_total) / static_cast<double>(this->m_stat_calculations));
}
+}
+
-} // namespace devices
+ } //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index f76660e1cb9..da44370d0d9 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -10,367 +10,282 @@
#include "netlist/nl_base.h"
#include "netlist/nl_errstr.h"
-#include "plib/palloc.h"
-#include "plib/pmatrix2d.h"
-#include "plib/putil.h"
-#include "plib/vector_ops.h"
-
-#include <cmath>
+#include "netlist/plib/putil.h"
namespace netlist
{
-namespace devices
-{
+ namespace devices
+ {
/* FIXME: these should become proper devices */
struct solver_parameters_t
{
- bool m_pivot;
+ int m_pivot;
nl_double m_accuracy;
nl_double m_dynamic_lte;
nl_double m_min_timestep;
nl_double m_max_timestep;
nl_double m_gs_sor;
bool m_dynamic_ts;
- std::size_t m_gs_loops;
- std::size_t m_nr_loops;
+ unsigned m_gs_loops;
+ unsigned m_nr_loops;
netlist_time m_nr_recalc_delay;
- bool m_use_gabs;
- bool m_use_linear_prediction;
bool m_log_stats;
};
- class terms_for_net_t : plib::nocopyassignmove
- {
- public:
- terms_for_net_t();
-
- void clear();
+class terms_for_net_t : plib::nocopyassignmove
+{
+public:
+ terms_for_net_t();
- void add(terminal_t *term, int net_other, bool sorted);
+ void clear();
- std::size_t count() const { return m_terms.size(); }
+ void add(terminal_t *term, int net_other, bool sorted);
- terminal_t **terms() { return m_terms.data(); }
+ inline std::size_t count() const { return m_terms.size(); }
- std::size_t m_railstart;
+ inline terminal_t **terms() { return m_terms.data(); }
+ inline int *connected_net_idx() { return m_connected_net_idx.data(); }
+ inline nl_double *gt() { return m_gt.data(); }
+ inline nl_double *go() { return m_go.data(); }
+ inline nl_double *Idr() { return m_Idr.data(); }
+ inline nl_double * const *connected_net_V() const { return m_connected_net_V.data(); }
- std::vector<unsigned> m_nz; /* all non zero for multiplication */
- std::vector<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */
- std::vector<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
+ void set_pointers();
- /* state */
- nl_double m_last_V;
- nl_double m_DD_n_m_1;
- nl_double m_h_n_m_1;
+ std::size_t m_railstart;
- std::vector<int> m_connected_net_idx;
- private:
- std::vector<terminal_t *> m_terms;
+ std::vector<unsigned> m_nz; /* all non zero for multiplication */
+ std::vector<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */
+ std::vector<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
- };
+ /* state */
+ nl_double m_last_V;
+ nl_double m_DD_n_m_1;
+ nl_double m_h_n_m_1;
- class proxied_analog_output_t : public analog_output_t
- {
- public:
+private:
+ std::vector<int> m_connected_net_idx;
+ std::vector<nl_double> m_go;
+ std::vector<nl_double> m_gt;
+ std::vector<nl_double> m_Idr;
+ std::vector<nl_double *> m_connected_net_V;
+ std::vector<terminal_t *> m_terms;
- proxied_analog_output_t(core_device_t &dev, const pstring &aname, analog_net_t *pnet)
- : analog_output_t(dev, aname)
- , m_proxied_net(pnet)
- { }
+};
- analog_net_t *proxied_net() const { return m_proxied_net;}
- private:
- analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
- };
+class proxied_analog_output_t : public analog_output_t
+{
+public:
- class matrix_solver_t : public device_t
- {
- public:
- using list_t = std::vector<matrix_solver_t *>;
+ proxied_analog_output_t(core_device_t &dev, const pstring &aname)
+ : analog_output_t(dev, aname)
+ , m_proxied_net(nullptr)
+ { }
+ virtual ~proxied_analog_output_t();
- enum eSortType
- {
- NOSORT,
- ASCENDING,
- DESCENDING,
- PREFER_IDENTITY_TOP_LEFT,
- PREFER_BAND_MATRIX
- };
-
- void setup(analog_net_t::list_t &nets)
- {
- vsetup(nets);
- }
+ analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
+};
- void solve_base();
- /* after every call to solve, update inputs must be called.
- * this can be done as well as a batch to ease parallel processing.
- */
- const netlist_time solve(netlist_time now);
- void update_inputs();
+class matrix_solver_t : public device_t
+{
+public:
+ using list_t = std::vector<matrix_solver_t *>;
- bool has_dynamic_devices() const { return m_dynamic_devices.size() > 0; }
- bool has_timestep_devices() const { return m_step_devices.size() > 0; }
+ enum eSortType
+ {
+ NOSORT,
+ ASCENDING,
+ DESCENDING
+ };
- void update_forced();
- void update_after(const netlist_time after)
- {
- m_Q_sync.net().toggle_and_push_to_queue(after);
- }
+ virtual ~matrix_solver_t() override;
- /* netdevice functions */
- NETLIB_UPDATEI();
- NETLIB_RESETI();
+ void setup(analog_net_t::list_t &nets)
+ {
+ vsetup(nets);
+ }
- public:
- int get_net_idx(detail::net_t *net);
- std::pair<int, int> get_left_right_of_diag(std::size_t row, std::size_t diag);
- double get_weight_around_diag(std::size_t row, std::size_t diag);
+ void solve_base();
- virtual void log_stats();
+ /* after every call to solve, update inputs must be called.
+ * this can be done as well as a batch to ease parallel processing.
+ */
+ const netlist_time solve();
+ void update_inputs();
- virtual std::pair<pstring, pstring> create_solver_code()
- {
- return std::pair<pstring, pstring>("", plib::pfmt("/* solver doesn't support static compile */\n\n"));
- }
+ inline bool has_dynamic_devices() const { return m_dynamic_devices.size() > 0; }
+ inline bool has_timestep_devices() const { return m_step_devices.size() > 0; }
- /* return number of floating point operations for solve */
- std::size_t ops() { return m_ops; }
+ void update_forced();
+ void update_after(const netlist_time &after)
+ {
+ m_Q_sync.net().toggle_and_push_to_queue(after);
+ }
- protected:
+ /* netdevice functions */
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
- matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
- eSortType sort, const solver_parameters_t *params);
+public:
+ int get_net_idx(detail::net_t *net);
- void sort_terms(eSortType sort);
+ virtual void log_stats();
- void setup_base(analog_net_t::list_t &nets);
- void update_dynamic();
+ virtual std::pair<pstring, pstring> create_solver_code()
+ {
+ return std::pair<pstring, pstring>("", plib::pfmt("/* solver doesn't support static compile */\n\n"));
+ }
- virtual void vsetup(analog_net_t::list_t &nets) = 0;
- virtual unsigned vsolve_non_dynamic(const bool newton_raphson) = 0;
+ /* return number of floating point operations for solve */
+ std::size_t ops() { return m_ops; }
- netlist_time compute_next_timestep(const double cur_ts);
- /* virtual */ void add_term(std::size_t net_idx, terminal_t *term);
+protected:
- template <typename T>
- void store(const T & V);
+ matrix_solver_t(netlist_t &anetlist, const pstring &name,
+ const eSortType sort, const solver_parameters_t *params);
- template <typename T>
- auto delta(const T & V) -> typename std::decay<decltype(V[0])>::type;
+ void setup_base(analog_net_t::list_t &nets);
+ void update_dynamic();
- template <typename T>
- void build_LE_A(T &child);
- template <typename T>
- void build_LE_RHS(T &child);
+ virtual void vsetup(analog_net_t::list_t &nets) = 0;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) = 0;
- void set_pointers()
- {
- const std::size_t iN = this->m_nets.size();
-
- std::size_t max_count = 0;
- std::size_t max_rail = 0;
- 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]->m_railstart);
- }
-
- m_mat_ptr.resize(iN, max_rail+1);
- m_gtn.resize(iN, max_count);
- m_gonn.resize(iN, max_count);
- m_Idrn.resize(iN, max_count);
- m_connected_net_Vn.resize(iN, max_count);
-
- for (std::size_t k = 0; k < iN; k++)
- {
- auto count = m_terms[k]->count();
-
- for (std::size_t i = 0; i < count; i++)
- {
- m_terms[k]->terms()[i]->set_ptrs(&m_gtn[k][i], &m_gonn[k][i], &m_Idrn[k][i]);
- m_connected_net_Vn[k][i] = m_terms[k]->terms()[i]->connected_terminal()->net().Q_Analog_state_ptr();
- }
- }
- }
+ netlist_time compute_next_timestep(const double cur_ts);
+ /* virtual */ void add_term(std::size_t net_idx, terminal_t *term);
- template <typename AP, typename FT>
- void fill_matrix(std::size_t N, AP &tcr, FT &RHS)
- {
- for (std::size_t k = 0; k < N; k++)
- {
- auto *net = m_terms[k].get();
- auto **tcr_r = &(tcr[k][0]);
-
- const std::size_t term_count = net->count();
- const std::size_t railstart = net->m_railstart;
- const auto &go = m_gonn[k];
- const auto &gt = m_gtn[k];
- const auto &Idr = m_Idrn[k];
- const auto &cnV = m_connected_net_Vn[k];
-
- for (std::size_t i = 0; i < railstart; i++)
- *tcr_r[i] += go[i];
-
- typename FT::value_type gtot_t = 0.0;
- typename FT::value_type RHS_t = 0.0;
-
- for (std::size_t i = 0; i < term_count; i++)
- {
- gtot_t += gt[i];
- RHS_t += Idr[i];
- }
- // FIXME: Code above is faster than vec_sum - Check this
- #if 0
- auto gtot_t = plib::vec_sum<FT>(term_count, m_gt);
- auto RHS_t = plib::vec_sum<FT>(term_count, m_Idr);
- #endif
-
- for (std::size_t i = railstart; i < term_count; i++)
- {
- RHS_t += (/*m_Idr[i]*/ (- go[i]) * *cnV[i]);
- }
-
- RHS[k] = RHS_t;
- // update diagonal element ...
- *tcr_r[railstart] += gtot_t; //mat.A[mat.diag[k]] += gtot_t;
- }
+ template <typename T>
+ void store(const T * RESTRICT V);
+ template <typename T>
+ T delta(const T * RESTRICT V);
- }
+ template <typename T>
+ void build_LE_A();
+ template <typename T>
+ void build_LE_RHS();
- template <typename T>
- using aligned_alloc = plib::aligned_allocator<T, PALIGN_VECTOROPT>;
+ std::vector<std::unique_ptr<terms_for_net_t>> m_terms;
+ std::vector<analog_net_t *> m_nets;
+ std::vector<std::unique_ptr<proxied_analog_output_t>> m_inps;
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_gonn;
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_gtn;
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_Idrn;
- plib::pmatrix2d<nl_double *, aligned_alloc<nl_double *>> m_mat_ptr;
- plib::pmatrix2d<nl_double *, aligned_alloc<nl_double *>> m_connected_net_Vn;
+ std::vector<terms_for_net_t *> m_rails_temp;
- plib::pmatrix2d<nl_double> m_test;
+ const solver_parameters_t &m_params;
- std::vector<plib::unique_ptr<terms_for_net_t>> m_terms;
- std::vector<analog_net_t *> m_nets;
- std::vector<pool_owned_ptr<proxied_analog_output_t>> m_inps;
+ state_var<int> m_stat_calculations;
+ state_var<int> m_stat_newton_raphson;
+ state_var<int> m_stat_vsolver_calls;
+ state_var<int> m_iterative_fail;
+ state_var<int> m_iterative_total;
- std::vector<plib::unique_ptr<terms_for_net_t>> m_rails_temp;
+private:
- const solver_parameters_t &m_params;
+ state_var<netlist_time> m_last_step;
+ std::vector<core_device_t *> m_step_devices;
+ std::vector<core_device_t *> m_dynamic_devices;
- state_var<int> m_stat_calculations;
- state_var<int> m_stat_newton_raphson;
- state_var<int> m_stat_vsolver_calls;
- state_var<int> m_iterative_fail;
- state_var<int> m_iterative_total;
+ logic_input_t m_fb_sync;
+ logic_output_t m_Q_sync;
- private:
+ /* calculate matrix */
+ void setup_matrix();
- state_var<netlist_time> m_last_step;
- std::vector<core_device_t *> m_step_devices;
- std::vector<core_device_t *> m_dynamic_devices;
+ void step(const netlist_time &delta);
- logic_input_t m_fb_sync;
- logic_output_t m_Q_sync;
+ std::size_t m_ops;
+ const eSortType m_sort;
+};
- /* calculate matrix */
- void setup_matrix();
+template <typename T>
+T matrix_solver_t::delta(const T * RESTRICT V)
+{
+ /* NOTE: Ideally we should also include currents (RHS) here. This would
+ * need a reevaluation of the right hand side after voltages have been updated
+ * and thus belong into a different calculation. This applies to all solvers.
+ */
+
+ const std::size_t iN = this->m_terms.size();
+ T cerr = 0;
+ for (std::size_t i = 0; i < iN; i++)
+ cerr = std::max(cerr, std::abs(V[i] - static_cast<T>(this->m_nets[i]->Q_Analog())));
+ return cerr;
+}
+
+template <typename T>
+void matrix_solver_t::store(const T * RESTRICT V)
+{
+ const std::size_t iN = this->m_terms.size();
+ for (std::size_t i = 0; i < iN; i++)
+ this->m_nets[i]->set_Q_Analog(V[i]);
+}
- void step(const netlist_time &delta);
+template <typename T>
+void matrix_solver_t::build_LE_A()
+{
+ static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
- std::size_t m_ops;
- const eSortType m_sort;
- };
+ T &child = static_cast<T &>(*this);
- template <typename T>
- auto matrix_solver_t::delta(const T & V) -> typename std::decay<decltype(V[0])>::type
+ const std::size_t iN = child.N();
+ for (std::size_t k = 0; k < iN; k++)
{
- /* NOTE: Ideally we should also include currents (RHS) here. This would
- * need a reevaluation of the right hand side after voltages have been updated
- * and thus belong into a different calculation. This applies to all solvers.
- */
-
- const std::size_t iN = this->m_terms.size();
- typename std::decay<decltype(V[0])>::type cerr = 0;
- for (std::size_t i = 0; i < iN; i++)
- cerr = std::max(cerr, std::abs(V[i] - this->m_nets[i]->Q_Analog()));
- return cerr;
- }
+ terms_for_net_t *terms = m_terms[k].get();
+ nl_double * Ak = &child.A(k, 0);
- template <typename T>
- void matrix_solver_t::store(const T & V)
- {
- const std::size_t iN = this->m_terms.size();
- for (std::size_t i = 0; i < iN; i++)
- this->m_nets[i]->set_Q_Analog(V[i]);
- }
+ for (std::size_t i=0; i < iN; i++)
+ Ak[i] = 0.0;
- template <typename T>
- void matrix_solver_t::build_LE_A(T &child)
- {
- using float_type = typename T::float_type;
- static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
+ const std::size_t terms_count = terms->count();
+ const std::size_t railstart = terms->m_railstart;
+ const nl_double * const RESTRICT gt = terms->gt();
- const std::size_t iN = child.size();
- for (std::size_t k = 0; k < iN; k++)
{
- terms_for_net_t *terms = m_terms[k].get();
- float_type * Ak = &child.A(k, 0ul);
-
- for (std::size_t i=0; i < iN; i++)
- Ak[i] = 0.0;
-
- const std::size_t terms_count = terms->count();
- const std::size_t railstart = terms->m_railstart;
- const float_type * const gt = m_gtn[k];
-
- {
- float_type akk = 0.0;
- for (std::size_t i = 0; i < terms_count; i++)
- akk += gt[i];
+ nl_double akk = 0.0;
+ for (std::size_t i = 0; i < terms_count; i++)
+ akk += gt[i];
- Ak[k] = akk;
- }
+ Ak[k] = akk;
+ }
- const float_type * const go = m_gonn[k];
- int * net_other = terms->m_connected_net_idx.data();
+ const nl_double * const RESTRICT go = terms->go();
+ int * RESTRICT net_other = terms->connected_net_idx();
- for (std::size_t i = 0; i < railstart; i++)
- Ak[net_other[i]] += go[i];
- }
+ for (std::size_t i = 0; i < railstart; i++)
+ Ak[net_other[i]] -= go[i];
}
+}
- template <typename T>
- void matrix_solver_t::build_LE_RHS(T &child)
- {
- static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
- using float_type = typename T::float_type;
+template <typename T>
+void matrix_solver_t::build_LE_RHS()
+{
+ static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
+ T &child = static_cast<T &>(*this);
- const std::size_t iN = child.size();
- for (std::size_t k = 0; k < iN; k++)
- {
- float_type rhsk_a = 0.0;
- float_type rhsk_b = 0.0;
+ const std::size_t iN = child.N();
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ nl_double rhsk_a = 0.0;
+ nl_double rhsk_b = 0.0;
- const std::size_t terms_count = m_terms[k]->count();
- const float_type * const go = m_gonn[k];
- const float_type * const Idr = m_Idrn[k];
- const float_type * const * other_cur_analog = m_connected_net_Vn[k];
+ const std::size_t terms_count = m_terms[k]->count();
+ const nl_double * const RESTRICT go = m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = m_terms[k]->Idr();
+ const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->connected_net_V();
- for (std::size_t i = 0; i < terms_count; i++)
- rhsk_a = rhsk_a + Idr[i];
+ for (std::size_t i = 0; i < terms_count; i++)
+ rhsk_a = rhsk_a + Idr[i];
- for (std::size_t i = m_terms[k]->m_railstart; i < terms_count; i++)
- //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
- rhsk_b = rhsk_b - go[i] * *other_cur_analog[i];
+ for (std::size_t i = m_terms[k]->m_railstart; i < terms_count; i++)
+ //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
+ rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
- child.RHS(k) = rhsk_a + rhsk_b;
- }
+ child.RHS(k) = rhsk_a + rhsk_b;
}
+}
-} //namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_DIRECT_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index 2501742218d..f03cb738028 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -8,228 +8,286 @@
#ifndef NLD_MS_DIRECT_H_
#define NLD_MS_DIRECT_H_
-#include "nld_matrix_solver.h"
+#include <algorithm>
+
#include "nld_solver.h"
-#include "plib/mat_cr.h"
-#include "plib/vector_ops.h"
+#include "nld_matrix_solver.h"
+#include "vector_base.h"
-#include <algorithm>
-#include <cmath>
+/* Disabling dynamic allocation gives a ~10% boost in performance
+ * This flag has been added to support continuous storage for arrays
+ * going forward in case we implement cuda solvers in the future.
+ */
+#define NL_USE_DYNAMIC_ALLOCATION (1)
namespace netlist
{
-namespace devices
-{
-
- template <typename FT, int SIZE>
- class matrix_solver_direct_t: public matrix_solver_t
+ namespace devices
{
- friend class matrix_solver_t;
- public:
-
- using float_type = FT;
+//#define nl_ext_double _float128 // slow, very slow
+//#define nl_ext_double long double // slightly slower
+#define nl_ext_double nl_double
- matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
- matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name, const eSortType sort, const solver_parameters_t *params, const std::size_t size);
- void vsetup(analog_net_t::list_t &nets) override;
- void reset() override { matrix_solver_t::reset(); }
-
- protected:
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- unsigned solve_non_dynamic(const bool newton_raphson);
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_direct_t: public matrix_solver_t
+{
+ friend class matrix_solver_t;
+public:
- constexpr std::size_t size() const { return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; }
+ matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
+ matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const eSortType sort, const solver_parameters_t *params, const std::size_t size);
- void LE_solve();
+ virtual ~matrix_solver_direct_t() override;
- template <typename T>
- void LE_back_subst(T & x);
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual void reset() override { matrix_solver_t::reset(); }
- FT &A(std::size_t r, std::size_t c) { return m_A[r * m_pitch + c]; }
- FT &RHS(std::size_t r) { return m_A[r * m_pitch + size()]; }
- plib::parray<FT, SIZE> m_new_V;
+protected:
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ unsigned solve_non_dynamic(const bool newton_raphson);
- private:
- static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS();
- static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 1) + 7) / 8) * 8;
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
- const std::size_t m_dim;
- const std::size_t m_pitch;
- plib::parray<FT, SIZE * int(m_pitch_ABS)> m_A;
+ void LE_solve();
- };
+ template <typename T>
+ void LE_back_subst(T * RESTRICT x);
+
+#if (NL_USE_DYNAMIC_ALLOCATION)
+ template <typename T1, typename T2>
+ nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r * m_pitch + c]; }
+ template <typename T1>
+ nl_ext_double &RHS(const T1 &r) { return m_A[r * m_pitch + N()]; }
+#else
+ template <typename T1, typename T2>
+ nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
+ template <typename T1>
+ nl_ext_double &RHS(const T1 &r) { return m_A[r][N()]; }
+#endif
+ nl_double m_last_RHS[storage_N]; // right hand side - contains currents
+
+private:
+ //static const std::size_t m_pitch = (((storage_N + 1) + 0) / 1) * 1;
+ static constexpr std::size_t m_pitch = (((storage_N + 1) + 7) / 8) * 8;
+ //static const std::size_t m_pitch = (((storage_N + 1) + 15) / 16) * 16;
+ //static const std::size_t m_pitch = (((storage_N + 1) + 31) / 32) * 32;
+#if (NL_USE_DYNAMIC_ALLOCATION)
+ //nl_ext_double * RESTRICT m_A;
+ std::vector<nl_ext_double> m_A;
+#else
+ nl_ext_double m_A[storage_N][m_pitch];
+#endif
+ //nl_ext_double m_RHSx[storage_N];
+
+ const std::size_t m_dim;
+
+};
+
+// ----------------------------------------------------------------------------------------
+// matrix_solver_direct
+// ----------------------------------------------------------------------------------------
+
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_direct_t<m_N, storage_N>::~matrix_solver_direct_t()
+{
+#if (NL_USE_DYNAMIC_ALLOCATION)
+ //plib::pfree_array(m_A);
+#endif
+}
- // ----------------------------------------------------------------------------------------
- // matrix_solver_direct
- // ----------------------------------------------------------------------------------------
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
+{
+ matrix_solver_t::setup_base(nets);
- template <typename FT, int SIZE>
- void matrix_solver_direct_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
+ /* add RHS element */
+ for (std::size_t k = 0; k < N(); k++)
{
- matrix_solver_t::setup_base(nets);
+ terms_for_net_t * t = m_terms[k].get();
- /* add RHS element */
- for (std::size_t k = 0; k < size(); k++)
- {
- terms_for_net_t * t = m_terms[k].get();
+ if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(N())))
+ t->m_nzrd.push_back(static_cast<unsigned>(N()));
+ }
- if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(size())))
- t->m_nzrd.push_back(static_cast<unsigned>(size()));
- }
+ netlist().save(*this, m_last_RHS, "m_last_RHS");
- // FIXME: This shouldn't be necessary ...
- for (std::size_t k = 0; k < size(); k++)
- state().save(*this, RHS(k), this->name(), plib::pfmt("RHS.{1}")(k));
- }
+ for (std::size_t k = 0; k < N(); k++)
+ netlist().save(*this, RHS(k), plib::pfmt("RHS.{1}")(k));
+}
- template <typename FT, int SIZE>
- void matrix_solver_direct_t<FT, SIZE>::LE_solve()
+
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_direct_t<m_N, storage_N>::LE_solve()
+{
+ const std::size_t kN = N();
+ if (!m_params.m_pivot)
{
- const std::size_t kN = size();
- if (!m_params.m_pivot)
+ for (std::size_t i = 0; i < kN; i++)
{
- for (std::size_t i = 0; i < kN; i++)
- {
- /* FIXME: Singular matrix? */
- const FT f = 1.0 / A(i,i);
- const auto &nzrd = m_terms[i]->m_nzrd;
- const auto &nzbd = m_terms[i]->m_nzbd;
- for (std::size_t j : nzbd)
- {
- const FT f1 = -f * A(j, i);
- for (std::size_t k : nzrd)
- A(j, k) += A(i, k) * f1;
- //RHS(j) += RHS(i) * f1;
- }
+ /* FIXME: Singular matrix? */
+ nl_double *Ai = &A(i, 0);
+ const nl_double f = 1.0 / A(i,i);
+ const auto &nzrd = m_terms[i]->m_nzrd;
+ const auto &nzbd = m_terms[i]->m_nzbd;
+
+ for (std::size_t j : nzbd)
+ {
+ nl_double *Aj = &A(j, 0);
+ const nl_double f1 = -f * Aj[i];
+ for (std::size_t k : nzrd)
+ Aj[k] += Ai[k] * f1;
+ //RHS(j) += RHS(i) * f1;
}
}
- else
+ }
+ else
+ {
+ for (std::size_t i = 0; i < kN; i++)
{
- for (std::size_t i = 0; i < kN; i++)
+ /* Find the row with the largest first value */
+ std::size_t maxrow = i;
+ for (std::size_t j = i + 1; j < kN; j++)
{
- /* Find the row with the largest first value */
- std::size_t maxrow = i;
- for (std::size_t j = i + 1; j < kN; j++)
- {
- //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
- if (A(j,i) * A(j,i) > A(maxrow,i) * A(maxrow,i))
- maxrow = j;
- }
+ //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
+ if (A(j,i) * A(j,i) > A(maxrow,i) * A(maxrow,i))
+ maxrow = j;
+ }
- if (maxrow != i)
- {
- /* Swap the maxrow and ith row */
- for (std::size_t k = 0; k < kN + 1; k++) {
- std::swap(A(i,k), A(maxrow,k));
- }
- //std::swap(RHS(i), RHS(maxrow));
+ if (maxrow != i)
+ {
+ /* Swap the maxrow and ith row */
+ for (std::size_t k = 0; k < kN + 1; k++) {
+ std::swap(A(i,k), A(maxrow,k));
}
- /* FIXME: Singular matrix? */
- const FT f = 1.0 / A(i,i);
+ //std::swap(RHS(i), RHS(maxrow));
+ }
+ /* FIXME: Singular matrix? */
+ const nl_double f = 1.0 / A(i,i);
- /* Eliminate column i from row j */
+ /* Eliminate column i from row j */
- for (std::size_t j = i + 1; j < kN; j++)
+ for (std::size_t j = i + 1; j < kN; j++)
+ {
+ const nl_double f1 = - A(j,i) * f;
+ if (f1 != NL_FCONST(0.0))
{
- const FT f1 = - A(j,i) * f;
- if (f1 != plib::constants<FT>::zero())
- {
- const FT * pi = &A(i,i+1);
- FT * pj = &A(j,i+1);
- #if 1
- plib::vec_add_mult_scalar_p(kN-i,pj, pi,f1);
- #else
- vec_add_mult_scalar_p1(kN-i-1,pj,pi,f1);
- //for (unsigned k = i+1; k < kN; k++)
- // pj[k] = pj[k] + pi[k] * f1;
- //for (unsigned k = i+1; k < kN; k++)
- //A(j,k) += A(i,k) * f1;
- RHS(j) += RHS(i) * f1;
- #endif
- }
+ const nl_double * RESTRICT pi = &A(i,i+1);
+ nl_double * RESTRICT pj = &A(j,i+1);
+#if 1
+ vec_add_mult_scalar_p(kN-i,pi,f1,pj);
+#else
+ vec_add_mult_scalar_p(kN-i-1,pj,f1,pi);
+ //for (unsigned k = i+1; k < kN; k++)
+ // pj[k] = pj[k] + pi[k] * f1;
+ //for (unsigned k = i+1; k < kN; k++)
+ //A(j,k) += A(i,k) * f1;
+ RHS(j) += RHS(i) * f1;
+#endif
}
}
}
}
+}
- template <typename FT, int SIZE>
- template <typename T>
- void matrix_solver_direct_t<FT, SIZE>::LE_back_subst(
- T & x)
- {
- const std::size_t kN = size();
+template <std::size_t m_N, std::size_t storage_N>
+template <typename T>
+void matrix_solver_direct_t<m_N, storage_N>::LE_back_subst(
+ T * RESTRICT x)
+{
+ const std::size_t kN = N();
- /* back substitution */
- if (m_params.m_pivot)
+ /* back substitution */
+ if (m_params.m_pivot)
+ {
+ for (std::size_t j = kN; j-- > 0; )
{
- for (std::size_t j = kN; j-- > 0; )
- {
- FT tmp = 0;
- for (std::size_t k = j+1; k < kN; k++)
- tmp += A(j,k) * x[k];
- x[j] = (RHS(j) - tmp) / A(j,j);
- }
+ T tmp = 0;
+ for (std::size_t k = j+1; k < kN; k++)
+ tmp += A(j,k) * x[k];
+ x[j] = (RHS(j) - tmp) / A(j,j);
}
- else
+ }
+ else
+ {
+ for (std::size_t j = kN; j-- > 0; )
{
- for (std::size_t j = kN; j-- > 0; )
+ T tmp = 0;
+
+ const auto *p = m_terms[j]->m_nzrd.data();
+ const auto e = m_terms[j]->m_nzrd.size() - 1; /* exclude RHS element */
+ T * Aj = &A(j,0);
+ for (std::size_t k = 0; k < e; k++)
{
- FT tmp = 0;
- const auto &nzrd = m_terms[j]->m_nzrd;
- const auto e = nzrd.size() - 1; /* exclude RHS element */
- for ( std::size_t k = 0; k < e; k++)
- tmp += A(j, nzrd[k]) * x[nzrd[k]];
- x[j] = (RHS(j) - tmp) / A(j,j);
+ const auto pk = p[k];
+ tmp += Aj[pk] * x[pk];
}
+ x[j] = (RHS(j) - tmp) / A(j,j);
}
}
+}
- template <typename FT, int SIZE>
- unsigned matrix_solver_direct_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphson)
- {
- this->LE_solve();
- this->LE_back_subst(m_new_V);
- const FT err = (newton_raphson ? delta(m_new_V) : 0.0);
- store(m_new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
- }
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_direct_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
+{
+ nl_double new_V[storage_N]; // = { 0.0 };
- template <typename FT, int SIZE>
- unsigned matrix_solver_direct_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
- {
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
+ this->LE_solve();
+ this->LE_back_subst(new_V);
- this->m_stat_calculations++;
- return this->solve_non_dynamic(newton_raphson);
- }
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
+ store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
- template <typename FT, int SIZE>
- matrix_solver_direct_t<FT, SIZE>::matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_t(anetlist, name, ASCENDING, params)
- , m_new_V(size)
- , m_dim(size)
- , m_pitch(m_pitch_ABS ? m_pitch_ABS : (((m_dim + 1) + 7) / 8) * 8)
- , m_A(size * m_pitch)
+template <std::size_t m_N, std::size_t storage_N>
+inline unsigned matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+{
+ build_LE_A<matrix_solver_direct_t>();
+ build_LE_RHS<matrix_solver_direct_t>();
+
+ for (std::size_t i=0, iN=N(); i < iN; i++)
+ m_last_RHS[i] = RHS(i);
+
+ this->m_stat_calculations++;
+ return this->solve_non_dynamic(newton_raphson);
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(netlist_t &anetlist, const pstring &name,
+ const solver_parameters_t *params, const std::size_t size)
+: matrix_solver_t(anetlist, name, ASCENDING, params)
+, m_dim(size)
+{
+#if (NL_USE_DYNAMIC_ALLOCATION)
+ m_A.resize(N() * m_pitch);
+ //m_A = plib::palloc_array<nl_ext_double>(N() * m_pitch);
+#endif
+ for (unsigned k = 0; k < N(); k++)
{
+ m_last_RHS[k] = 0.0;
}
+}
- template <typename FT, int SIZE>
- matrix_solver_direct_t<FT, SIZE>::matrix_solver_direct_t(netlist_state_t &anetlist, const pstring &name,
- const eSortType sort, const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_t(anetlist, name, sort, params)
- , m_new_V(size)
- , m_dim(size)
- , m_pitch(m_pitch_ABS ? m_pitch_ABS : (((m_dim + 1) + 7) / 8) * 8)
- , m_A(size * m_pitch)
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(netlist_t &anetlist, const pstring &name,
+ const eSortType sort, const solver_parameters_t *params, const std::size_t size)
+: matrix_solver_t(anetlist, name, sort, params)
+, m_dim(size)
+{
+#if (NL_USE_DYNAMIC_ALLOCATION)
+ m_A.resize(N() * m_pitch);
+ //m_A = plib::palloc_array<nl_ext_double>(N() * m_pitch);
+#endif
+ for (unsigned k = 0; k < N(); k++)
{
+ m_last_RHS[k] = 0.0;
}
+}
-} // namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_DIRECT_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_direct1.h b/src/lib/netlist/solver/nld_ms_direct1.h
index fbbb8ecb098..6e1f99bad7d 100644
--- a/src/lib/netlist/solver/nld_ms_direct1.h
+++ b/src/lib/netlist/solver/nld_ms_direct1.h
@@ -13,41 +13,37 @@
namespace netlist
{
-namespace devices
-{
- template <typename FT>
- class matrix_solver_direct1_t: public matrix_solver_direct_t<FT, 1>
+ namespace devices
{
- public:
-
- using float_type = FT;
- using base_type = matrix_solver_direct_t<FT, 1>;
-
- matrix_solver_direct1_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params)
- : matrix_solver_direct_t<FT, 1>(anetlist, name, params, 1)
- {}
+class matrix_solver_direct1_t: public matrix_solver_direct_t<1,1>
+{
+public:
- // ----------------------------------------------------------------------------------------
- // matrix_solver - Direct1
- // ----------------------------------------------------------------------------------------
- unsigned vsolve_non_dynamic(const bool newton_raphson) override
- {
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
- //NL_VERBOSE_OUT(("{1} {2}\n", new_val, m_RHS[0] / m_A[0][0]);
+ matrix_solver_direct1_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params)
+ : matrix_solver_direct_t<1, 1>(anetlist, name, params, 1)
+ {}
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- std::array<FT, 1> new_V = { this->RHS(0) / this->A(0,0) };
+};
- const FT err = (newton_raphson ? this->delta(new_V) : 0.0);
- this->store(new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
- }
+// ----------------------------------------------------------------------------------------
+// matrix_solver - Direct1
+// ----------------------------------------------------------------------------------------
- };
+inline unsigned matrix_solver_direct1_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
+{
+ build_LE_A<matrix_solver_direct1_t>();
+ build_LE_RHS<matrix_solver_direct1_t>();
+ //NL_VERBOSE_OUT(("{1} {2}\n", new_val, m_RHS[0] / m_A[0][0]);
+ nl_double new_V[1] = { RHS(0) / A(0,0) };
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
+ store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
-} //namespace devices
+ } //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/solver/nld_ms_direct2.h b/src/lib/netlist/solver/nld_ms_direct2.h
index 01f77c3bc3c..4004bce9cc4 100644
--- a/src/lib/netlist/solver/nld_ms_direct2.h
+++ b/src/lib/netlist/solver/nld_ms_direct2.h
@@ -13,46 +13,43 @@
namespace netlist
{
-namespace devices
+ namespace devices
+ {
+class matrix_solver_direct2_t: public matrix_solver_direct_t<2,2>
{
+public:
- // ----------------------------------------------------------------------------------------
- // matrix_solver - Direct2
- // ----------------------------------------------------------------------------------------
-
- template <typename FT>
- class matrix_solver_direct2_t: public matrix_solver_direct_t<FT, 2>
- {
- public:
+ matrix_solver_direct2_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params)
+ : matrix_solver_direct_t<2, 2>(anetlist, name, params, 2)
+ {}
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- using float_type = FT;
+};
- matrix_solver_direct2_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params)
- : matrix_solver_direct_t<double, 2>(anetlist, name, params, 2)
- {}
- unsigned vsolve_non_dynamic(const bool newton_raphson) override
- {
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
+// ----------------------------------------------------------------------------------------
+// matrix_solver - Direct2
+// ----------------------------------------------------------------------------------------
- const float_type a = this->A(0,0);
- const float_type b = this->A(0,1);
- const float_type c = this->A(1,0);
- const float_type d = this->A(1,1);
+inline unsigned matrix_solver_direct2_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
+{
+ build_LE_A<matrix_solver_direct2_t>();
+ build_LE_RHS<matrix_solver_direct2_t>();
- const float_type v1 = (a * this->RHS(1) - c * this->RHS(0)) / (a * d - b * c);
- const float_type v0 = (this->RHS(0) - b * v1) / a;
- std::array<float_type, 2> new_V = {v0, v1};
+ const nl_double a = A(0,0);
+ const nl_double b = A(0,1);
+ const nl_double c = A(1,0);
+ const nl_double d = A(1,1);
- this->m_stat_calculations++;
- const float_type err = (newton_raphson ? this->delta(new_V) : 0.0);
- this->store(new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
- }
+ nl_double new_V[2];
+ new_V[1] = (a * RHS(1) - c * RHS(0)) / (a * d - b * c);
+ new_V[0] = (RHS(0) - b * new_V[1]) / a;
- };
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
+ store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
-} //namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_DIRECT2_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_direct_lu.h b/src/lib/netlist/solver/nld_ms_direct_lu.h
index e7cedc1dd29..c379cf8d055 100644
--- a/src/lib/netlist/solver/nld_ms_direct_lu.h
+++ b/src/lib/netlist/solver/nld_ms_direct_lu.h
@@ -8,11 +8,11 @@
#ifndef NLD_MS_DIRECT_H_
#define NLD_MS_DIRECT_H_
+#include <algorithm>
+
#include "solver/nld_solver.h"
#include "solver/nld_matrix_solver.h"
-#include <algorithm>
-
//#define A(r, c) m_A[_r][_c]
namespace netlist
@@ -36,9 +36,9 @@ public:
virtual void vsetup(analog_net_t::list_t &nets) override;
virtual void reset() override { matrix_solver_t::reset(); }
- unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
+ inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
- int vsolve_non_dynamic(const bool newton_raphson);
+ inline int vsolve_non_dynamic(const bool newton_raphson);
protected:
virtual void add_term(int net_idx, terminal_t *term) override;
@@ -139,10 +139,12 @@ protected:
nl_double compute_next_timestep();
template <typename T1, typename T2>
- nl_ext_double &A(const T1 r, const T2 c) { return m_A[r][c]; }
+ inline nl_ext_double &A(const T1 r, const T2 c) { return m_A[r][c]; }
//nl_double m_A[storage_N][((storage_N + 7) / 8) * 8];
nl_double m_RHS[storage_N];
+ nl_double m_last_RHS[storage_N]; // right hand side - contains currents
+ nl_double m_last_V[storage_N];
terms_for_net_t *m_rails_temp;
@@ -353,6 +355,7 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
* save states
*/
save(NLNAME(m_RHS));
+ save(NLNAME(m_last_RHS));
save(NLNAME(m_last_V));
for (unsigned k = 0; k < N(); k++)
@@ -587,10 +590,13 @@ unsigned matrix_solver_direct_t<m_N, storage_N>::solve_non_dynamic(const bool ne
}
template <unsigned m_N, unsigned storage_N>
-int matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+inline int matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
this->build_LE_A();
- this->build_LE_RHS(m_RHS);
+ this->build_LE_RHS(m_last_RHS);
+
+ for (unsigned i=0, iN=N(); i < iN; i++)
+ m_RHS[i] = m_last_RHS[i];
return this->solve_non_dynamic(newton_raphson);
}
@@ -602,6 +608,11 @@ matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(const solver_para
, m_lp_fact(0)
{
m_rails_temp = palloc_array(terms_for_net_t, N());
+
+ for (unsigned k = 0; k < N(); k++)
+ {
+ m_last_RHS[k] = 0.0;
+ }
}
template <unsigned m_N, unsigned storage_N>
@@ -615,6 +626,7 @@ matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(const eSolverType
for (unsigned k = 0; k < N(); k++)
{
m_terms[k] = palloc(terms_for_net_t);
+ m_last_RHS[k] = 0.0;
}
}
diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h
index f3e56a342d6..a17ca1ec282 100644
--- a/src/lib/netlist/solver/nld_ms_gcr.h
+++ b/src/lib/netlist/solver/nld_ms_gcr.h
@@ -10,201 +10,390 @@
#ifndef NLD_MS_GCR_H_
#define NLD_MS_GCR_H_
-#include "plib/mat_cr.h"
+#include <algorithm>
+#include "../plib/pdynlib.h"
+#include "mat_cr.h"
#include "nld_ms_direct.h"
#include "nld_solver.h"
-#include "plib/pdynlib.h"
-#include "plib/pstream.h"
-#include "plib/vector_ops.h"
-
-#include <algorithm>
+#include "vector_base.h"
+#include "../plib/pstream.h"
namespace netlist
{
-namespace devices
+ namespace devices
+ {
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_GCR_t: public matrix_solver_t
{
+public:
+
+ matrix_solver_GCR_t(netlist_t &anetlist, const pstring &name,
+ const solver_parameters_t *params, const std::size_t size)
+ : matrix_solver_t(anetlist, name, matrix_solver_t::ASCENDING, params)
+ , m_dim(size)
+ , mat(size)
+ , m_proc()
+ {
+ }
- template <typename FT, int SIZE>
- class matrix_solver_GCR_t: public matrix_solver_t
+ virtual ~matrix_solver_GCR_t() override
{
- public:
-
- using mat_type = plib::matrix_compressed_rows_t<FT, SIZE>;
- // FIXME: dirty hack to make this compile
- static constexpr const std::size_t storage_N = 100;
-
- matrix_solver_GCR_t(netlist_state_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_t(anetlist, name, matrix_solver_t::PREFER_IDENTITY_TOP_LEFT, params)
- , m_dim(size)
- , RHS(size)
- , new_V(size)
- , mat(static_cast<typename mat_type::index_type>(size))
- , m_proc()
- {
- }
+ }
+
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
- constexpr std::size_t N() const { return m_dim; }
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- void vsetup(analog_net_t::list_t &nets) override;
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ virtual std::pair<pstring, pstring> create_solver_code() override;
- std::pair<pstring, pstring> create_solver_code() override;
+private:
- private:
+ //typedef typename mat_cr_t<storage_N>::type mattype;
+ typedef typename mat_cr_t<storage_N>::index_type mattype;
- using mat_index_type = typename plib::matrix_compressed_rows_t<FT, SIZE>::index_type;
+ void csc_private(plib::putf8_fmt_writer &strm);
- void csc_private(plib::putf8_fmt_writer &strm);
+ using extsolver = void (*)(double * RESTRICT m_A, double * RESTRICT RHS, double * RESTRICT V);
- using extsolver = void (*)(double * m_A, double * RHS, double * V);
+ pstring static_compile_name();
- pstring static_compile_name();
+ const std::size_t m_dim;
+ std::vector<unsigned> m_term_cr[storage_N];
+ mat_cr_t<storage_N> mat;
- const std::size_t m_dim;
- plib::parray<FT, SIZE> RHS;
- plib::parray<FT, SIZE> new_V;
+ //extsolver m_proc;
+ plib::dynproc<void, double * RESTRICT, double * RESTRICT, double * RESTRICT> m_proc;
- mat_type mat;
+};
- //extsolver m_proc;
- plib::dynproc<void, double * , double * , double * > m_proc;
+// ----------------------------------------------------------------------------------------
+// matrix_solver - GCR
+// ----------------------------------------------------------------------------------------
+
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
+{
+ setup_base(nets);
- };
+ mattype nz = 0;
+ const std::size_t iN = this->N();
- // ----------------------------------------------------------------------------------------
- // matrix_solver - GCR
- // ----------------------------------------------------------------------------------------
+ /* build the final matrix */
- // FIXME: namespace or static class member
- template <typename V>
- std::size_t inline get_level(const V &v, std::size_t k)
+ bool touched[storage_N][storage_N] = { { false } };
+ for (std::size_t k = 0; k < iN; k++)
{
- for (std::size_t i = 0; i < v.size(); i++)
- if (plib::container::contains(v[i], k))
- return i;
- throw plib::pexception("Error in get_level");
+ for (auto &j : this->m_terms[k]->m_nz)
+ touched[k][j] = true;
}
- template <typename FT, int SIZE>
- void matrix_solver_GCR_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
- {
- setup_base(nets);
+ unsigned fc = 0;
- const std::size_t iN = this->N();
+ unsigned ops = 0;
- /* build the final matrix */
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ ops++; // 1/A(k,k)
+ for (std::size_t row = k + 1; row < iN; row++)
+ {
+ if (touched[row][k])
+ {
+ ops++;
+ fc++;
+ for (std::size_t col = k + 1; col < iN; col++)
+ if (touched[k][col])
+ {
+ touched[row][col] = true;
+ ops += 2;
+ }
+ }
+ }
+ }
- std::vector<std::vector<unsigned>> fill(iN);
- std::size_t raw_elements = 0;
+ for (mattype k=0; k<iN; k++)
+ {
+ mat.ia[k] = nz;
- for (std::size_t k = 0; k < iN; k++)
+ for (mattype j=0; j<iN; j++)
{
- fill[k].resize(iN, decltype(mat)::FILL_INFINITY);
- for (auto &j : this->m_terms[k]->m_nz)
+ if (touched[k][j])
{
- fill[k][j] = 0;
- raw_elements++;
+ mat.ja[nz] = j;
+ if (j == k)
+ mat.diag[k] = nz;
+ nz++;
}
+ }
+ m_term_cr[k].clear();
+ /* build pointers into the compressed row format matrix for each terminal */
+ for (std::size_t j=0; j< this->m_terms[k]->m_railstart;j++)
+ {
+ int other = this->m_terms[k]->connected_net_idx()[j];
+ for (auto i = mat.ia[k]; i < nz; i++)
+ if (other == static_cast<int>(mat.ja[i]))
+ {
+ m_term_cr[k].push_back(i);
+ break;
+ }
}
+ nl_assert(m_term_cr[k].size() == this->m_terms[k]->m_railstart);
+ }
- auto gr = mat.gaussian_extend_fill_mat(fill);
+ mat.ia[iN] = nz;
+ mat.nz_num = nz;
- /* FIXME: move this to the cr matrix class and use computed
- * parallel ordering once it makes sense.
- */
+ this->log().verbose("Ops: {1} Occupancy ratio: {2}\n", ops,
+ static_cast<double>(nz) / static_cast<double>(iN * iN));
+
+ // FIXME: Move me
+
+ if (netlist().lib().isLoaded())
+ {
+ pstring symname = static_compile_name();
+#if 0
+ m_proc = this->netlist().lib().template getsym<extsolver>(symname);
+ if (m_proc != nullptr)
+ this->log().verbose("External static solver {1} found ...", symname);
+ else
+ this->log().warning("External static solver {1} not found ...", symname);
+#else
+ m_proc.load(this->netlist().lib(), symname);
+ if (m_proc.resolved())
+ this->log().warning("External static solver {1} found ...", symname);
+ else
+ this->log().warning("External static solver {1} not found ...", symname);
+#endif
+ }
- std::vector<unsigned> levL(iN, 0);
- std::vector<unsigned> levU(iN, 0);
+}
+#if 0
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &strm)
+{
+ const std::size_t iN = N();
+ for (std::size_t i = 0; i < iN - 1; i++)
+ {
+ const auto &nzbd = this->m_terms[i]->m_nzbd;
- // parallel scheme for L x = y
- for (std::size_t k = 0; k < iN; k++)
+ if (nzbd.size() > 0)
{
- unsigned lm=0;
- for (std::size_t j = 0; j<k; j++)
- if (fill[k][j] < decltype(mat)::FILL_INFINITY)
- lm = std::max(lm, levL[j]);
- levL[k] = 1+lm;
+ std::size_t pi = mat.diag[i];
+
+ //const nl_double f = 1.0 / m_A[pi++];
+ strm("const double f{1} = 1.0 / m_A[{2}];\n", i, pi);
+ pi++;
+ const std::size_t piie = mat.ia[i+1];
+
+ //for (auto & j : nzbd)
+ for (std::size_t j : nzbd)
+ {
+ // proceed to column i
+ std::size_t pj = mat.ia[j];
+
+ while (mat.ja[pj] < i)
+ pj++;
+
+ //const nl_double f1 = - m_A[pj++] * f;
+ strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];\n", i, j, i, pj);
+ pj++;
+
+ // subtract row i from j */
+ for (std::size_t pii = pi; pii<piie; )
+ {
+ while (mat.ja[pj] < mat.ja[pii])
+ pj++;
+ //m_A[pj++] += m_A[pii++] * f1;
+ strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};\n", pj, pii, i, j);
+ pj++; pii++;
+ }
+ //RHS[j] += f1 * RHS[i];
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
+ }
}
+ }
- // parallel scheme for U x = y
- for (std::size_t k = iN; k-- > 0; )
+ //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
+ strm("\tV[{1}] = RHS[{2}] / m_A[{3}];\n", iN - 1, iN - 1, mat.diag[iN - 1]);
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ strm("\tdouble tmp{1} = 0.0;\n", j);
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
{
- unsigned lm=0;
- for (std::size_t j = iN; --j > k; )
- if (fill[k][j] < decltype(mat)::FILL_INFINITY)
- lm = std::max(lm, levU[j]);
- levU[k] = 1+lm;
+ strm("\ttmp{1} += m_A[{2}] * V[{3}];\n", j, pk, mat.ja[pk]);
}
+ strm("\tV[{1}] = (RHS[{1}] - tmp{1}) / m_A[{4}];\n", j, j, j, mat.diag[j]);
+ }
+}
+#else
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &strm)
+{
+ const std::size_t iN = N();
+ for (std::size_t i = 0; i < mat.nz_num; i++)
+ strm("double m_A{1} = m_A[{2}];\n", i, i);
- for (std::size_t k = 0; k < iN; k++)
+ for (std::size_t i = 0; i < iN - 1; i++)
+ {
+ const auto &nzbd = this->m_terms[i]->m_nzbd;
+
+ if (nzbd.size() > 0)
{
- unsigned fm = 0;
- pstring ml = "";
- for (std::size_t j = 0; j < iN; j++)
+ std::size_t pi = mat.diag[i];
+
+ //const nl_double f = 1.0 / m_A[pi++];
+ strm("const double f{1} = 1.0 / m_A{2};\n", i, pi);
+ pi++;
+ const std::size_t piie = mat.ia[i+1];
+
+ //for (auto & j : nzbd)
+ for (std::size_t j : nzbd)
{
- ml += fill[k][j] == 0 ? "X" : fill[k][j] < decltype(mat)::FILL_INFINITY ? "+" : ".";
- if (fill[k][j] < decltype(mat)::FILL_INFINITY)
- if (fill[k][j] > fm)
- fm = fill[k][j];
+ // proceed to column i
+ std::size_t pj = mat.ia[j];
+
+ while (mat.ja[pj] < i)
+ pj++;
+
+ //const nl_double f1 = - m_A[pj++] * f;
+ strm("\tconst double f{1}_{2} = -f{3} * m_A{4};\n", i, j, i, pj);
+ pj++;
+
+ // subtract row i from j */
+ for (std::size_t pii = pi; pii<piie; )
+ {
+ while (mat.ja[pj] < mat.ja[pii])
+ pj++;
+ //m_A[pj++] += m_A[pii++] * f1;
+ strm("\tm_A{1} += m_A{2} * f{3}_{4};\n", pj, pii, i, j);
+ pj++; pii++;
+ }
+ //RHS[j] += f1 * RHS[i];
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
}
- this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml, levL[k], levU[k], get_level(mat.m_ge_par, k), fm);
}
+ }
+
+ //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
+ strm("\tV[{1}] = RHS[{2}] / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ strm("\tdouble tmp{1} = 0.0;\n", j);
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
+ {
+ strm("\ttmp{1} += m_A{2} * V[{3}];\n", j, pk, mat.ja[pk]);
+ }
+ strm("\tV[{1}] = (RHS[{1}] - tmp{1}) / m_A{4};\n", j, j, j, mat.diag[j]);
+ }
+}
+#endif
+
+template <std::size_t m_N, std::size_t storage_N>
+pstring matrix_solver_GCR_t<m_N, storage_N>::static_compile_name()
+{
+ plib::postringstream t;
+ plib::putf8_fmt_writer w(t);
+ csc_private(w);
+ std::hash<pstring> h;
+
+ return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+std::pair<pstring, pstring> matrix_solver_GCR_t<m_N, storage_N>::create_solver_code()
+{
+ plib::postringstream t;
+ plib::putf8_fmt_writer strm(t);
+ pstring name = static_compile_name();
+
+ strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS, double * __restrict V)\n")(name));
+ strm.writeline("{\n");
+ csc_private(strm);
+ strm.writeline("}\n");
+ return std::pair<pstring, pstring>(name, t.str());
+}
- mat.build_from_fill_mat(fill);
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+{
+ const std::size_t iN = this->N();
+
+ nl_double RHS[storage_N];
+ nl_double new_V[storage_N];
- for (mat_index_type k=0; k<iN; k++)
+ mat.set_scalar(0.0);
+
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ terms_for_net_t *t = this->m_terms[k].get();
+ nl_double gtot_t = 0.0;
+ nl_double RHS_t = 0.0;
+
+ const std::size_t term_count = t->count();
+ const std::size_t railstart = t->m_railstart;
+ const nl_double * const RESTRICT gt = t->gt();
+ const nl_double * const RESTRICT go = t->go();
+ const nl_double * const RESTRICT Idr = t->Idr();
+ const nl_double * const * RESTRICT other_cur_analog = t->connected_net_V();
+ const unsigned * const RESTRICT tcr = m_term_cr[k].data();
+
+#if 0
+ for (std::size_t i = 0; i < term_count; i++)
{
- 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]->m_railstart;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++)
- if (other == static_cast<int>(mat.col_idx[i]))
- {
- m_mat_ptr[k][j] = &mat.A[i];
- cnt++;
- break;
- }
- }
- nl_assert(cnt == this->m_terms[k]->m_railstart);
- m_mat_ptr[k][this->m_terms[k]->m_railstart] = &mat.A[mat.diag[k]];
+ gtot_t += gt[i];
+ RHS_t += Idr[i];
}
- this->log().verbose("maximum fill: {1}", gr.first);
- this->log().verbose("Post elimination occupancy ratio: {2} Ops: {1}", gr.second,
- static_cast<double>(mat.nz_num) / static_cast<double>(iN * iN));
- this->log().verbose(" Pre elimination occupancy ratio: {2}",
- static_cast<double>(raw_elements) / static_cast<double>(iN * iN));
+ for (std::size_t i = railstart; i < term_count; i++)
+ RHS_t += go[i] * *other_cur_analog[i];
- // FIXME: Move me
+ RHS[k] = RHS_t;
- if (state().lib().isLoaded())
+ // add diagonal element
+ mat.A[mat.diag[k]] = gtot_t;
+
+ for (std::size_t i = 0; i < railstart; i++)
+ mat.A[tcr[i]] -= go[i];
+ }
+#else
+ for (std::size_t i = 0; i < railstart; i++)
+ mat.A[tcr[i]] -= go[i];
+
+ for (std::size_t i = 0; i < railstart; i++)
{
- pstring symname = static_compile_name();
- m_proc.load(this->state().lib(), symname);
- if (m_proc.resolved())
- this->log().warning("External static solver {1} found ...", symname);
- else
- this->log().warning("External static solver {1} not found ...", symname);
+ gtot_t += gt[i];
+ RHS_t += Idr[i];
}
- }
+ for (std::size_t i = railstart; i < term_count; i++)
+ {
+ RHS_t += (Idr[i] + go[i] * *other_cur_analog[i]);
+ gtot_t += gt[i];
+ }
- template <typename FT, int SIZE>
- void matrix_solver_GCR_t<FT, SIZE>::csc_private(plib::putf8_fmt_writer &strm)
- {
- const std::size_t iN = N();
+ RHS[k] = RHS_t;
+ mat.A[mat.diag[k]] += gtot_t;
+ }
+#endif
+ mat.ia[iN] = static_cast<mattype>(mat.nz_num);
- for (std::size_t i = 0; i < mat.nz_num; i++)
- strm("double m_A{1} = m_A[{2}];\n", i, i);
+ /* now solve it */
+ //if (m_proc != nullptr)
+ if (m_proc.resolved())
+ {
+ //static_solver(m_A, RHS);
+ m_proc(&mat.A[0], &RHS[0], &new_V[0]);
+ }
+ else
+ {
for (std::size_t i = 0; i < iN - 1; i++)
{
const auto &nzbd = this->m_terms[i]->m_nzbd;
@@ -212,114 +401,61 @@ namespace devices
if (nzbd.size() > 0)
{
std::size_t pi = mat.diag[i];
+ const nl_double f = 1.0 / mat.A[pi++];
+ const std::size_t piie = mat.ia[i+1];
- //const FT f = 1.0 / m_A[pi++];
- strm("const double f{1} = 1.0 / m_A{2};\n", i, pi);
- pi++;
- const std::size_t piie = mat.row_idx[i+1];
-
- //for (auto & j : nzbd)
- for (std::size_t j : nzbd)
+ for (std::size_t j : nzbd) // for (std::size_t j = i + 1; j < iN; j++)
{
// proceed to column i
- std::size_t pj = mat.row_idx[j];
+ //__builtin_prefetch(&m_A[mat.diag[j+1]], 1);
+ std::size_t pj = mat.ia[j];
- while (mat.col_idx[pj] < i)
+ while (mat.ja[pj] < i)
pj++;
- //const FT f1 = - m_A[pj++] * f;
- strm("\tconst double f{1}_{2} = -f{3} * m_A{4};\n", i, j, i, pj);
- pj++;
+ const nl_double f1 = - mat.A[pj++] * f;
// subtract row i from j */
for (std::size_t pii = pi; pii<piie; )
{
- while (mat.col_idx[pj] < mat.col_idx[pii])
+ while (mat.ja[pj] < mat.ja[pii])
pj++;
- //m_A[pj++] += m_A[pii++] * f1;
- strm("\tm_A{1} += m_A{2} * f{3}_{4};\n", pj, pii, i, j);
- pj++; pii++;
+ mat.A[pj++] += mat.A[pii++] * f1;
}
- //RHS[j] += f1 * RHS[i];
- strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
+ RHS[j] += f1 * RHS[i];
}
}
}
+ /* backward substitution
+ *
+ */
+
+ /* row n-1 */
+ new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
- //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
- strm("\tV[{1}] = RHS[{2}] / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
for (std::size_t j = iN - 1; j-- > 0;)
{
- strm("\tdouble tmp{1} = 0.0;\n", j);
- const std::size_t e = mat.row_idx[j+1];
- for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
+ //__builtin_prefetch(&new_V[j-1], 1);
+ //if (j>0)__builtin_prefetch(&m_A[mat.diag[j-1]], 0);
+ double tmp = 0;
+ auto jdiag = mat.diag[j];
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = jdiag + 1; pk < e; pk++)
{
- strm("\ttmp{1} += m_A{2} * V[{3}];\n", j, pk, mat.col_idx[pk]);
+ tmp += mat.A[pk] * new_V[mat.ja[pk]];
}
- strm("\tV[{1}] = (RHS[{1}] - tmp{1}) / m_A{4};\n", j, j, j, mat.diag[j]);
+ new_V[j] = (RHS[j] - tmp) / mat.A[jdiag];
}
}
- template <typename FT, int SIZE>
- pstring matrix_solver_GCR_t<FT, SIZE>::static_compile_name()
- {
- plib::postringstream t;
- plib::putf8_fmt_writer w(&t);
- csc_private(w);
- std::hash<pstring> h;
-
- return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
- }
+ this->m_stat_calculations++;
- template <typename FT, int SIZE>
- std::pair<pstring, pstring> matrix_solver_GCR_t<FT, SIZE>::create_solver_code()
- {
- plib::postringstream t;
- plib::putf8_fmt_writer strm(&t);
- pstring name = static_compile_name();
-
- strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS, double * __restrict V)\n")(name));
- strm.writeline("{\n");
- csc_private(strm);
- strm.writeline("}\n");
- return std::pair<pstring, pstring>(name, t.str());
- }
-
- template <typename FT, int SIZE>
- unsigned matrix_solver_GCR_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
- {
- const std::size_t iN = this->N();
-
- mat.set_scalar(0.0);
-
- /* populate matrix */
-
- this->fill_matrix(iN, m_mat_ptr, RHS);
-
- /* now solve it */
-
- //if (m_proc != nullptr)
- if (m_proc.resolved())
- {
- //static_solver(m_A, RHS);
- m_proc(&mat.A[0], &RHS[0], &new_V[0]);
- }
- else
- {
- // mat.gaussian_elimination_parallel(RHS);
- mat.gaussian_elimination(RHS);
- /* backward substitution */
- mat.gaussian_back_substitution(new_V, RHS);
- }
-
- this->m_stat_calculations++;
-
- const FT err = (newton_raphson ? delta(new_V) : 0.0);
- store(new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
- }
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
+ store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
-} // namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_GCR_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h
index 2ff515ebda7..2e4e447d14f 100644
--- a/src/lib/netlist/solver/nld_ms_gmres.h
+++ b/src/lib/netlist/solver/nld_ms_gmres.h
@@ -1,145 +1,387 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
- * nld_ms_gmres.h
+ * nld_ms_sor.h
+ *
+ * Generic successive over relaxation solver.
+ *
+ * Fow w==1 we will do the classic Gauss-Seidel approach
*
*/
#ifndef NLD_MS_GMRES_H_
#define NLD_MS_GMRES_H_
-#include "nld_ms_direct.h"
-#include "nld_solver.h"
-#include "plib/gmres.h"
-#include "plib/mat_cr.h"
-#include "plib/parray.h"
-#include "plib/vector_ops.h"
-
#include <algorithm>
-#include <cmath>
+#include "mat_cr.h"
+#include "nld_ms_direct.h"
+#include "nld_solver.h"
+#include "vector_base.h"
namespace netlist
{
-namespace devices
+ namespace devices
+ {
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_GMRES_t: public matrix_solver_direct_t<m_N, storage_N>
{
+public:
+
+ matrix_solver_GMRES_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
+ : matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
+ , m_use_iLU_preconditioning(true)
+ , m_use_more_precise_stop_condition(false)
+ , m_accuracy_mult(1.0)
+ , mat(size)
+ {
+ }
- template <typename FT, int SIZE>
- class matrix_solver_GMRES_t: public matrix_solver_direct_t<FT, SIZE>
+ virtual ~matrix_solver_GMRES_t() override
{
- public:
+ }
- using float_type = FT;
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- /* Sort rows in ascending order. This should minimize fill-in and thus
- * maximize the efficiency of the incomplete LUT.
- * This is already preconditioning.
- */
- matrix_solver_GMRES_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_solver_t::PREFER_BAND_MATRIX, params, size)
- //, m_ops(size, 2)
- , m_ops(size, 4)
- , m_gmres(size)
- {
- }
+private:
+
+ //typedef typename mat_cr_t<storage_N>::type mattype;
+ typedef typename mat_cr_t<storage_N>::index_type mattype;
+
+ unsigned solve_ilu_gmres(nl_double (& RESTRICT x)[storage_N], const nl_double (& RESTRICT rhs)[storage_N], const unsigned restart_max, std::size_t mr, nl_double accuracy);
+
+ std::vector<unsigned> m_term_cr[storage_N];
+
+ bool m_use_iLU_preconditioning;
+ bool m_use_more_precise_stop_condition;
+ nl_double m_accuracy_mult; // FXIME: Save state
- void vsetup(analog_net_t::list_t &nets) override;
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ mat_cr_t<storage_N> mat;
- private:
+ nl_double m_LU[storage_N * storage_N];
- using mattype = typename plib::matrix_compressed_rows_t<FT, SIZE>::index_type;
+ nl_double m_c[storage_N + 1]; /* mr + 1 */
+ nl_double m_g[storage_N + 1]; /* mr + 1 */
+ nl_double m_ht[storage_N + 1][storage_N]; /* (mr + 1), mr */
+ nl_double m_s[storage_N + 1]; /* mr + 1 */
+ nl_double m_v[storage_N + 1][storage_N]; /*(mr + 1), n */
+ nl_double m_y[storage_N + 1]; /* mr + 1 */
- plib::mat_precondition_ILU<FT, SIZE> m_ops;
- plib::gmres_t<FT, SIZE> m_gmres;
- };
+};
- // ----------------------------------------------------------------------------------------
- // matrix_solver - GMRES
- // ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// matrix_solver - GMRES
+// ----------------------------------------------------------------------------------------
- template <typename FT, int SIZE>
- void matrix_solver_GMRES_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GMRES_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
+{
+ matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
+
+ mattype nz = 0;
+ const std::size_t iN = this->N();
+
+ for (std::size_t k=0; k<iN; k++)
{
- matrix_solver_direct_t<FT, SIZE>::vsetup(nets);
+ terms_for_net_t * RESTRICT row = this->m_terms[k].get();
+ mat.ia[k] = nz;
- const std::size_t iN = this->size();
+ for (std::size_t j=0; j<row->m_nz.size(); j++)
+ {
+ mat.ja[nz] = static_cast<mattype>(row->m_nz[j]);
+ if (row->m_nz[j] == k)
+ mat.diag[k] = nz;
+ nz++;
+ }
- std::vector<std::vector<unsigned>> fill(iN);
+ /* build pointers into the compressed row format matrix for each terminal */
- for (std::size_t k=0; k<iN; k++)
+ for (unsigned j=0; j< this->m_terms[k]->m_railstart;j++)
{
- fill[k].resize(iN, decltype(m_ops.m_mat)::FILL_INFINITY);
- terms_for_net_t * row = this->m_terms[k].get();
- for (const auto &nz_j : row->m_nz)
- {
- fill[k][static_cast<mattype>(nz_j)] = 0;
- }
+ for (unsigned i = mat.ia[k]; i<nz; i++)
+ if (this->m_terms[k]->connected_net_idx()[j] == static_cast<int>(mat.ja[i]))
+ {
+ m_term_cr[k].push_back(i);
+ break;
+ }
+ nl_assert(m_term_cr[k].size() == this->m_terms[k]->m_railstart);
}
+ }
- m_ops.build(fill);
+ mat.ia[iN] = nz;
+ mat.nz_num = nz;
+}
- /* build pointers into the compressed row format matrix for each terminal */
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+{
+ const std::size_t iN = this->N();
+
+ /* ideally, we could get an estimate for the spectral radius of
+ * Inv(D - L) * U
+ *
+ * and estimate using
+ *
+ * omega = 2.0 / (1.0 + std::sqrt(1-rho))
+ */
- for (std::size_t k=0; k<iN; k++)
+ //nz_num = 0;
+ nl_double RHS[storage_N];
+ nl_double new_V[storage_N];
+
+ mat.set_scalar(0.0);
+
+ for (std::size_t k = 0; k < iN; k++)
+ {
+ nl_double gtot_t = 0.0;
+ nl_double RHS_t = 0.0;
+
+ const std::size_t term_count = this->m_terms[k]->count();
+ const std::size_t railstart = this->m_terms[k]->m_railstart;
+ const nl_double * const RESTRICT gt = this->m_terms[k]->gt();
+ const nl_double * const RESTRICT go = this->m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
+ const nl_double * const * RESTRICT other_cur_analog = this->m_terms[k]->connected_net_V();
+
+ for (std::size_t i = 0; i < term_count; i++)
{
- std::size_t cnt = 0;
- for (std::size_t j=0; j< this->m_terms[k]->m_railstart;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]))
- {
- this->m_mat_ptr[k][j] = &m_ops.m_mat.A[i];
- cnt++;
- break;
- }
- }
- nl_assert(cnt == this->m_terms[k]->m_railstart);
- this->m_mat_ptr[k][this->m_terms[k]->m_railstart] = &m_ops.m_mat.A[m_ops.m_mat.diag[k]];
+ gtot_t = gtot_t + gt[i];
+ RHS_t = RHS_t + Idr[i];
}
+
+ for (std::size_t i = railstart; i < term_count; i++)
+ RHS_t = RHS_t + go[i] * *other_cur_analog[i];
+
+ RHS[k] = RHS_t;
+
+ // add diagonal element
+ mat.A[mat.diag[k]] = gtot_t;
+
+ for (std::size_t i = 0; i < railstart; i++)
+ {
+ const std::size_t pi = m_term_cr[k][i];
+ mat.A[pi] -= go[i];
+ }
+
+ new_V[k] = this->m_nets[k]->Q_Analog();
+
}
+ mat.ia[iN] = static_cast<mattype>(mat.nz_num);
+
+ const nl_double accuracy = this->m_params.m_accuracy;
+
+ unsigned mr = iN;
+ if (iN > 3 )
+ mr = static_cast<unsigned>(std::sqrt(iN) * 2.0);
+ unsigned iter = std::max(1u, this->m_params.m_gs_loops);
+ unsigned gsl = solve_ilu_gmres(new_V, RHS, iter, mr, accuracy);
+ unsigned failed = mr * iter;
- template <typename FT, int SIZE>
- unsigned matrix_solver_GMRES_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
+ this->m_iterative_total += gsl;
+ this->m_stat_calculations++;
+
+ if (gsl>=failed)
+ {
+ this->m_iterative_fail++;
+ return matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(newton_raphson);
+ }
+
+ const nl_double err = (newton_raphson ? this->delta(new_V) : 0.0);
+ this->store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
+
+template <typename T>
+inline static void givens_mult( const T c, const T s, T & g0, T & g1 )
+{
+ const T tg0 = c * g0 - s * g1;
+ const T tg1 = s * g0 + c * g1;
+
+ g0 = tg0;
+ g1 = tg1;
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double (& RESTRICT x)[storage_N], const nl_double (& RESTRICT rhs)[storage_N], const unsigned restart_max, std::size_t mr, nl_double accuracy)
+{
+ /*-------------------------------------------------------------------------
+ * The code below was inspired by code published by John Burkardt under
+ * the LPGL here:
+ *
+ * http://people.sc.fsu.edu/~jburkardt/cpp_src/mgmres/mgmres.html
+ *
+ * The code below was completely written from scratch based on the pseudo code
+ * found here:
+ *
+ * http://de.wikipedia.org/wiki/GMRES-Verfahren
+ *
+ * The Algorithm itself is described in
+ *
+ * Yousef Saad,
+ * Iterative Methods for Sparse Linear Systems,
+ * Second Edition,
+ * SIAM, 20003,
+ * ISBN: 0898715342,
+ * LC: QA188.S17.
+ *
+ *------------------------------------------------------------------------*/
+
+ unsigned itr_used = 0;
+ double rho_delta = 0.0;
+
+ const std::size_t n = this->N();
+
+ if (mr > n) mr = n;
+
+ if (m_use_iLU_preconditioning)
+ mat.incomplete_LU_factorization(m_LU);
+
+ if (m_use_more_precise_stop_condition)
{
- const std::size_t iN = this->size();
+ /* derive residual for a given delta x
+ *
+ * LU y = A dx
+ *
+ * ==> rho / accuracy = sqrt(y * y)
+ *
+ * This approach will approximate the iterative stop condition
+ * based |xnew - xold| pretty precisely. But it is slow, or expressed
+ * differently: The invest doesn't pay off.
+ * Therefore we use the approach in the else part.
+ */
+ nl_double t[storage_N];
+ nl_double Ax[storage_N];
+ vec_set(n, accuracy, t);
+ mat.mult_vec(t, Ax);
+
+ mat.solveLUx(m_LU, Ax);
+
+ const nl_double rho_to_accuracy = std::sqrt(vec_mult2(n, Ax)) / accuracy;
+
+ rho_delta = accuracy * rho_to_accuracy;
+ }
+ else
+ rho_delta = accuracy * std::sqrt(n) * m_accuracy_mult;
+
+ for (unsigned itr = 0; itr < restart_max; itr++)
+ {
+ std::size_t last_k = mr;
+ nl_double rho;
+
+ nl_double Ax[storage_N];
+ nl_double residual[storage_N];
+
+ mat.mult_vec(x, Ax);
+
+ vec_sub(n, rhs, Ax, residual);
+
+ if (m_use_iLU_preconditioning)
+ {
+ mat.solveLUx(m_LU, residual);
+ }
+
+ rho = std::sqrt(vec_mult2(n, residual));
- plib::parray<FT, SIZE> RHS(iN);
- //float_type new_V[storage_N];
+ if (rho < rho_delta)
+ return itr_used + 1;
- m_ops.m_mat.set_scalar(0.0);
+ vec_set(mr+1, NL_FCONST(0.0), m_g);
+ m_g[0] = rho;
- /* populate matrix and V for first estimate */
- this->fill_matrix(iN, this->m_mat_ptr, RHS);
+ for (std::size_t i = 0; i < mr; i++)
+ vec_set(mr + 1, NL_FCONST(0.0), m_ht[i]);
- for (std::size_t k = 0; k < iN; k++)
+ vec_mult_scalar(n, residual, NL_FCONST(1.0) / rho, m_v[0]);
+
+ for (std::size_t k = 0; k < mr; k++)
{
- this->m_new_V[k] = this->m_nets[k]->Q_Analog();
+ const std::size_t k1 = k + 1;
+
+ mat.mult_vec(m_v[k], m_v[k1]);
+
+ if (m_use_iLU_preconditioning)
+ mat.solveLUx(m_LU, m_v[k1]);
+
+ for (std::size_t j = 0; j <= k; j++)
+ {
+ m_ht[j][k] = vec_mult(n, m_v[k1], m_v[j]);
+ vec_add_mult_scalar(n, m_v[j], -m_ht[j][k], m_v[k1]);
+ }
+ m_ht[k1][k] = std::sqrt(vec_mult2(n, m_v[k1]));
+
+ if (m_ht[k1][k] != 0.0)
+ vec_scale(n, m_v[k1], NL_FCONST(1.0) / m_ht[k1][k]);
+
+ for (std::size_t j = 0; j < k; j++)
+ givens_mult(m_c[j], m_s[j], m_ht[j][k], m_ht[j+1][k]);
+
+ const nl_double mu = 1.0 / std::hypot(m_ht[k][k], m_ht[k1][k]);
+
+ m_c[k] = m_ht[k][k] * mu;
+ m_s[k] = -m_ht[k1][k] * mu;
+ m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[k1][k];
+ m_ht[k1][k] = 0.0;
+
+ givens_mult(m_c[k], m_s[k], m_g[k], m_g[k1]);
+
+ rho = std::abs(m_g[k1]);
+
+ itr_used = itr_used + 1;
+
+ if (rho <= rho_delta)
+ {
+ last_k = k;
+ break;
+ }
}
- const float_type accuracy = this->m_params.m_accuracy;
+ if (last_k >= mr)
+ /* didn't converge within accuracy */
+ last_k = mr - 1;
- auto iter = std::max(plib::constants<std::size_t>::one(), this->m_params.m_gs_loops);
- auto gsl = m_gmres.solve(m_ops, this->m_new_V, RHS, iter, accuracy);
+ /* Solve the system H * y = g */
+ /* x += m_v[j] * m_y[j] */
+ for (std::size_t i = last_k + 1; i-- > 0;)
+ {
+ double tmp = m_g[i];
+ for (std::size_t j = i + 1; j <= last_k; j++)
+ {
+ tmp -= m_ht[i][j] * m_y[j];
+ }
+ m_y[i] = tmp / m_ht[i][i];
+ }
+
+ for (std::size_t i = 0; i <= last_k; i++)
+ vec_add_mult_scalar(n, m_v[i], m_y[i], x);
- this->m_iterative_total += gsl;
- this->m_stat_calculations++;
+#if 1
+ if (rho <= rho_delta)
+ {
+ break;
+ }
+#else
+ /* we try to approximate the x difference between to steps using m_v[last_k] */
- if (gsl > iter)
+ double xdelta = m_y[last_k] * vec_maxabs(n, m_v[last_k]);
+ if (xdelta < accuracy)
{
- this->m_iterative_fail++;
- return matrix_solver_direct_t<FT, SIZE>::vsolve_non_dynamic(newton_raphson);
+ if (m_accuracy_mult < 16384.0)
+ m_accuracy_mult = m_accuracy_mult * 2.0;
+ break;
}
+ else
+ m_accuracy_mult = m_accuracy_mult / 2.0;
- const float_type err = (newton_raphson ? this->delta(this->m_new_V) : 0.0);
- this->store(this->m_new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
+#endif
}
+ return itr_used;
+}
-} // namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_GMRES_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h
index d85ab0044f4..ed95cd2dc03 100644
--- a/src/lib/netlist/solver/nld_ms_sm.h
+++ b/src/lib/netlist/solver/nld_ms_sm.h
@@ -33,275 +33,293 @@
#ifndef NLD_MS_SM_H_
#define NLD_MS_SM_H_
-#include "nld_matrix_solver.h"
-#include "nld_solver.h"
-#include "plib/vector_ops.h"
-
#include <algorithm>
+#include "nld_solver.h"
+#include "nld_matrix_solver.h"
+#include "vector_base.h"
+
namespace netlist
{
-namespace devices
+ namespace devices
+ {
+//#define nl_ext_double _float128 // slow, very slow
+//#define nl_ext_double long double // slightly slower
+#define nl_ext_double nl_double
+
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_sm_t: public matrix_solver_t
{
+ friend class matrix_solver_t;
- template <typename FT, int SIZE>
- class matrix_solver_sm_t: public matrix_solver_t
- {
- friend class matrix_solver_t;
+public:
- public:
+ matrix_solver_sm_t(netlist_t &anetlist, const pstring &name,
+ const solver_parameters_t *params, const std::size_t size);
- using float_ext_type = FT;
- using float_type = FT;
- // FIXME: dirty hack to make this compile
- static constexpr const std::size_t storage_N = 100;
+ virtual ~matrix_solver_sm_t() override;
- matrix_solver_sm_t(netlist_state_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const std::size_t size);
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual void reset() override { matrix_solver_t::reset(); }
- void vsetup(analog_net_t::list_t &nets) override;
- void reset() override { matrix_solver_t::reset(); }
+protected:
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ unsigned solve_non_dynamic(const bool newton_raphson);
- protected:
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- unsigned solve_non_dynamic(const bool newton_raphson);
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
- constexpr std::size_t size() const { return m_dim; }
+ void LE_invert();
- void LE_invert();
+ template <typename T>
+ void LE_compute_x(T * RESTRICT x);
- template <typename T>
- void LE_compute_x(T * x);
+ template <typename T1, typename T2>
+ nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
+ template <typename T1, typename T2>
+ nl_ext_double &W(const T1 &r, const T2 &c) { return m_W[r][c]; }
+ template <typename T1, typename T2>
+ nl_ext_double &Ainv(const T1 &r, const T2 &c) { return m_Ainv[r][c]; }
+ template <typename T1>
+ nl_ext_double &RHS(const T1 &r) { return m_RHS[r]; }
- template <typename T1, typename T2>
- float_ext_type &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
- template <typename T1, typename T2>
- float_ext_type &W(const T1 &r, const T2 &c) { return m_W[r][c]; }
- template <typename T1, typename T2>
- float_ext_type &Ainv(const T1 &r, const T2 &c) { return m_Ainv[r][c]; }
- template <typename T1>
- float_ext_type &RHS(const T1 &r) { return m_RHS[r]; }
+ template <typename T1, typename T2>
+ nl_ext_double &lA(const T1 &r, const T2 &c) { return m_lA[r][c]; }
+ template <typename T1, typename T2>
+ nl_ext_double &lAinv(const T1 &r, const T2 &c) { return m_lAinv[r][c]; }
- template <typename T1, typename T2>
- float_ext_type &lA(const T1 &r, const T2 &c) { return m_lA[r][c]; }
- template <typename T1, typename T2>
- float_ext_type &lAinv(const T1 &r, const T2 &c) { return m_lAinv[r][c]; }
+ nl_double m_last_RHS[storage_N]; // right hand side - contains currents
- private:
- static constexpr std::size_t m_pitch = ((( storage_N) + 7) / 8) * 8;
- float_ext_type m_A[storage_N][m_pitch];
- float_ext_type m_Ainv[storage_N][m_pitch];
- float_ext_type m_W[storage_N][m_pitch];
- float_ext_type m_RHS[storage_N]; // right hand side - contains currents
+private:
+ static constexpr std::size_t m_pitch = ((( storage_N) + 7) / 8) * 8;
+ nl_ext_double m_A[storage_N][m_pitch];
+ nl_ext_double m_Ainv[storage_N][m_pitch];
+ nl_ext_double m_W[storage_N][m_pitch];
+ nl_ext_double m_RHS[storage_N]; // right hand side - contains currents
- float_ext_type m_lA[storage_N][m_pitch];
- float_ext_type m_lAinv[storage_N][m_pitch];
+ nl_ext_double m_lA[storage_N][m_pitch];
+ nl_ext_double m_lAinv[storage_N][m_pitch];
- //float_ext_type m_RHSx[storage_N];
+ //nl_ext_double m_RHSx[storage_N];
- const std::size_t m_dim;
- std::size_t m_cnt;
+ const std::size_t m_dim;
+ std::size_t m_cnt;
- };
+};
- // ----------------------------------------------------------------------------------------
- // matrix_solver_direct
- // ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// matrix_solver_direct
+// ----------------------------------------------------------------------------------------
- template <typename FT, int SIZE>
- void matrix_solver_sm_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
- {
- matrix_solver_t::setup_base(nets);
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_sm_t<m_N, storage_N>::~matrix_solver_sm_t()
+{
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_sm_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
+{
+ matrix_solver_t::setup_base(nets);
+
+ netlist().save(*this, m_last_RHS, "m_last_RHS");
+
+ for (unsigned k = 0; k < N(); k++)
+ netlist().save(*this, RHS(k), plib::pfmt("RHS.{1}")(k));
+}
- /* FIXME: Shouldn't be necessary */
- for (std::size_t k = 0; k < size(); k++)
- state().save(*this, RHS(k), this->name(), plib::pfmt("RHS.{1}")(k));
- }
- template <typename FT, int SIZE>
- void matrix_solver_sm_t<FT, SIZE>::LE_invert()
- {
- const std::size_t kN = size();
- for (std::size_t i = 0; i < kN; i++)
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_sm_t<m_N, storage_N>::LE_invert()
+{
+ const std::size_t kN = N();
+
+ for (std::size_t i = 0; i < kN; i++)
+ {
+ for (std::size_t j = 0; j < kN; j++)
{
- for (std::size_t j = 0; j < kN; j++)
- {
- W(i,j) = lA(i,j) = A(i,j);
- Ainv(i,j) = 0.0;
- }
- Ainv(i,i) = 1.0;
+ W(i,j) = lA(i,j) = A(i,j);
+ Ainv(i,j) = 0.0;
}
- /* down */
- for (std::size_t i = 0; i < kN; i++)
- {
- /* FIXME: Singular matrix? */
- const float_type f = 1.0 / W(i,i);
- const auto * const p = m_terms[i]->m_nzrd.data();
- const std::size_t e = m_terms[i]->m_nzrd.size();
+ Ainv(i,i) = 1.0;
+ }
+ /* down */
+ for (std::size_t i = 0; i < kN; i++)
+ {
+ /* FIXME: Singular matrix? */
+ const nl_double f = 1.0 / W(i,i);
+ const auto * RESTRICT const p = m_terms[i]->m_nzrd.data();
+ const std::size_t e = m_terms[i]->m_nzrd.size();
- /* Eliminate column i from row j */
+ /* Eliminate column i from row j */
- const auto * const pb = m_terms[i]->m_nzbd.data();
- const std::size_t eb = m_terms[i]->m_nzbd.size();
- for (std::size_t jb = 0; jb < eb; jb++)
+ const auto * RESTRICT const pb = m_terms[i]->m_nzbd.data();
+ const std::size_t eb = m_terms[i]->m_nzbd.size();
+ for (std::size_t jb = 0; jb < eb; jb++)
+ {
+ const unsigned j = pb[jb];
+ const nl_double f1 = - W(j,i) * f;
+ if (f1 != 0.0)
{
- const unsigned j = pb[jb];
- const float_type f1 = - W(j,i) * f;
- if (f1 != 0.0)
- {
- for (std::size_t k = 0; k < e; k++)
- W(j,p[k]) += W(i,p[k]) * f1;
- for (std::size_t k = 0; k <= i; k ++)
- Ainv(j,k) += Ainv(i,k) * f1;
- }
+ for (std::size_t k = 0; k < e; k++)
+ W(j,p[k]) += W(i,p[k]) * f1;
+ for (std::size_t k = 0; k <= i; k ++)
+ Ainv(j,k) += Ainv(i,k) * f1;
}
}
- /* up */
- for (std::size_t i = kN; i-- > 0; )
+ }
+ /* up */
+ for (std::size_t i = kN; i-- > 0; )
+ {
+ /* FIXME: Singular matrix? */
+ const nl_double f = 1.0 / W(i,i);
+ for (std::size_t j = i; j-- > 0; )
{
- /* FIXME: Singular matrix? */
- const float_type f = 1.0 / W(i,i);
- for (std::size_t j = i; j-- > 0; )
+ const nl_double f1 = - W(j,i) * f;
+ if (f1 != 0.0)
{
- const float_type f1 = - W(j,i) * f;
- if (f1 != 0.0)
- {
- for (std::size_t k = i; k < kN; k++)
- W(j,k) += W(i,k) * f1;
- for (std::size_t k = 0; k < kN; k++)
- Ainv(j,k) += Ainv(i,k) * f1;
- }
- }
- for (std::size_t k = 0; k < kN; k++)
- {
- Ainv(i,k) *= f;
- lAinv(i,k) = Ainv(i,k);
+ for (std::size_t k = i; k < kN; k++)
+ W(j,k) += W(i,k) * f1;
+ for (std::size_t k = 0; k < kN; k++)
+ Ainv(j,k) += Ainv(i,k) * f1;
}
}
+ for (std::size_t k = 0; k < kN; k++)
+ {
+ Ainv(i,k) *= f;
+ lAinv(i,k) = Ainv(i,k);
+ }
}
+}
- template <typename FT, int SIZE>
- template <typename T>
- void matrix_solver_sm_t<FT, SIZE>::LE_compute_x(
- T * x)
- {
- const std::size_t kN = size();
+template <std::size_t m_N, std::size_t storage_N>
+template <typename T>
+void matrix_solver_sm_t<m_N, storage_N>::LE_compute_x(
+ T * RESTRICT x)
+{
+ const std::size_t kN = N();
- for (std::size_t i=0; i<kN; i++)
- x[i] = 0.0;
+ for (std::size_t i=0; i<kN; i++)
+ x[i] = 0.0;
- for (std::size_t k=0; k<kN; k++)
- {
- const float_type f = RHS(k);
+ for (std::size_t k=0; k<kN; k++)
+ {
+ const nl_double f = RHS(k);
- for (std::size_t i=0; i<kN; i++)
- x[i] += Ainv(i,k) * f;
- }
+ for (std::size_t i=0; i<kN; i++)
+ x[i] += Ainv(i,k) * f;
}
+}
- template <typename FT, int SIZE>
- unsigned matrix_solver_sm_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphson)
- {
- static constexpr const bool incremental = true;
- const std::size_t iN = size();
- float_type new_V[storage_N]; // = { 0.0 };
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_sm_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
+{
+ static constexpr const bool incremental = true;
+ const std::size_t iN = N();
+
+ nl_double new_V[storage_N]; // = { 0.0 };
- if ((m_cnt % 50) == 0)
+ if ((m_cnt % 50) == 0)
+ {
+ /* complete calculation */
+ this->LE_invert();
+ }
+ else
+ {
+ if (!incremental)
{
- /* complete calculation */
- this->LE_invert();
+ for (std::size_t row = 0; row < iN; row ++)
+ for (std::size_t k = 0; k < iN; k++)
+ Ainv(row,k) = lAinv(row, k);
}
- else
+ for (std::size_t row = 0; row < iN; row ++)
{
- if (!incremental)
+ nl_double v[m_pitch] = {0};
+ std::size_t cols[m_pitch];
+ std::size_t colcount = 0;
+
+ auto &nz = m_terms[row]->m_nz;
+ for (unsigned & col : nz)
{
- for (std::size_t row = 0; row < iN; row ++)
- for (std::size_t k = 0; k < iN; k++)
- Ainv(row,k) = lAinv(row, k);
+ v[col] = A(row,col) - lA(row,col);
+ if (incremental)
+ lA(row,col) = A(row,col);
+ if (v[col] != 0.0)
+ cols[colcount++] = col;
}
- for (std::size_t row = 0; row < iN; row ++)
+
+ if (colcount > 0)
{
- float_type v[m_pitch] = {0};
- std::size_t cols[m_pitch];
- std::size_t colcount = 0;
+ nl_double lamba = 0.0;
+ nl_double w[m_pitch] = {0};
+
+ nl_double z[m_pitch];
+ /* compute w and lamba */
+ for (std::size_t i = 0; i < iN; i++)
+ z[i] = Ainv(i, row); /* u is row'th column */
- auto &nz = m_terms[row]->m_nz;
- for (unsigned & col : nz)
+ for (std::size_t j = 0; j < colcount; j++)
+ lamba += v[cols[j]] * z[cols[j]];
+
+ for (std::size_t j=0; j<colcount; j++)
{
- v[col] = A(row,col) - lA(row,col);
- if (incremental)
- lA(row,col) = A(row,col);
- if (v[col] != 0.0)
- cols[colcount++] = col;
+ std::size_t col = cols[j];
+ nl_double f = v[col];
+ for (std::size_t k = 0; k < iN; k++)
+ w[k] += Ainv(col,k) * f; /* Transpose(Ainv) * v */
}
- if (colcount > 0)
+ lamba = -1.0 / (1.0 + lamba);
+ for (std::size_t i=0; i<iN; i++)
{
- float_type lamba = 0.0;
- float_type w[m_pitch] = {0};
-
- float_type z[m_pitch];
- /* compute w and lamba */
- for (std::size_t i = 0; i < iN; i++)
- z[i] = Ainv(i, row); /* u is row'th column */
-
- for (std::size_t j = 0; j < colcount; j++)
- lamba += v[cols[j]] * z[cols[j]];
-
- for (std::size_t j=0; j<colcount; j++)
- {
- std::size_t col = cols[j];
- float_type f = v[col];
+ const nl_double f = lamba * z[i];
+ if (f != 0.0)
for (std::size_t k = 0; k < iN; k++)
- w[k] += Ainv(col,k) * f; /* Transpose(Ainv) * v */
- }
-
- lamba = -1.0 / (1.0 + lamba);
- for (std::size_t i=0; i<iN; i++)
- {
- const float_type f = lamba * z[i];
- if (f != 0.0)
- for (std::size_t k = 0; k < iN; k++)
- Ainv(i,k) += f * w[k];
- }
+ Ainv(i,k) += f * w[k];
}
-
}
- }
-
- m_cnt++;
-
- this->LE_compute_x(new_V);
- const float_type err = (newton_raphson ? delta(new_V) : 0.0);
- store(new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
+ }
}
- template <typename FT, int SIZE>
- unsigned matrix_solver_sm_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
- {
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
+ m_cnt++;
- this->m_stat_calculations++;
- return this->solve_non_dynamic(newton_raphson);
- }
+ this->LE_compute_x(new_V);
+
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
+ store(new_V);
+ return (err > this->m_params.m_accuracy) ? 2 : 1;
+}
- template <typename FT, int SIZE>
- matrix_solver_sm_t<FT, SIZE>::matrix_solver_sm_t(netlist_state_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_t(anetlist, name, NOSORT, params)
- , m_dim(size)
- , m_cnt(0)
+template <std::size_t m_N, std::size_t storage_N>
+inline unsigned matrix_solver_sm_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+{
+ build_LE_A<matrix_solver_sm_t>();
+ build_LE_RHS<matrix_solver_sm_t>();
+
+ for (std::size_t i=0, iN=N(); i < iN; i++)
+ m_last_RHS[i] = RHS(i);
+
+ this->m_stat_calculations++;
+ return this->solve_non_dynamic(newton_raphson);
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_sm_t<m_N, storage_N>::matrix_solver_sm_t(netlist_t &anetlist, const pstring &name,
+ const solver_parameters_t *params, const std::size_t size)
+: matrix_solver_t(anetlist, name, NOSORT, params)
+, m_dim(size)
+, m_cnt(0)
+{
+ for (std::size_t k = 0; k < N(); k++)
{
+ m_last_RHS[k] = 0.0;
}
+}
-} // namespace devices
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_DIRECT_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_sor.h b/src/lib/netlist/solver/nld_ms_sor.h
index c31aaa6d46a..eea692d6c47 100644
--- a/src/lib/netlist/solver/nld_ms_sor.h
+++ b/src/lib/netlist/solver/nld_ms_sor.h
@@ -12,42 +12,33 @@
#ifndef NLD_MS_SOR_H_
#define NLD_MS_SOR_H_
+#include <algorithm>
+
#include "nld_ms_direct.h"
#include "nld_solver.h"
-#include <algorithm>
-
namespace netlist
{
namespace devices
-{
-
-template <typename FT, int SIZE>
-class matrix_solver_SOR_t: public matrix_solver_direct_t<FT, SIZE>
+ {
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_SOR_t: public matrix_solver_direct_t<m_N, storage_N>
{
public:
- using float_type = FT;
-
- matrix_solver_SOR_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
+ matrix_solver_SOR_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
+ : matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
, m_lp_fact(*this, "m_lp_fact", 0)
- , w(size, 0.0)
- , one_m_w(size, 0.0)
- , RHS(size, 0.0)
- //, new_V(size, 0.0)
{
}
- void vsetup(analog_net_t::list_t &nets) override;
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ virtual ~matrix_solver_SOR_t() override {}
+
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
private:
- state_var<float_type> m_lp_fact;
- std::vector<float_type> w;
- std::vector<float_type> one_m_w;
- std::vector<float_type> RHS;
- //std::vector<float_type> new_V;
+ state_var<nl_double> m_lp_fact;
};
// ----------------------------------------------------------------------------------------
@@ -55,16 +46,16 @@ private:
// ----------------------------------------------------------------------------------------
-template <typename FT, int SIZE>
-void matrix_solver_SOR_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_SOR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
- matrix_solver_direct_t<FT, SIZE>::vsetup(nets);
+ matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
}
-template <typename FT, int SIZE>
-unsigned matrix_solver_SOR_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- const std::size_t iN = this->size();
+ const std::size_t iN = this->N();
bool resched = false;
unsigned resched_cnt = 0;
@@ -76,21 +67,26 @@ unsigned matrix_solver_SOR_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_rap
* omega = 2.0 / (1.0 + std::sqrt(1-rho))
*/
- const float_type ws = this->m_params.m_gs_sor;
+ const nl_double ws = this->m_params.m_gs_sor;
+
+ nl_double w[storage_N];
+ nl_double one_m_w[storage_N];
+ nl_double RHS[storage_N];
+ nl_double new_V[storage_N];
for (std::size_t k = 0; k < iN; k++)
{
- float_type gtot_t = 0.0;
- float_type gabs_t = 0.0;
- float_type RHS_t = 0.0;
+ nl_double gtot_t = 0.0;
+ nl_double gabs_t = 0.0;
+ nl_double RHS_t = 0.0;
const std::size_t term_count = this->m_terms[k]->count();
- const float_type * const gt = this->m_gtn[k];
- const float_type * const go = this->m_gonn[k];
- const float_type * const Idr = this->m_Idrn[k];
- auto other_cur_analog = this->m_connected_net_Vn[k];
+ const nl_double * const RESTRICT gt = this->m_terms[k]->gt();
+ const nl_double * const RESTRICT go = this->m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
+ const nl_double * const *other_cur_analog = this->m_terms[k]->connected_net_V();
- this->m_new_V[k] = this->m_nets[k]->Q_Analog();
+ new_V[k] = this->m_nets[k]->Q_Analog();
for (std::size_t i = 0; i < term_count; i++)
{
@@ -99,60 +95,61 @@ unsigned matrix_solver_SOR_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_rap
}
for (std::size_t i = this->m_terms[k]->m_railstart; i < term_count; i++)
- RHS_t = RHS_t - go[i] * *other_cur_analog[i];
+ RHS_t = RHS_t + go[i] * *other_cur_analog[i];
RHS[k] = RHS_t;
- if (this->m_params.m_use_gabs)
+ if (USE_GABS)
{
for (std::size_t i = 0; i < term_count; i++)
gabs_t = gabs_t + std::abs(go[i]);
- gabs_t *= plib::constants<nl_double>::cast(0.5); // derived by try and error
+ gabs_t *= NL_FCONST(0.5); // derived by try and error
if (gabs_t <= gtot_t)
{
w[k] = ws / gtot_t;
- one_m_w[k] = plib::constants<FT>::one() - ws;
+ one_m_w[k] = NL_FCONST(1.0) - ws;
}
else
{
- w[k] = plib::constants<FT>::one() / (gtot_t + gabs_t);
- one_m_w[k] = plib::constants<FT>::one() - plib::constants<FT>::one() * gtot_t / (gtot_t + gabs_t);
+ w[k] = NL_FCONST(1.0) / (gtot_t + gabs_t);
+ one_m_w[k] = NL_FCONST(1.0) - NL_FCONST(1.0) * gtot_t / (gtot_t + gabs_t);
}
}
else
{
w[k] = ws / gtot_t;
- one_m_w[k] = plib::constants<FT>::one() - ws;
+ one_m_w[k] = NL_FCONST(1.0) - ws;
}
}
- const float_type accuracy = this->m_params.m_accuracy;
+ const nl_double accuracy = this->m_params.m_accuracy;
do {
resched = false;
- float_type err = 0;
+ nl_double err = 0;
for (std::size_t k = 0; k < iN; k++)
{
- const int * net_other = this->m_terms[k]->m_connected_net_idx.data();
+ const int * RESTRICT net_other = this->m_terms[k]->connected_net_idx();
const std::size_t railstart = this->m_terms[k]->m_railstart;
- const float_type * go = this->m_gonn[k];
+ const nl_double * RESTRICT go = this->m_terms[k]->go();
- float_type Idrive = 0.0;
+ nl_double Idrive = 0.0;
for (std::size_t i = 0; i < railstart; i++)
- Idrive = Idrive - go[i] * this->m_new_V[static_cast<std::size_t>(net_other[i])];
+ Idrive = Idrive + go[i] * new_V[net_other[i]];
- const float_type new_val = this->m_new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k];
+ const nl_double new_val = new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k];
- err = std::max(std::abs(new_val - this->m_new_V[k]), err);
- this->m_new_V[k] = new_val;
+ err = std::max(std::abs(new_val - new_V[k]), err);
+ new_V[k] = new_val;
}
if (err > accuracy)
resched = true;
resched_cnt++;
- } while (resched && (resched_cnt < this->m_params.m_gs_loops));
+ //} while (resched && (resched_cnt < this->m_params.m_gs_loops));
+ } while (resched && ((resched_cnt < this->m_params.m_gs_loops)));
this->m_iterative_total += resched_cnt;
this->m_stat_calculations++;
@@ -161,12 +158,13 @@ unsigned matrix_solver_SOR_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_rap
{
// Fallback to direct solver ...
this->m_iterative_fail++;
- return matrix_solver_direct_t<FT, SIZE>::vsolve_non_dynamic(newton_raphson);
+ return matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(newton_raphson);
}
- const float_type err = (newton_raphson ? this->delta(this->m_new_V) : 0.0);
- this->store(this->m_new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
+ for (std::size_t k = 0; k < iN; k++)
+ this->m_nets[k]->set_Q_Analog(new_V[k]);
+
+ return resched_cnt;
}
} //namespace devices
diff --git a/src/lib/netlist/solver/nld_ms_sor_mat.h b/src/lib/netlist/solver/nld_ms_sor_mat.h
index 83e4870cf28..50bcac1a52d 100644
--- a/src/lib/netlist/solver/nld_ms_sor_mat.h
+++ b/src/lib/netlist/solver/nld_ms_sor_mat.h
@@ -12,220 +12,212 @@
#ifndef NLD_MS_SOR_MAT_H_
#define NLD_MS_SOR_MAT_H_
-#include "nld_matrix_solver.h"
+#include <algorithm>
+
#include "nld_ms_direct.h"
+#include "nld_matrix_solver.h"
#include "nld_solver.h"
-#include <algorithm>
-
namespace netlist
{
-namespace devices
-{
-
- template <typename FT, int SIZE>
- class matrix_solver_SOR_mat_t: public matrix_solver_direct_t<FT, SIZE>
+ namespace devices
{
- friend class matrix_solver_t;
+template <std::size_t m_N, std::size_t storage_N>
+class matrix_solver_SOR_mat_t: public matrix_solver_direct_t<m_N, storage_N>
+{
+ friend class matrix_solver_t;
- public:
+public:
- using float_type = FT;
+ matrix_solver_SOR_mat_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, std::size_t size)
+ : matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::DESCENDING, params, size)
+ , m_Vdelta(*this, "m_Vdelta", 0.0)
+ , m_omega(*this, "m_omega", params->m_gs_sor)
+ , m_lp_fact(*this, "m_lp_fact", 0)
+ , m_gs_fail(*this, "m_gs_fail", 0)
+ , m_gs_total(*this, "m_gs_total", 0)
+ {
+ }
- matrix_solver_SOR_mat_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, std::size_t size)
- : matrix_solver_direct_t<FT, SIZE>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
- , m_Vdelta(*this, "m_Vdelta", std::vector<float_type>(size))
- , m_omega(*this, "m_omega", params->m_gs_sor)
- , m_lp_fact(*this, "m_lp_fact", 0)
- {
- }
+ virtual ~matrix_solver_SOR_mat_t() override {}
- void vsetup(analog_net_t::list_t &nets) override;
+ virtual void vsetup(analog_net_t::list_t &nets) override;
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- private:
- //state_var<float_type[storage_N]> m_Vdelta;
- state_var<std::vector<float_type>> m_Vdelta;
+private:
+ state_var<nl_double[storage_N]> m_Vdelta;
- state_var<float_type> m_omega;
- state_var<float_type> m_lp_fact;
+ state_var<nl_double> m_omega;
+ state_var<nl_double> m_lp_fact;
+ state_var<int> m_gs_fail;
+ state_var<int> m_gs_total;
+};
- };
+// ----------------------------------------------------------------------------------------
+// matrix_solver - Gauss - Seidel
+// ----------------------------------------------------------------------------------------
- // ----------------------------------------------------------------------------------------
- // matrix_solver - Gauss - Seidel
- // ----------------------------------------------------------------------------------------
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_SOR_mat_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
+{
+ matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
+}
- template <typename FT, int SIZE>
- void matrix_solver_SOR_mat_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
- {
- matrix_solver_direct_t<FT, SIZE>::vsetup(nets);
- }
+#if 0
+//FIXME: move to solve_base
+template <unsigned m_N, unsigned storage_N>
+nl_double matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve()
+{
+ /*
+ * enable linear prediction on first newton pass
+ */
- #if 0
- //FIXME: move to solve_base
- template <unsigned m_N, unsigned storage_N>
- float_type matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve()
- {
- /*
- * enable linear prediction on first newton pass
- */
-
- if (this->m_params->use_linear_prediction)
- for (unsigned k = 0; k < this->size(); k++)
- {
- this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
- this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_cur_Analog + this->m_Vdelta[k] * this->current_timestep() * m_lp_fact;
- }
- else
- for (unsigned k = 0; k < this->size(); k++)
- {
- this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
- }
+ if (USE_LINEAR_PREDICTION)
+ for (unsigned k = 0; k < this->N(); k++)
+ {
+ this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
+ this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_cur_Analog + this->m_Vdelta[k] * this->current_timestep() * m_lp_fact;
+ }
+ else
+ for (unsigned k = 0; k < this->N(); k++)
+ {
+ this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
+ }
- this->solve_base(this);
+ this->solve_base(this);
- if (this->m_params->use_linear_prediction)
+ if (USE_LINEAR_PREDICTION)
+ {
+ nl_double sq = 0;
+ nl_double sqo = 0;
+ const nl_double rez_cts = 1.0 / this->current_timestep();
+ for (unsigned k = 0; k < this->N(); k++)
{
- float_type sq = 0;
- float_type sqo = 0;
- const float_type rez_cts = 1.0 / this->current_timestep();
- for (unsigned k = 0; k < this->size(); k++)
- {
- const analog_net_t *n = this->m_nets[k];
- const float_type nv = (n->Q_Analog() - this->m_last_V[k]) * rez_cts ;
- sq += nv * nv;
- sqo += this->m_Vdelta[k] * this->m_Vdelta[k];
- this->m_Vdelta[k] = nv;
- }
-
- // FIXME: used to be 1e90, but this would not be compatible with float
- if (sqo > NL_FCONST(1e-20))
- m_lp_fact = std::min(std::sqrt(sq/sqo), (float_type) 2.0);
- else
- m_lp_fact = NL_FCONST(0.0);
+ const analog_net_t *n = this->m_nets[k];
+ const nl_double nv = (n->Q_Analog() - this->m_last_V[k]) * rez_cts ;
+ sq += nv * nv;
+ sqo += this->m_Vdelta[k] * this->m_Vdelta[k];
+ this->m_Vdelta[k] = nv;
}
-
- return this->compute_next_timestep();
+ // FIXME: used to be 1e90, but this would not be compatible with float
+ if (sqo > NL_FCONST(1e-20))
+ m_lp_fact = std::min(std::sqrt(sq/sqo), (nl_double) 2.0);
+ else
+ m_lp_fact = NL_FCONST(0.0);
}
- #endif
- template <typename FT, int SIZE>
- unsigned matrix_solver_SOR_mat_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
- {
- /* The matrix based code looks a lot nicer but actually is 30% slower than
- * the optimized code which works directly on the data structures.
- * Need something like that for gaussian elimination as well.
- */
+ return this->compute_next_timestep();
+}
+#endif
+
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
+{
+ /* The matrix based code looks a lot nicer but actually is 30% slower than
+ * the optimized code which works directly on the data structures.
+ * Need something like that for gaussian elimination as well.
+ */
- const std::size_t iN = this->size();
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
+ nl_double new_v[storage_N] = { 0.0 };
+ const std::size_t iN = this->N();
- bool resched = false;
+ matrix_solver_t::build_LE_A<matrix_solver_SOR_mat_t>();
+ matrix_solver_t::build_LE_RHS<matrix_solver_SOR_mat_t>();
- unsigned resched_cnt = 0;
+ bool resched = false;
+ unsigned resched_cnt = 0;
- #if 0
- static int ws_cnt = 0;
- ws_cnt++;
- if (1 && ws_cnt % 200 == 0)
+
+#if 0
+ static int ws_cnt = 0;
+ ws_cnt++;
+ if (1 && ws_cnt % 200 == 0)
+ {
+ // update omega
+ nl_double lambdaN = 0;
+ nl_double lambda1 = 1e9;
+ for (int k = 0; k < iN; k++)
{
- // update omega
- float_type lambdaN = 0;
- float_type lambda1 = 1e9;
- for (int k = 0; k < iN; k++)
- {
- #if 0
- float_type akk = std::abs(this->m_A[k][k]);
- if ( akk > lambdaN)
- lambdaN = akk;
- if (akk < lambda1)
- lambda1 = akk;
- #else
- float_type akk = std::abs(this->m_A[k][k]);
- float_type s = 0.0;
- for (int i=0; i<iN; i++)
- s = s + std::abs(this->m_A[k][i]);
- akk = s / akk - 1.0;
- if ( akk > lambdaN)
- lambdaN = akk;
- if (akk < lambda1)
- lambda1 = akk;
- #endif
- }
-
- //ws = 2.0 / (2.0 - lambdaN - lambda1);
- m_omega = 2.0 / (2.0 - lambda1);
- }
+ #if 0
+ nl_double akk = std::abs(this->m_A[k][k]);
+ if ( akk > lambdaN)
+ lambdaN = akk;
+ if (akk < lambda1)
+ lambda1 = akk;
+ #else
+ nl_double akk = std::abs(this->m_A[k][k]);
+ nl_double s = 0.0;
+ for (int i=0; i<iN; i++)
+ s = s + std::abs(this->m_A[k][i]);
+ akk = s / akk - 1.0;
+ if ( akk > lambdaN)
+ lambdaN = akk;
+ if (akk < lambda1)
+ lambda1 = akk;
#endif
+ }
+ //printf("lambda: %f %f\n", lambda, 2.0 / (1.0 + 2 * sqrt(lambda)) );
+
+ //ws = 2.0 / (2.0 - lambdaN - lambda1);
+ m_omega = 2.0 / (2.0 - lambda1);
+ //printf("%f %f %f\n", m_omega, lambda1, lambdaN);
+ }
+#endif
+
+ for (std::size_t k = 0; k < iN; k++)
+ new_v[k] = this->m_nets[k]->Q_Analog();
+
+ do {
+ resched = false;
+ nl_double cerr = 0.0;
for (std::size_t k = 0; k < iN; k++)
- this->m_new_V[k] = this->m_nets[k]->Q_Analog();
-
- do {
- resched = false;
- float_type cerr = 0.0;
-
- for (std::size_t k = 0; k < iN; k++)
- {
- float_type Idrive = 0;
-
- const auto *p = this->m_terms[k]->m_nz.data();
- const std::size_t e = this->m_terms[k]->m_nz.size();
-
- for (std::size_t i = 0; i < e; i++)
- Idrive = Idrive + this->A(k,p[i]) * this->m_new_V[p[i]];
-
- FT w = m_omega / this->A(k,k);
- if (this->m_params.m_use_gabs)
- {
- FT gabs_t = 0.0;
- for (std::size_t i = 0; i < e; i++)
- if (p[i] != k)
- gabs_t = gabs_t + std::abs(this->A(k,p[i]));
-
- gabs_t *= plib::constants<FT>::one(); // derived by try and error
- if (gabs_t > this->A(k,k))
- {
- w = plib::constants<FT>::one() / (this->A(k,k) + gabs_t);
- }
- }
-
- const float_type delta = w * (this->RHS(k) - Idrive) ;
- cerr = std::max(cerr, std::abs(delta));
- this->m_new_V[k] += delta;
- }
-
- if (cerr > this->m_params.m_accuracy)
- {
- resched = true;
- }
- resched_cnt++;
- } while (resched && (resched_cnt < this->m_params.m_gs_loops));
-
- this->m_stat_calculations++;
- this->m_iterative_total += resched_cnt;
-
- if (resched)
{
- this->m_iterative_fail++;
- //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
- return matrix_solver_direct_t<FT, SIZE>::solve_non_dynamic(newton_raphson);
+ nl_double Idrive = 0;
+
+ const auto *p = this->m_terms[k]->m_nz.data();
+ const std::size_t e = this->m_terms[k]->m_nz.size();
+
+ for (std::size_t i = 0; i < e; i++)
+ Idrive = Idrive + this->A(k,p[i]) * new_v[p[i]];
+
+ const nl_double delta = m_omega * (this->RHS(k) - Idrive) / this->A(k,k);
+ cerr = std::max(cerr, std::abs(delta));
+ new_v[k] += delta;
+ }
+
+ if (cerr > this->m_params.m_accuracy)
+ {
+ resched = true;
}
+ resched_cnt++;
+ } while (resched && (resched_cnt < this->m_params.m_gs_loops));
+
+ this->m_stat_calculations++;
+ this->m_iterative_total += resched_cnt;
+ this->m_gs_total += resched_cnt;
- const float_type err = (newton_raphson ? this->delta(this->m_new_V) : 0.0);
- this->store(this->m_new_V);
- return (err > this->m_params.m_accuracy) ? 2 : 1;
+ if (resched)
+ {
+ this->m_iterative_fail++;
+ //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
+ this->m_gs_fail++;
+ return matrix_solver_direct_t<m_N, storage_N>::solve_non_dynamic(newton_raphson);
+ }
+ else {
+ this->store(new_v);
+ return resched_cnt;
}
-} // namespace devices
+}
+
+ } //namespace devices
} // namespace netlist
#endif /* NLD_MS_GAUSS_SEIDEL_H_ */
diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h
index 3372b50c7c5..0d4e7781eed 100644
--- a/src/lib/netlist/solver/nld_ms_w.h
+++ b/src/lib/netlist/solver/nld_ms_w.h
@@ -40,80 +40,80 @@
#ifndef NLD_MS_W_H_
#define NLD_MS_W_H_
-#include "nld_matrix_solver.h"
-#include "nld_solver.h"
-#include "plib/vector_ops.h"
-
#include <algorithm>
+#include "nld_solver.h"
+#include "nld_matrix_solver.h"
+#include "vector_base.h"
+
namespace netlist
{
namespace devices
{
+//#define nl_ext_double _float128 // slow, very slow
+//#define nl_ext_double long double // slightly slower
+#define nl_ext_double nl_double
-template <typename FT, int SIZE>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_w_t: public matrix_solver_t
{
friend class matrix_solver_t;
-
public:
- using float_ext_type = FT;
- using float_type = FT;
- // FIXME: dirty hack to make this compile
- static constexpr const std::size_t storage_N = 100;
+ matrix_solver_w_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
- matrix_solver_w_t(netlist_state_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
+ virtual ~matrix_solver_w_t() override;
- void vsetup(analog_net_t::list_t &nets) override;
- void reset() override { matrix_solver_t::reset(); }
+ virtual void vsetup(analog_net_t::list_t &nets) override;
+ virtual void reset() override { matrix_solver_t::reset(); }
protected:
- unsigned vsolve_non_dynamic(const bool newton_raphson) override;
+ virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
unsigned solve_non_dynamic(const bool newton_raphson);
- constexpr std::size_t size() const { return m_dim; }
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
void LE_invert();
template <typename T>
- void LE_compute_x(T * x);
+ void LE_compute_x(T * RESTRICT x);
template <typename T1, typename T2>
- float_ext_type &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
+ inline nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
template <typename T1, typename T2>
- float_ext_type &W(const T1 &r, const T2 &c) { return m_W[r][c]; }
+ inline nl_ext_double &W(const T1 &r, const T2 &c) { return m_W[r][c]; }
/* access to Ainv for fixed columns over row, there store transposed */
template <typename T1, typename T2>
- float_ext_type &Ainv(const T1 &r, const T2 &c) { return m_Ainv[c][r]; }
+ inline nl_ext_double &Ainv(const T1 &r, const T2 &c) { return m_Ainv[c][r]; }
template <typename T1>
- float_ext_type &RHS(const T1 &r) { return m_RHS[r]; }
+ inline nl_ext_double &RHS(const T1 &r) { return m_RHS[r]; }
template <typename T1, typename T2>
- float_ext_type &lA(const T1 &r, const T2 &c) { return m_lA[r][c]; }
+ inline nl_ext_double &lA(const T1 &r, const T2 &c) { return m_lA[r][c]; }
+ nl_double m_last_RHS[storage_N]; // right hand side - contains currents
private:
static constexpr std::size_t m_pitch = ((( storage_N) + 7) / 8) * 8;
- float_ext_type m_A[storage_N][m_pitch];
- float_ext_type m_Ainv[storage_N][m_pitch];
- float_ext_type m_W[storage_N][m_pitch];
- float_ext_type m_RHS[storage_N]; // right hand side - contains currents
+ nl_ext_double m_A[storage_N][m_pitch];
+ nl_ext_double m_Ainv[storage_N][m_pitch];
+ nl_ext_double m_W[storage_N][m_pitch];
+ nl_ext_double m_RHS[storage_N]; // right hand side - contains currents
- float_ext_type m_lA[storage_N][m_pitch];
+ nl_ext_double m_lA[storage_N][m_pitch];
/* temporary */
- float_type H[storage_N][m_pitch] ;
+ nl_double H[storage_N][m_pitch] ;
unsigned rows[storage_N];
unsigned cols[storage_N][m_pitch];
unsigned colcount[storage_N];
unsigned m_cnt;
- //float_ext_type m_RHSx[storage_N];
+ //nl_ext_double m_RHSx[storage_N];
const std::size_t m_dim;
@@ -123,22 +123,28 @@ private:
// matrix_solver_direct
// ----------------------------------------------------------------------------------------
-template <typename FT, int SIZE>
-void matrix_solver_w_t<FT, SIZE>::vsetup(analog_net_t::list_t &nets)
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_w_t<m_N, storage_N>::~matrix_solver_w_t()
+{
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_w_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
matrix_solver_t::setup_base(nets);
- // FIXME: This shouldn't be necessary, recalculate on each entry ...
- for (std::size_t k = 0; k < size(); k++)
- state().save(*this, RHS(k), this->name(), plib::pfmt("RHS.{1}")(k));
+ netlist().save(*this, m_last_RHS, "m_last_RHS");
+
+ for (unsigned k = 0; k < N(); k++)
+ netlist().save(*this, RHS(k), plib::pfmt("RHS.{1}")(k));
}
-template <typename FT, int SIZE>
-void matrix_solver_w_t<FT, SIZE>::LE_invert()
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_w_t<m_N, storage_N>::LE_invert()
{
- const std::size_t kN = size();
+ const std::size_t kN = N();
for (std::size_t i = 0; i < kN; i++)
{
@@ -153,18 +159,18 @@ void matrix_solver_w_t<FT, SIZE>::LE_invert()
for (std::size_t i = 0; i < kN; i++)
{
/* FIXME: Singular matrix? */
- const float_type f = 1.0 / W(i,i);
- const auto * const p = m_terms[i]->m_nzrd.data();
+ const nl_double f = 1.0 / W(i,i);
+ const auto * RESTRICT const p = m_terms[i]->m_nzrd.data();
const size_t e = m_terms[i]->m_nzrd.size();
/* Eliminate column i from row j */
- const auto * const pb = m_terms[i]->m_nzbd.data();
+ const auto * RESTRICT const pb = m_terms[i]->m_nzbd.data();
const size_t eb = m_terms[i]->m_nzbd.size();
for (std::size_t jb = 0; jb < eb; jb++)
{
const auto j = pb[jb];
- const float_type f1 = - W(j,i) * f;
+ const nl_double f1 = - W(j,i) * f;
if (f1 != 0.0)
{
for (std::size_t k = 0; k < e; k++)
@@ -178,10 +184,10 @@ void matrix_solver_w_t<FT, SIZE>::LE_invert()
for (std::size_t i = kN; i-- > 0; )
{
/* FIXME: Singular matrix? */
- const float_type f = 1.0 / W(i,i);
+ const nl_double f = 1.0 / W(i,i);
for (std::size_t j = i; j-- > 0; )
{
- const float_type f1 = - W(j,i) * f;
+ const nl_double f1 = - W(j,i) * f;
if (f1 != 0.0)
{
for (std::size_t k = i; k < kN; k++)
@@ -197,19 +203,19 @@ void matrix_solver_w_t<FT, SIZE>::LE_invert()
}
}
-template <typename FT, int SIZE>
+template <std::size_t m_N, std::size_t storage_N>
template <typename T>
-void matrix_solver_w_t<FT, SIZE>::LE_compute_x(
- T * x)
+void matrix_solver_w_t<m_N, storage_N>::LE_compute_x(
+ T * RESTRICT x)
{
- const std::size_t kN = size();
+ const std::size_t kN = N();
for (std::size_t i=0; i<kN; i++)
x[i] = 0.0;
for (std::size_t k=0; k<kN; k++)
{
- const float_type f = RHS(k);
+ const nl_double f = RHS(k);
for (std::size_t i=0; i<kN; i++)
x[i] += Ainv(i,k) * f;
@@ -217,14 +223,14 @@ void matrix_solver_w_t<FT, SIZE>::LE_compute_x(
}
-template <typename FT, int SIZE>
-unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphson)
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_w_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
{
- const auto iN = size();
+ const auto iN = N();
- float_type new_V[storage_N]; // = { 0.0 };
+ nl_double new_V[storage_N]; // = { 0.0 };
- if ((m_cnt % 50) == 0)
+ if ((m_cnt % 100) == 0)
{
/* complete calculation */
this->LE_invert();
@@ -260,7 +266,7 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
/* construct w = transform(V) * y
* dim: rowcount x iN
* */
- float_type w[storage_N];
+ nl_double w[storage_N];
for (unsigned i = 0; i < rowcount; i++)
{
const unsigned r = rows[i];
@@ -281,7 +287,7 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
for (unsigned k=0; k< colcount[i]; k++)
{
const unsigned col = cols[i][k];
- float_type f = VT(rows[i],col);
+ nl_double f = VT(rows[i],col);
if (f!=0.0)
for (unsigned j= 0; j < rowcount; j++)
H[i][j] += f * Ainv(col,rows[j]);
@@ -291,16 +297,16 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
for (unsigned i = 0; i < rowcount; i++)
{
if (H[i][i] == 0.0)
- plib::perrlogger("{} H singular\n", this->name());
- const float_type f = 1.0 / H[i][i];
+ printf("%s H singular\n", this->name().c_str());
+ const nl_double f = 1.0 / H[i][i];
for (unsigned j = i+1; j < rowcount; j++)
{
- const float_type f1 = - f * H[j][i];
+ const nl_double f1 = - f * H[j][i];
if (f1!=0.0)
{
- float_type *pj = &H[j][i+1];
- const float_type *pi = &H[i][i+1];
+ nl_double *pj = &H[j][i+1];
+ const nl_double *pi = &H[i][i+1];
for (unsigned k = 0; k < rowcount-i-1; k++)
pj[k] += f1 * pi[k];
//H[j][k] += f1 * H[i][k];
@@ -310,12 +316,12 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
}
/* Back substitution */
//inv(H) w = t w = H t
- float_type t[storage_N]; // FIXME: convert to member
+ nl_double t[storage_N]; // FIXME: convert to member
for (unsigned j = rowcount; j-- > 0; )
{
- float_type tmp = 0;
- const float_type *pj = &H[j][j+1];
- const float_type *tj = &t[j+1];
+ nl_double tmp = 0;
+ const nl_double *pj = &H[j][j+1];
+ const nl_double *tj = &t[j+1];
for (unsigned k = 0; k < rowcount-j-1; k++)
tmp += pj[k] * tj[k];
//tmp += H[j][k] * t[k];
@@ -325,7 +331,7 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
/* x = y - Zt */
for (unsigned i=0; i<iN; i++)
{
- float_type tmp = 0.0;
+ nl_double tmp = 0.0;
for (unsigned j=0; j<rowcount;j++)
{
const unsigned row = rows[j];
@@ -337,40 +343,47 @@ unsigned matrix_solver_w_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphso
}
m_cnt++;
- if (false)
+ if (0)
for (unsigned i=0; i<iN; i++)
{
- float_type tmp = 0.0;
+ nl_double tmp = 0.0;
for (unsigned j=0; j<iN; j++)
{
tmp += A(i,j) * new_V[j];
}
if (std::abs(tmp-RHS(i)) > 1e-6)
- plib::perrlogger("{} failed on row {}: {} RHS: {}\n", this->name(), i, std::abs(tmp-RHS(i)), RHS(i));
+ printf("%s failed on row %d: %f RHS: %f\n", this->name().c_str(), i, std::abs(tmp-RHS(i)), RHS(i));
}
- const float_type err = (newton_raphson ? delta(new_V) : 0.0);
+ const nl_double err = (newton_raphson ? delta(new_V) : 0.0);
store(new_V);
return (err > this->m_params.m_accuracy) ? 2 : 1;
}
-template <typename FT, int SIZE>
-unsigned matrix_solver_w_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
+template <std::size_t m_N, std::size_t storage_N>
+inline unsigned matrix_solver_w_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- this->build_LE_A(*this);
- this->build_LE_RHS(*this);
+ build_LE_A<matrix_solver_w_t>();
+ build_LE_RHS<matrix_solver_w_t>();
+
+ for (std::size_t i=0, iN=N(); i < iN; i++)
+ m_last_RHS[i] = RHS(i);
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);
}
-template <typename FT, int SIZE>
-matrix_solver_w_t<FT, SIZE>::matrix_solver_w_t(netlist_state_t &anetlist, const pstring &name,
+template <std::size_t m_N, std::size_t storage_N>
+matrix_solver_w_t<m_N, storage_N>::matrix_solver_w_t(netlist_t &anetlist, const pstring &name,
const solver_parameters_t *params, const std::size_t size)
- : matrix_solver_t(anetlist, name, NOSORT, params)
- , m_cnt(0)
+: matrix_solver_t(anetlist, name, NOSORT, params)
+ ,m_cnt(0)
, m_dim(size)
{
+ for (std::size_t k = 0; k < N(); k++)
+ {
+ m_last_RHS[k] = 0.0;
+ }
}
} //namespace devices
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 4734cc3624d..cae76caab1a 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -31,398 +31,393 @@
#pragma GCC optimize "ivopts"
#endif
-#include "netlist/nl_lists.h"
-#include "netlist/nl_factory.h"
+#include <algorithm>
+#include <cmath> // <<= needed by windows build
+
+#include "../nl_lists.h"
+
+#include "../plib/pomp.h"
+
+#include "../nl_factory.h"
+
+#include "nld_solver.h"
#include "nld_matrix_solver.h"
+
+#if 1
#include "nld_ms_direct.h"
-#include "nld_ms_direct1.h"
-#include "nld_ms_direct2.h"
#include "nld_ms_gcr.h"
-#include "nld_ms_gmres.h"
+#else
+#include "nld_ms_direct_lu.h"
+#endif
+#include "nld_ms_w.h"
#include "nld_ms_sm.h"
+#include "nld_ms_direct1.h"
+#include "nld_ms_direct2.h"
#include "nld_ms_sor.h"
#include "nld_ms_sor_mat.h"
-#include "nld_ms_w.h"
-#include "nld_solver.h"
-#include "plib/pomp.h"
-
-#include <algorithm>
-#include <cmath>
+#include "nld_ms_gmres.h"
namespace netlist
{
-namespace devices
-{
+ namespace devices
+ {
- // ----------------------------------------------------------------------------------------
- // solver
- // ----------------------------------------------------------------------------------------
- NETLIB_RESET(solver)
- {
- for (auto &s : m_mat_solvers)
- s->reset();
- }
- void NETLIB_NAME(solver)::stop()
- {
- for (auto &s : m_mat_solvers)
- s->log_stats();
- }
+// ----------------------------------------------------------------------------------------
+// solver
+// ----------------------------------------------------------------------------------------
- NETLIB_UPDATE(solver)
- {
- if (m_params.m_dynamic_ts)
- return;
+NETLIB_RESET(solver)
+{
+ for (std::size_t i = 0; i < m_mat_solvers.size(); i++)
+ m_mat_solvers[i]->do_reset();
+}
- netlist_time now(exec().time());
- /* force solving during start up if there are no time-step devices */
- /* FIXME: Needs a more elegant solution */
- bool force_solve = (now < netlist_time::from_double(2 * m_params.m_max_timestep));
+void NETLIB_NAME(solver)::stop()
+{
+ for (std::size_t i = 0; i < m_mat_solvers.size(); i++)
+ m_mat_solvers[i]->log_stats();
+}
- std::size_t nthreads = std::min(static_cast<std::size_t>(m_parallel()), plib::omp::get_max_threads());
+NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
+{
+}
- std::vector<matrix_solver_t *> &solvers = (force_solve ? m_mat_solvers_all : m_mat_solvers_timestepping);
+NETLIB_UPDATE(solver)
+{
+ if (m_params.m_dynamic_ts)
+ return;
- if (nthreads > 1 && solvers.size() > 1)
- {
- plib::omp::set_num_threads(nthreads);
- plib::omp::for_static(static_cast<std::size_t>(0), solvers.size(), [&solvers, now](std::size_t i)
- {
- const netlist_time ts = solvers[i]->solve(now);
- plib::unused_var(ts);
- });
- }
- else
- for (auto & solver : solvers)
- {
- const netlist_time ts = solver->solve(now);
- plib::unused_var(ts);
- }
+ /* force solving during start up if there are no time-step devices */
+ /* FIXME: Needs a more elegant solution */
+ bool force_solve = (netlist().time() < netlist_time::from_double(2 * m_params.m_max_timestep));
- for (auto & solver : solvers)
- solver->update_inputs();
+ std::size_t nthreads = std::min(m_parallel(), plib::omp::get_max_threads());
+ std::size_t t_cnt = 0;
+ int solv[128];
+ for (int i = 0; i < m_mat_solvers.size(); i++)
+ if (m_mat_solvers[i]->has_timestep_devices() || force_solve)
+ solv[t_cnt++] = i;
- /* step circuit */
- if (!m_Q_step.net().is_queued())
- {
- m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_max_timestep));
- }
+ if (nthreads > 1 && t_cnt > 1)
+ {
+ plib::omp::set_num_threads(nthreads);
+ plib::omp::for_static(0, t_cnt, [this, &solv](int i) { ATTR_UNUSED const netlist_time ts = this->m_mat_solvers[solv[i]]->solve(); });
}
+ else
+ for (auto & solver : m_mat_solvers)
+ if (solver->has_timestep_devices() || force_solve)
+ ATTR_UNUSED const netlist_time ts = solver->solve();
+
+ for (auto & solver : m_mat_solvers)
+ if (solver->has_timestep_devices() || force_solve)
+ solver->update_inputs();
- template <class C>
- pool_owned_ptr<matrix_solver_t> create_it(netlist_state_t &nl, pstring name, solver_parameters_t &params, std::size_t size)
+ /* step circuit */
+ if (!m_Q_step.net().is_queued())
{
- return pool().make_poolptr<C>(nl, name, &params, size);
+ m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_double(m_params.m_max_timestep));
}
+}
- template <typename FT, int SIZE>
- pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername)
+template <class C>
+std::unique_ptr<matrix_solver_t> create_it(netlist_t &nl, pstring name, solver_parameters_t &params, std::size_t size)
+{
+ typedef C solver;
+ return plib::make_unique<solver>(nl, name, &params, size);
+}
+
+template <std::size_t m_N, std::size_t storage_N>
+std::unique_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername)
+{
+ if (pstring("SOR_MAT").equals(m_method()))
{
- if (m_method() == "SOR_MAT")
- {
- return create_it<matrix_solver_SOR_mat_t<FT, SIZE>>(state(), solvername, m_params, size);
- //typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat;
- //return plib::make_unique<solver_sor_mat>(state(), solvername, &m_params, size);
- }
- else if (m_method() == "MAT_CR")
- {
- if (size > 0) // GCR always outperforms MAT solver
- {
- return create_it<matrix_solver_GCR_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else
- {
- return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- }
- else if (m_method() == "MAT")
- {
- return create_it<matrix_solver_direct_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else if (m_method() == "SM")
- {
- /* Sherman-Morrison Formula */
- return create_it<matrix_solver_sm_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else if (m_method() == "W")
- {
- /* Woodbury Formula */
- return create_it<matrix_solver_w_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else if (m_method() == "SOR")
- {
- return create_it<matrix_solver_SOR_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else if (m_method() == "GMRES")
- {
- return create_it<matrix_solver_GMRES_t<FT, SIZE>>(state(), solvername, m_params, size);
- }
- else
- {
- log().fatal(MF_1_UNKNOWN_SOLVER_TYPE, m_method());
- return pool_owned_ptr<matrix_solver_t>();
- }
+ return create_it<matrix_solver_SOR_mat_t<m_N, storage_N>>(netlist(), solvername, m_params, size);
+ //typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat;
+ //return plib::make_unique<solver_sor_mat>(netlist(), solvername, &m_params, size);
}
-
- template <typename FT, int SIZE>
- pool_owned_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver_x(std::size_t size, const pstring &solvername)
+ else if (pstring("MAT_CR").equals(m_method()))
{
- if (SIZE > 0)
+ if (size > 0) // GCR always outperforms MAT solver
{
- if (size == SIZE)
- return create_solver<FT, SIZE>(size, solvername);
- else
- return this->create_solver_x<FT, SIZE-1>(size, solvername);
+ typedef matrix_solver_GCR_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
}
else
{
- if (size * 2 > -SIZE )
- return create_solver<FT, SIZE>(size, solvername);
- else
- return this->create_solver_x<FT, SIZE / 2>(size, solvername);
+ typedef matrix_solver_direct_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
}
}
-
- struct net_splitter
+ else if (pstring("MAT").equals(m_method()))
+ {
+ typedef matrix_solver_direct_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("SM").equals(m_method()))
+ {
+ /* Sherman-Morrison Formula */
+ typedef matrix_solver_sm_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("W").equals(m_method()))
+ {
+ /* Woodbury Formula */
+ typedef matrix_solver_w_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("SOR").equals(m_method()))
+ {
+ typedef matrix_solver_SOR_t<m_N,storage_N> solver_GS;
+ return plib::make_unique<solver_GS>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("GMRES").equals(m_method()))
{
+ typedef matrix_solver_GMRES_t<m_N,storage_N> solver_GMRES;
+ return plib::make_unique<solver_GMRES>(netlist(), solvername, &m_params, size);
+ }
+ else
+ {
+ log().fatal(MF_1_UNKNOWN_SOLVER_TYPE, m_method());
+ return nullptr;
+ }
+}
- bool already_processed(const analog_net_t &n) const
- {
- /* no need to process rail nets - these are known variables */
- if (n.isRailNet())
+struct net_splitter
+{
+
+ bool already_processed(analog_net_t *n)
+ {
+ if (n->isRailNet())
+ return true;
+ for (auto & grp : groups)
+ if (plib::container::contains(grp, n))
return true;
- /* if it's already processed - no need to continue */
- for (auto & grp : groups)
- if (plib::container::contains(grp, &n))
- return true;
- return false;
- }
+ return false;
+ }
- void process_net(analog_net_t &n)
+ void process_net(analog_net_t *n)
+ {
+ if (n->num_cons() == 0)
+ return;
+ /* add the net */
+ groups.back().push_back(n);
+ for (auto &p : n->m_core_terms)
{
- /* ignore empty nets. FIXME: print a warning message */
- if (n.num_cons() == 0)
- return;
- /* add the net */
- groups.back().push_back(&n);
- /* process all terminals connected to this net */
- for (auto &term : n.core_terms())
+ if (p->is_type(detail::terminal_type::TERMINAL))
{
- /* only process analog terminals */
- if (term->is_type(detail::terminal_type::TERMINAL))
- {
- auto *pt = static_cast<terminal_t *>(term);
- /* check the connected terminal */
- analog_net_t &connected_net = pt->connected_terminal()->net();
- if (!already_processed(connected_net))
- process_net(connected_net);
- }
+ terminal_t *pt = static_cast<terminal_t *>(p);
+ analog_net_t *other_net = &pt->m_otherterm->net();
+ if (!already_processed(other_net))
+ process_net(other_net);
}
}
+ }
- void run(netlist_state_t &netlist)
+ void run(netlist_t &netlist)
+ {
+ for (auto & net : netlist.m_nets)
{
- for (auto & net : netlist.nets())
+ netlist.log().debug("processing {1}\n", net->name());
+ if (!net->isRailNet() && net->num_cons() > 0)
{
- netlist.log().debug("processing {1}\n", net->name());
- if (!net->isRailNet() && net->num_cons() > 0)
+ netlist.log().debug(" ==> not a rail net\n");
+ /* Must be an analog net */
+ analog_net_t *n = static_cast<analog_net_t *>(net.get());
+ if (!already_processed(n))
{
- netlist.log().debug(" ==> not a rail net\n");
- /* Must be an analog net */
- auto &n = *static_cast<analog_net_t *>(net.get());
- if (!already_processed(n))
- {
- groups.emplace_back(analog_net_t::list_t());
- process_net(n);
- }
+ groups.push_back(analog_net_t::list_t());
+ process_net(n);
}
}
}
+ }
- std::vector<analog_net_t::list_t> groups;
- };
+ std::vector<analog_net_t::list_t> groups;
+};
- void NETLIB_NAME(solver)::post_start()
+void NETLIB_NAME(solver)::post_start()
+{
+ const bool use_specific = true;
+
+ m_params.m_pivot = m_pivot();
+ m_params.m_accuracy = m_accuracy();
+ /* FIXME: Throw when negative */
+ m_params.m_gs_loops = static_cast<unsigned>(m_gs_loops());
+ m_params.m_nr_loops = static_cast<unsigned>(m_nr_loops());
+ m_params.m_nr_recalc_delay = netlist_time::from_double(m_nr_recalc_delay());
+ m_params.m_dynamic_lte = m_dynamic_lte();
+ m_params.m_gs_sor = m_gs_sor();
+
+ m_params.m_min_timestep = m_dynamic_min_ts();
+ m_params.m_dynamic_ts = (m_dynamic_ts() == 1 ? true : false);
+ m_params.m_max_timestep = netlist_time::from_double(1.0 / m_freq()).as_double();
+
+ if (m_params.m_dynamic_ts)
{
- m_params.m_pivot = m_pivot();
- m_params.m_accuracy = m_accuracy();
- /* FIXME: Throw when negative */
- m_params.m_gs_loops = static_cast<unsigned>(m_gs_loops());
- m_params.m_nr_loops = static_cast<unsigned>(m_nr_loops());
- m_params.m_nr_recalc_delay = netlist_time::from_double(m_nr_recalc_delay());
- m_params.m_dynamic_lte = m_dynamic_lte();
- m_params.m_gs_sor = m_gs_sor();
-
- m_params.m_min_timestep = m_dynamic_min_ts();
- m_params.m_dynamic_ts = (m_dynamic_ts() == 1 ? true : false);
- m_params.m_max_timestep = netlist_time::from_double(1.0 / m_freq()).as_double();
-
- m_params.m_use_gabs = m_use_gabs();
- m_params.m_use_linear_prediction = m_use_linear_prediction();
-
+ m_params.m_max_timestep *= 1;//NL_FCONST(1000.0);
+ }
+ else
+ {
+ m_params.m_min_timestep = m_params.m_max_timestep;
+ }
- if (m_params.m_dynamic_ts)
- {
- m_params.m_max_timestep *= 1;//NL_FCONST(1000.0);
- }
- else
- {
- m_params.m_min_timestep = m_params.m_max_timestep;
- }
+ //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::)
- //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::)
+ // Override log statistics
+ pstring p = plib::util::environment("NL_STATS", "");
+ if (p != "")
+ m_params.m_log_stats = p.as_long();
+ else
+ m_params.m_log_stats = m_log_stats();
- // Override log statistics
- pstring p = plib::util::environment("NL_STATS", "");
- if (p != "")
- m_params.m_log_stats = plib::pstonum<decltype(m_params.m_log_stats)>(p);
- else
- m_params.m_log_stats = m_log_stats();
+ log().verbose("Scanning net groups ...");
+ // determine net groups
- log().verbose("Scanning net groups ...");
- // determine net groups
+ net_splitter splitter;
- net_splitter splitter;
+ splitter.run(netlist());
- splitter.run(state());
+ // setup the solvers
+ log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), netlist().m_nets.size());
+ for (auto & grp : splitter.groups)
+ {
+ std::unique_ptr<matrix_solver_t> ms;
+ std::size_t net_count = grp.size();
+ pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
- // setup the solvers
- log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size());
- for (auto & grp : splitter.groups)
+ switch (net_count)
{
- pool_owned_ptr<matrix_solver_t> ms;
- std::size_t net_count = grp.size();
- pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
+#if 1
+ case 1:
+ if (use_specific)
+ ms = plib::make_unique<matrix_solver_direct1_t>(netlist(), sname, &m_params);
+ else
+ ms = create_solver<1,1>(1, sname);
+ break;
+ case 2:
+ if (use_specific)
+ ms = plib::make_unique<matrix_solver_direct2_t>(netlist(), sname, &m_params);
+ else
+ ms = create_solver<2,2>(2, sname);
+ break;
+#if 0
+ case 3:
+ ms = create_solver<3,3>(3, sname);
+ break;
+ case 4:
+ ms = create_solver<4,4>(4, sname);
+ break;
+ case 5:
+ ms = create_solver<5,5>(5, sname);
+ break;
+ case 6:
+ ms = create_solver<6,6>(6, sname);
+ break;
+ case 7:
+ ms = create_solver<7,7>(7, sname);
+ break;
+ case 8:
+ ms = create_solver<8,8>(8, sname);
+ break;
+ case 9:
+ ms = create_solver<9,9>(9, sname);
+ break;
+ case 10:
+ ms = create_solver<10,10>(10, sname);
+ break;
+ case 11:
+ ms = create_solver<11,11>(11, sname);
+ break;
+ case 12:
+ ms = create_solver<12,12>(12, sname);
+ break;
+ case 15:
+ ms = create_solver<15,15>(15, sname);
+ break;
+ case 31:
+ ms = create_solver<31,31>(31, sname);
+ break;
+ case 35:
+ ms = create_solver<35,35>(35, sname);
+ break;
+ case 43:
+ ms = create_solver<43,43>(43, sname);
+ break;
+ case 49:
+ ms = create_solver<49,49>(49, sname);
+ break;
+#endif
+#if 0
+ case 87:
+ ms = create_solver<87,87>(87, sname);
+ break;
+#endif
+#endif
+ default:
+ log().warning(MW_1_NO_SPECIFIC_SOLVER, net_count);
+ if (net_count <= 8)
+ {
+ ms = create_solver<0, 8>(net_count, sname);
+ }
+ else if (net_count <= 16)
+ {
+ ms = create_solver<0,16>(net_count, sname);
+ }
+ else if (net_count <= 32)
+ {
+ ms = create_solver<0,32>(net_count, sname);
+ }
+ else
+ if (net_count <= 64)
+ {
+ ms = create_solver<0,64>(net_count, sname);
+ }
+ else
+ if (net_count <= 128)
+ {
+ ms = create_solver<0,128>(net_count, sname);
+ }
+ else
+ {
+ log().fatal(MF_1_NETGROUP_SIZE_EXCEEDED_1, 128);
+ ms = nullptr; /* tease compilers */
+ }
- switch (net_count)
- {
- #if 1
- case 1:
- ms = pool().make_poolptr<matrix_solver_direct1_t<double>>(state(), sname, &m_params);
- break;
- case 2:
- ms = pool().make_poolptr<matrix_solver_direct2_t<double>>(state(), sname, &m_params);
- break;
- case 3:
- ms = create_solver<double, 3>(3, sname);
- break;
- case 4:
- ms = create_solver<double, 4>(4, sname);
- break;
- case 5:
- ms = create_solver<double, 5>(5, sname);
- break;
- case 6:
- ms = create_solver<double, 6>(6, sname);
- break;
- case 7:
- ms = create_solver<double, 7>(7, sname);
- break;
- case 8:
- ms = create_solver<double, 8>(8, sname);
- break;
- case 9:
- ms = create_solver<double, 9>(9, sname);
- break;
- case 10:
- ms = create_solver<double, 10>(10, sname);
- break;
- #if 0
- case 11:
- ms = create_solver<double, 11>(11, sname);
- break;
- case 12:
- ms = create_solver<double, 12>(12, sname);
- break;
- case 15:
- ms = create_solver<double, 15>(15, sname);
- break;
- case 31:
- ms = create_solver<double, 31>(31, sname);
- break;
- case 35:
- ms = create_solver<double, 35>(35, sname);
- break;
- case 43:
- ms = create_solver<double, 43>(43, sname);
- break;
- case 49:
- ms = create_solver<double, 49>(49, sname);
- break;
- #endif
- #if 1
- case 86:
- ms = create_solver<double,86>(86, sname);
- break;
- #endif
- #endif
- default:
- log().warning(MW_1_NO_SPECIFIC_SOLVER, net_count);
- if (net_count <= 8)
- {
- ms = create_solver<double, -8>(net_count, sname);
- }
- else if (net_count <= 16)
- {
- ms = create_solver<double, -16>(net_count, sname);
- }
- else if (net_count <= 32)
- {
- ms = create_solver<double, -32>(net_count, sname);
- }
- else
- if (net_count <= 64)
- {
- ms = create_solver<double, -64>(net_count, sname);
- }
- else
- if (net_count <= 128)
- {
- ms = create_solver<double, -128>(net_count, sname);
- }
- else
- {
- log().fatal(MF_1_NETGROUP_SIZE_EXCEEDED_1, 128);
- return; /* tease compilers */
- }
- break;
- }
+ break;
+ }
- // FIXME ...
- ms->setup(grp);
+ // FIXME ...
+ ms->setup(grp);
- log().verbose("Solver {1}", ms->name());
- log().verbose(" ==> {2} nets", grp.size());
- log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic");
- log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep");
- for (auto &n : grp)
+ log().verbose("Solver {1}", ms->name());
+ log().verbose(" ==> {2} nets", grp.size());
+ log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic");
+ log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep");
+ for (auto &n : grp)
+ {
+ log().verbose("Net {1}", n->name());
+ for (const auto &pcore : n->m_core_terms)
{
- log().verbose("Net {1}", n->name());
- for (const auto &pcore : n->core_terms())
- {
- log().verbose(" {1}", pcore->name());
- }
+ log().verbose(" {1}", pcore->name());
}
-
- m_mat_solvers_all.push_back(ms.get());
- if (ms->has_timestep_devices())
- m_mat_solvers_timestepping.push_back(ms.get());
-
- m_mat_solvers.emplace_back(std::move(ms));
}
+
+ m_mat_solvers.push_back(std::move(ms));
}
+}
- void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp)
+void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp)
+{
+ for (auto & s : m_mat_solvers)
{
- for (auto & s : m_mat_solvers)
- {
- auto r = s->create_solver_code();
- mp[r.first] = r.second; // automatically overwrites identical names
- }
+ auto r = s->create_solver_code();
+ mp[r.first] = r.second; // automatically overwrites identical names
}
+}
- NETLIB_DEVICE_IMPL(solver, "SOLVER", "FREQ")
+ NETLIB_DEVICE_IMPL(solver)
-} // namespace devices
+ } //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h
index c9ec967a72a..986d14f401a 100644
--- a/src/lib/netlist/solver/nld_solver.h
+++ b/src/lib/netlist/solver/nld_solver.h
@@ -8,13 +8,11 @@
#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_
-#include "netlist/nl_base.h"
-#include "nld_matrix_solver.h"
-#include "plib/pstream.h"
-
#include <map>
-#include <memory>
-#include <vector>
+
+#include "../nl_base.h"
+#include "../plib/pstream.h"
+#include "nld_matrix_solver.h"
//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
#define ATTR_ALIGNED(N) ATTR_ALIGN
@@ -25,97 +23,89 @@
namespace netlist
{
-namespace devices
-{
- class NETLIB_NAME(solver);
+ namespace devices
+ {
+class NETLIB_NAME(solver);
- class matrix_solver_t;
- NETLIB_OBJECT(solver)
+class matrix_solver_t;
+
+NETLIB_OBJECT(solver)
+{
+ NETLIB_CONSTRUCTOR(solver)
+ , m_fb_step(*this, "FB_step")
+ , m_Q_step(*this, "Q_step")
+ , m_freq(*this, "FREQ", 48000.0)
+
+ /* iteration parameters */
+ , m_gs_sor(*this, "SOR_FACTOR", 1.059)
+ , m_method(*this, "METHOD", "MAT_CR")
+ , m_accuracy(*this, "ACCURACY", 1e-7)
+ , m_gs_loops(*this, "GS_LOOPS",9) // Gauss-Seidel loops
+
+ /* general parameters */
+ , m_gmin(*this, "GMIN", NETLIST_GMIN_DEFAULT)
+ , m_pivot(*this, "PIVOT", 0) // use pivoting - on supported solvers
+ , m_nr_loops(*this, "NR_LOOPS", 250) // Newton-Raphson loops
+ , m_nr_recalc_delay(*this, "NR_RECALC_DELAY", NLTIME_FROM_NS(10).as_double()) // Delay to next solve attempt if nr loops exceeded
+ , m_parallel(*this, "PARALLEL", 0)
+
+ /* automatic time step */
+ , m_dynamic_ts(*this, "DYNAMIC_TS", 0)
+ , m_dynamic_lte(*this, "DYNAMIC_LTE", 1e-5) // diff/timestep
+ , m_dynamic_min_ts(*this, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_double timestep resolution
+
+ , m_log_stats(*this, "LOG_STATS", 0) // log statistics on shutdown
+ , m_params()
{
- NETLIB_CONSTRUCTOR(solver)
- , m_fb_step(*this, "FB_step")
- , m_Q_step(*this, "Q_step")
- , m_freq(*this, "FREQ", 48000.0)
-
- /* iteration parameters */
- , m_gs_sor(*this, "SOR_FACTOR", 1.059)
- , m_method(*this, "METHOD", "MAT_CR")
- , m_accuracy(*this, "ACCURACY", 1e-7)
- , m_gs_loops(*this, "GS_LOOPS", 9) // Gauss-Seidel loops
-
- /* general parameters */
- , m_gmin(*this, "GMIN", 1e-9)
- , m_pivot(*this, "PIVOT", false) // use pivoting - on supported solvers
- , m_nr_loops(*this, "NR_LOOPS", 250) // Newton-Raphson loops
- , m_nr_recalc_delay(*this, "NR_RECALC_DELAY", NLTIME_FROM_NS(10).as_double()) // Delay to next solve attempt if nr loops exceeded
- , m_parallel(*this, "PARALLEL", 0)
-
- /* automatic time step */
- , m_dynamic_ts(*this, "DYNAMIC_TS", false)
- , m_dynamic_lte(*this, "DYNAMIC_LTE", 1e-5) // diff/timestep
- , m_dynamic_min_ts(*this, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_double timestep resolution
-
- /* special */
- , m_use_gabs(*this, "USE_GABS", true)
- , m_use_linear_prediction(*this, "USE_LINEAR_PREDICTION", false) // // savings are eaten up by effort
-
- , m_log_stats(*this, "LOG_STATS", true) // log statistics on shutdown
- , m_params()
- {
- // internal staff
-
- connect(m_fb_step, m_Q_step);
- }
-
- void post_start();
- void stop();
-
- nl_double gmin() const { return m_gmin(); }
-
- void create_solver_code(std::map<pstring, pstring> &mp);
-
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- // NETLIB_UPDATE_PARAMI();
-
- private:
- logic_input_t m_fb_step;
- logic_output_t m_Q_step;
-
- param_double_t m_freq;
- param_double_t m_gs_sor;
- param_str_t m_method;
- param_double_t m_accuracy;
- param_int_t m_gs_loops;
- param_double_t m_gmin;
- param_logic_t m_pivot;
- param_int_t m_nr_loops;
- param_double_t m_nr_recalc_delay;
- param_int_t m_parallel;
- param_logic_t m_dynamic_ts;
- param_double_t m_dynamic_lte;
- param_double_t m_dynamic_min_ts;
-
- param_logic_t m_use_gabs;
- param_logic_t m_use_linear_prediction;
-
- param_logic_t m_log_stats;
-
- std::vector<pool_owned_ptr<matrix_solver_t>> m_mat_solvers;
- std::vector<matrix_solver_t *> m_mat_solvers_all;
- std::vector<matrix_solver_t *> m_mat_solvers_timestepping;
-
- solver_parameters_t m_params;
-
- template <typename FT, int SIZE>
- pool_owned_ptr<matrix_solver_t> create_solver(std::size_t size, const pstring &solvername);
-
- template <typename FT, int SIZE>
- pool_owned_ptr<matrix_solver_t> create_solver_x(std::size_t size, const pstring &solvername);
- };
-
-} //namespace devices
+ // internal staff
+
+ connect(m_fb_step, m_Q_step);
+ }
+
+ virtual ~NETLIB_NAME(solver)() override;
+
+ void post_start();
+ void stop();
+
+ inline nl_double gmin() { return m_gmin(); }
+
+ void create_solver_code(std::map<pstring, pstring> &mp);
+
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ // NETLIB_UPDATE_PARAMI();
+
+protected:
+ logic_input_t m_fb_step;
+ logic_output_t m_Q_step;
+
+ param_double_t m_freq;
+ param_double_t m_gs_sor;
+ param_str_t m_method;
+ param_double_t m_accuracy;
+ param_int_t m_gs_loops;
+ param_double_t m_gmin;
+ param_logic_t m_pivot;
+ param_int_t m_nr_loops;
+ param_double_t m_nr_recalc_delay;
+ param_int_t m_parallel;
+ param_logic_t m_dynamic_ts;
+ param_double_t m_dynamic_lte;
+ param_double_t m_dynamic_min_ts;
+
+ param_logic_t m_log_stats;
+
+ std::vector<std::unique_ptr<matrix_solver_t>> m_mat_solvers;
+private:
+
+ solver_parameters_t m_params;
+
+ template <std::size_t m_N, std::size_t storage_N>
+ std::unique_ptr<matrix_solver_t> create_solver(std::size_t size, const pstring &solvername);
+};
+
+ } //namespace devices
} // namespace netlist
#endif /* NLD_SOLVER_H_ */
diff --git a/src/lib/netlist/solver/vector_base.h b/src/lib/netlist/solver/vector_base.h
new file mode 100644
index 00000000000..28f5fa0dd44
--- /dev/null
+++ b/src/lib/netlist/solver/vector_base.h
@@ -0,0 +1,144 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * vector_base.h
+ *
+ * Base vector operations
+ *
+ */
+
+#ifndef VECTOR_BASE_H_
+#define VECTOR_BASE_H_
+
+#include <algorithm>
+#include "../plib/pconfig.h"
+
+#if 0
+template <unsigned storage_N>
+struct pvector
+{
+ pvector(unsigned size)
+ : m_N(size) { }
+
+ unsigned size() {
+ if (storage_N)
+ }
+
+ double m_V[storage_N];
+private:
+ unsigned m_N;
+};
+#endif
+
+#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+template<typename T, std::size_t N>
+inline static void vec_set (const std::size_t n, const T scalar, T (& RESTRICT v)[N])
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ v[i] = scalar;
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ v[i] = scalar;
+}
+
+template<typename T, std::size_t N>
+inline static T vec_mult (const std::size_t n, const T (& RESTRICT v1)[N], const T (& RESTRICT v2)[N] )
+{
+ T value = 0.0;
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ value += v1[i] * v2[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ value += v1[i] * v2[i];
+ return value;
+}
+
+template<typename T, std::size_t N>
+inline static T vec_mult2 (const std::size_t n, const T (& RESTRICT v)[N])
+{
+ T value = 0.0;
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ value += v[i] * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ value += v[i] * v[i];
+ return value;
+}
+
+template<typename T, std::size_t N>
+inline static void vec_mult_scalar (const std::size_t n, const T (& RESTRICT v)[N], const T & scalar, T (& RESTRICT result)[N])
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = scalar * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ result[i] = scalar * v[i];
+}
+
+template<typename T, std::size_t N>
+inline static void vec_add_mult_scalar (const std::size_t n, const T (& RESTRICT v)[N], const T scalar, T (& RESTRICT result)[N])
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = result[i] + scalar * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ result[i] = result[i] + scalar * v[i];
+}
+
+template<typename T>
+inline static void vec_add_mult_scalar_p(const std::size_t & n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
+{
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] += scalar * v[i];
+}
+
+inline static void vec_add_ip(const std::size_t n, const double * RESTRICT v, double * RESTRICT result)
+{
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] += v[i];
+}
+
+template<typename T, std::size_t N>
+inline void vec_sub(const std::size_t n, const T (& RESTRICT v1)[N], const T (& RESTRICT v2)[N], T (& RESTRICT result)[N])
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = v1[i] - v2[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ result[i] = v1[i] - v2[i];
+}
+
+template<typename T, std::size_t N>
+inline void vec_scale(const std::size_t n, T (& RESTRICT v)[N], const T scalar)
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ v[i] = scalar * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ v[i] = scalar * v[i];
+}
+
+inline double vec_maxabs(const std::size_t n, const double * RESTRICT v)
+{
+ double ret = 0.0;
+ for ( std::size_t i = 0; i < n; i++ )
+ ret = std::max(ret, std::abs(v[i]));
+
+ return ret;
+}
+#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#pragma GCC diagnostic pop
+#endif
+
+#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 0acf5041c91..bedddba3cda 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -5,20 +5,19 @@
*
*/
-#include "plib/palloc.h"
-#include "nl_convert.h"
-#include "plib/putil.h"
-
#include <algorithm>
#include <cmath>
#include <unordered_map>
+#include "nl_convert.h"
+#include "../plib/palloc.h"
+#include "../plib/putil.h"
/* FIXME: temporarily defined here - should be in a file */
/* FIXME: family logic in netlist is convoluted, create
* define a model param on core device
*/
/* Format: external name,netlist device,model */
-static const char * s_lib_map =
+static const pstring s_lib_map =
"SN74LS00D, TTL_7400_DIP, 74LSXX\n"
"SN74LS04D, TTL_7404_DIP, 74LSXX\n"
"SN74ALS08D, TTL_7408_DIP, 74ALSXX\n"
@@ -43,13 +42,14 @@ using lib_map_t = std::unordered_map<pstring, lib_map_entry>;
static lib_map_t read_lib_map(const pstring &lm)
{
- auto reader = plib::putf8_reader(plib::pistringstream(lm));
+ plib::pistringstream istrm(lm);
+ plib::putf8_reader reader(istrm);
lib_map_t m;
pstring line;
while (reader.readline(line))
{
std::vector<pstring> split(plib::psplit(line, ","));
- m[plib::trim(split[0])] = { plib::trim(split[1]), plib::trim(split[2]) };
+ m[split[0].trim()] = { split[1].trim(), split[2].trim() };
}
return m;
}
@@ -59,7 +59,7 @@ static lib_map_t read_lib_map(const pstring &lm)
-------------------------------------------------*/
nl_convert_base_t::nl_convert_base_t()
- : out(&m_buf)
+ : out(m_buf)
, m_numberchars("0123456789-+e.")
{
}
@@ -82,7 +82,7 @@ void nl_convert_base_t::add_ext_alias(const pstring &alias)
m_ext_alias.push_back(alias);
}
-void nl_convert_base_t::add_device(plib::unique_ptr<dev_t> dev)
+void nl_convert_base_t::add_device(std::unique_ptr<dev_t> dev)
{
for (auto & d : m_devs)
if (d->name() == dev->name())
@@ -106,7 +106,7 @@ void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
add_device(plib::make_unique<dev_t>(atype, aname));
}
-void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname)
+void nl_convert_base_t::add_term(pstring netname, pstring termname)
{
net_t * net = nullptr;
auto idx = m_nets.find(netname);
@@ -130,11 +130,11 @@ void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname
void nl_convert_base_t::dump_nl()
{
- for (auto & alias : m_ext_alias)
+ for (std::size_t i=0; i<m_ext_alias.size(); i++)
{
- net_t *net = m_nets[alias].get();
+ net_t *net = m_nets[m_ext_alias[i]].get();
// use the first terminal ...
- out("ALIAS({}, {})\n", alias.c_str(), net->terminals()[0].c_str());
+ out("ALIAS({}, {})\n", m_ext_alias[i].c_str(), net->terminals()[0].c_str());
// if the aliased net only has this one terminal connected ==> don't dump
if (net->terminals().size() == 1)
net->set_no_export();
@@ -166,6 +166,7 @@ void nl_convert_base_t::dump_nl()
net_t * net = i.second.get();
if (!net->is_no_export())
{
+ //printf("Net {}\n", net->name().c_str());
out("NET_C({}", net->terminals()[0].c_str() );
for (std::size_t j=1; j<net->terminals().size(); j++)
{
@@ -184,25 +185,25 @@ const pstring nl_convert_base_t::get_nl_val(const double val)
{
{
int i = 0;
- while (pstring(m_units[i].m_unit) != "-" )
+ while (pstring(m_units[i].m_unit, pstring::UTF8) != "-" )
{
if (m_units[i].m_mult <= std::abs(val))
break;
i++;
}
- return plib::pfmt(pstring(m_units[i].m_func))(val / m_units[i].m_mult);
+ return plib::pfmt(pstring(m_units[i].m_func, pstring::UTF8))(val / m_units[i].m_mult);
}
}
double nl_convert_base_t::get_sp_unit(const pstring &unit)
{
int i = 0;
- while (pstring(m_units[i].m_unit) != "-")
+ while (pstring(m_units[i].m_unit, pstring::UTF8) != "-")
{
- if (pstring(m_units[i].m_unit) == unit)
+ if (pstring(m_units[i].m_unit, pstring::UTF8) == unit)
return m_units[i].m_mult;
i++;
}
- plib::perrlogger("Unit {} unknown\n", unit);
+ fprintf(stderr, "Unit %s unknown\n", unit.c_str());
return 0.0;
}
@@ -211,9 +212,9 @@ double nl_convert_base_t::get_sp_val(const pstring &sin)
std::size_t p = 0;
while (p < sin.length() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos))
++p;
- pstring val = plib::left(sin, p);
+ pstring val = sin.left(p);
pstring unit = sin.substr(p);
- double ret = get_sp_unit(unit) * plib::pstonum<double>(val);
+ double ret = get_sp_unit(unit) * val.as_double();
return ret;
}
@@ -251,11 +252,11 @@ void nl_convert_spice_t::convert(const pstring &contents)
pstring line = "";
- for (const auto &i : spnl)
+ for (std::size_t i=0; i < spnl.size(); i++)
{
// Basic preprocessing
- pstring inl = plib::ucase(plib::trim(i));
- if (plib::startsWith(inl, "+"))
+ pstring inl = spnl[i].trim().ucase();
+ if (inl.startsWith("+"))
line = line + inl.substr(1);
else
{
@@ -284,13 +285,13 @@ void nl_convert_spice_t::process_line(const pstring &line)
out("// {}\n", line.substr(1).c_str());
break;
case '.':
- if (tt[0] == ".SUBCKT")
+ if (tt[0].equals(".SUBCKT"))
{
out("NETLIST_START({})\n", tt[1].c_str());
for (std::size_t i=2; i<tt.size(); i++)
add_ext_alias(tt[i]);
}
- else if (tt[0] == ".ENDS")
+ else if (tt[0].equals(".ENDS"))
{
dump_nl();
out("NETLIST_END()\n");
@@ -300,16 +301,15 @@ void nl_convert_spice_t::process_line(const pstring &line)
break;
case 'Q':
{
+ bool cerr = false;
/* check for fourth terminal ... should be numeric net
* including "0" or start with "N" (ltspice)
*/
+ ATTR_UNUSED long nval(tt[4].as_long(&cerr));
pstring model;
pstring pins ="CBE";
- bool err;
- auto nval = plib::pstonum_ne<long>(tt[4], err);
- plib::unused_var(nval);
- if ((err || plib::startsWith(tt[4], "N")) && tt.size() > 5)
+ if ((!cerr || tt[4].startsWith("N")) && tt.size() > 5)
model = tt[5];
else
model = tt[4];
@@ -317,8 +317,8 @@ void nl_convert_spice_t::process_line(const pstring &line)
if (m.size() == 2)
{
if (m[1].length() != 4)
- plib::perrlogger("error with model desc {}\n", model);
- pins = plib::left(m[1], 3);
+ fprintf(stderr, "error with model desc %s\n", model.c_str());
+ pins = m[1].left(3);
}
add_device("QBJT_EB", tt[0], m[0]);
add_term(tt[1], tt[0] + "." + pins.at(0));
@@ -327,7 +327,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
}
break;
case 'R':
- if (plib::startsWith(tt[0], "RV"))
+ if (tt[0].startsWith("RV"))
{
val = get_sp_val(tt[4]);
add_device("POT", tt[0], val);
@@ -351,7 +351,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
break;
case 'V':
// just simple Voltage sources ....
- if (tt[2] == "0")
+ if (tt[2].equals("0"))
{
val = get_sp_val(tt[3]);
add_device("ANALOG_INPUT", tt[0], val);
@@ -359,7 +359,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
//add_term(tt[2], tt[0] + ".2");
}
else
- plib::perrlogger("Voltage Source {} not connected to GND\n", tt[0]);
+ fprintf(stderr, "Voltage Source %s not connected to GND\n", tt[0].c_str());
break;
case 'I': // Input pin special notation
{
@@ -381,7 +381,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
// last element is component type
// FIXME: Parameter
- pstring xname = plib::replace_all(tt[0], pstring("."), pstring("_"));
+ pstring xname = tt[0].replace_all(".", "_");
pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP";
add_device(tname, xname);
for (std::size_t i=1; i < tt.size() - 1; i++)
@@ -401,16 +401,16 @@ void nl_convert_spice_t::process_line(const pstring &line)
Eagle converter
-------------------------------------------------*/
-nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &&strm)
- : plib::ptokenizer(std::move(strm))
+nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &strm)
+ : plib::ptokenizer(strm)
, m_convert(convert)
{
- this->identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-")
- .number_chars(".0123456789", "0123456789eE-.") //FIXME: processing of numbers
- .whitespace(pstring("") + ' ' + static_cast<char>(9) + static_cast<char>(10) + static_cast<char>(13))
- /* FIXME: gnetlist doesn't print comments */
- .comment("/*", "*/", "//")
- .string_char('\'');
+ set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
+ set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
+ /* FIXME: gnetlist doesn't print comments */
+ set_comment("/*", "*/", "//");
+ set_string_char('\'');
m_tok_ADD = register_token("ADD");
m_tok_VALUE = register_token("VALUE");
m_tok_SIGNAL = register_token("SIGNAL");
@@ -428,8 +428,9 @@ void nl_convert_eagle_t::tokenizer::verror(const pstring &msg, int line_num, con
//FIXME: should accept a stream as well
void nl_convert_eagle_t::convert(const pstring &contents)
{
-
- tokenizer tok(*this, plib::putf8_reader(plib::pistringstream(contents)));
+ plib::pistringstream istrm(contents);
+ plib::putf8_reader reader(istrm);
+ tokenizer tok(*this, reader);
out("NETLIST_START(dummy)\n");
add_term("GND", "GND");
@@ -486,12 +487,12 @@ void nl_convert_eagle_t::convert(const pstring &contents)
}
break;
case 'P':
- if (plib::ucase(sval) == "HIGH")
+ if (sval.ucase() == "HIGH")
add_device("TTL_INPUT", name, 1);
- else if (plib::ucase(sval) == "LOW")
+ else if (sval.ucase() == "LOW")
add_device("TTL_INPUT", name, 0);
else
- add_device("ANALOG_INPUT", name, plib::pstonum<double>(sval));
+ add_device("ANALOG_INPUT", name, sval.as_double());
add_pin_alias(name, "1", "Q");
break;
case 'D':
@@ -537,16 +538,16 @@ void nl_convert_eagle_t::convert(const pstring &contents)
RINF converter
-------------------------------------------------*/
-nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &&strm)
- : plib::ptokenizer(std::move(strm))
+nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &strm)
+ : plib::ptokenizer(strm)
, m_convert(convert)
{
- this->identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-")
- .number_chars("0123456789", "0123456789eE-.") //FIXME: processing of numbers
- .whitespace(pstring("") + ' ' + static_cast<char>(9) + static_cast<char>(10) + static_cast<char>(13))
- /* FIXME: gnetlist doesn't print comments */
- .comment("","","//") // FIXME:needs to be confirmed
- .string_char('"');
+ set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-");
+ set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
+ /* FIXME: gnetlist doesn't print comments */
+ set_comment("","","//"); // FIXME:needs to be confirmed
+ set_string_char('"');
m_tok_HEA = register_token(".HEA");
m_tok_APP = register_token(".APP");
m_tok_TIM = register_token(".TIM");
@@ -576,7 +577,9 @@ void nl_convert_rinf_t::tokenizer::verror(const pstring &msg, int line_num, cons
void nl_convert_rinf_t::convert(const pstring &contents)
{
- tokenizer tok(*this, plib::putf8_reader(plib::pistringstream(contents)));
+ plib::pistringstream istrm(contents);
+ plib::putf8_reader reader(istrm);
+ tokenizer tok(*this, reader);
auto lm = read_lib_map(s_lib_map);
out("NETLIST_START(dummy)\n");
diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h
index 5cdae8e372d..d3881320678 100644
--- a/src/lib/netlist/tools/nl_convert.h
+++ b/src/lib/netlist/tools/nl_convert.h
@@ -10,12 +10,10 @@
#ifndef NL_CONVERT_H_
#define NL_CONVERT_H_
-#include "plib/plists.h"
-#include "plib/pparser.h"
-#include "plib/pstring.h"
-#include "plib/ptypes.h"
-
#include <memory>
+#include "../plib/pstring.h"
+#include "../plib/plists.h"
+#include "../plib/pparser.h"
/*-------------------------------------------------
convert - convert a spice netlist
@@ -25,8 +23,6 @@ class nl_convert_base_t
{
public:
- COPYASSIGNMOVE(nl_convert_base_t, delete)
-
virtual ~nl_convert_base_t();
const pstring &result() { return m_buf.str(); }
@@ -44,7 +40,7 @@ protected:
void add_device(const pstring &atype, const pstring &aname, double aval);
void add_device(const pstring &atype, const pstring &aname);
- void add_term(const pstring &netname, const pstring &termname);
+ void add_term(pstring netname, pstring termname);
void dump_nl();
@@ -59,8 +55,8 @@ private:
struct net_t
{
public:
- explicit net_t(pstring aname)
- : m_name(std::move(aname)), m_no_export(false) {}
+ explicit net_t(const pstring &aname)
+ : m_name(aname), m_no_export(false) {}
const pstring &name() { return m_name;}
std::vector<pstring> &terminals() { return m_terminals; }
@@ -76,28 +72,16 @@ private:
struct dev_t
{
public:
- dev_t(pstring atype, pstring aname, pstring amodel)
- : m_type(std::move(atype))
- , m_name(std::move(aname))
- , m_model(std::move(amodel))
- , m_val(0)
- , m_has_val(false)
+ dev_t(const pstring &atype, const pstring &aname, const pstring &amodel)
+ : m_type(atype), m_name(aname), m_model(amodel), m_val(0), m_has_val(false)
{}
- dev_t(pstring atype, pstring aname, double aval)
- : m_type(std::move(atype))
- , m_name(std::move(aname))
- , m_model("")
- , m_val(aval)
- , m_has_val(true)
+ dev_t(const pstring &atype, const pstring &aname, double aval)
+ : m_type(atype), m_name(aname), m_model(""), m_val(aval), m_has_val(true)
{}
- dev_t(pstring atype, pstring aname)
- : m_type(std::move(atype))
- , m_name(std::move(aname))
- , m_model("")
- , m_val(0.0)
- , m_has_val(false)
+ dev_t(const pstring &atype, const pstring &aname)
+ : m_type(atype), m_name(aname), m_model(""), m_val(0.0), m_has_val(false)
{}
const pstring &name() { return m_name;}
@@ -125,8 +109,8 @@ private:
struct pin_alias_t
{
public:
- pin_alias_t(pstring name, pstring alias)
- : m_name(std::move(name)), m_alias(std::move(alias))
+ pin_alias_t(const pstring &name, const pstring &alias)
+ : m_name(name), m_alias(alias)
{}
const pstring &name() { return m_name; }
const pstring &alias() { return m_alias; }
@@ -137,14 +121,14 @@ private:
private:
- void add_device(plib::unique_ptr<dev_t> dev);
+ void add_device(std::unique_ptr<dev_t> dev);
plib::postringstream m_buf;
- std::vector<plib::unique_ptr<dev_t>> m_devs;
- std::unordered_map<pstring, plib::unique_ptr<net_t> > m_nets;
+ std::vector<std::unique_ptr<dev_t>> m_devs;
+ std::unordered_map<pstring, std::unique_ptr<net_t> > m_nets;
std::vector<pstring> m_ext_alias;
- std::unordered_map<pstring, plib::unique_ptr<pin_alias_t>> m_pins;
+ std::unordered_map<pstring, std::unique_ptr<pin_alias_t>> m_pins;
static unit_t m_units[];
pstring m_numberchars;
@@ -156,6 +140,9 @@ class nl_convert_spice_t : public nl_convert_base_t
public:
nl_convert_spice_t() : nl_convert_base_t() {}
+ virtual ~nl_convert_spice_t() override
+ {
+ }
void convert(const pstring &contents) override;
@@ -172,11 +159,14 @@ class nl_convert_eagle_t : public nl_convert_base_t
public:
nl_convert_eagle_t() : nl_convert_base_t() {}
+ virtual ~nl_convert_eagle_t() override
+ {
+ }
class tokenizer : public plib::ptokenizer
{
public:
- tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &&strm);
+ tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &strm);
token_id_t m_tok_ADD;
token_id_t m_tok_VALUE;
@@ -185,7 +175,7 @@ public:
protected:
- void verror(const pstring &msg, int line_num, const pstring &line) override;
+ virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
private:
nl_convert_eagle_t &m_convert;
@@ -205,11 +195,14 @@ class nl_convert_rinf_t : public nl_convert_base_t
public:
nl_convert_rinf_t() : nl_convert_base_t() {}
+ virtual ~nl_convert_rinf_t() override
+ {
+ }
class tokenizer : public plib::ptokenizer
{
public:
- tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &&strm);
+ tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &strm);
token_id_t m_tok_HEA;
token_id_t m_tok_APP;
@@ -223,7 +216,7 @@ public:
protected:
- void verror(const pstring &msg, int line_num, const pstring &line) override;
+ virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
private:
nl_convert_rinf_t &m_convert;