summaryrefslogtreecommitdiffstats
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, 11668 insertions, 8552 deletions
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index 6f4a2db86bf..aef920635fe 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -5,47 +5,49 @@
*
*/
-#include "../solver/nld_solver.h"
+#include "netlist/solver/nld_solver.h"
+#include "netlist/nl_setup.h"
#include "nlid_twoterm.h"
-#include "../nl_setup.h"
+
#include <cmath>
namespace netlist
{
- namespace analog
- {
-
-class diode
+namespace analog
{
-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); }
+ using constants = plib::constants<nl_double>;
-private:
- nl_double m_Is;
- nl_double m_VT;
- nl_double m_VT_inv;
-};
+ 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)
+ {
+ 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;
+ };
-// -----------------------------------------------------------------------------
-// nld_Q - Base classes
-// -----------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------
+ // nld_Q - Base classes
+ // -----------------------------------------------------------------------------
/*! Class representing the bjt model paramers.
*
@@ -73,7 +75,7 @@ private:
* | | RBM | minimum base resistance at high currents | | RB | 10 | * |
* | | RE | emitter resistance | | 0 | 1 | * |
* | | RC | collector resistance | | 0 | 10 | * |
- * | | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | Y | 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 | |
@@ -81,7 +83,7 @@ private:
* | | 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 | | |
- * | | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | Y | 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 | | |
@@ -95,343 +97,369 @@ private:
* | | 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_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")
{}
- 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_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
+
};
// Have a common start for transistors
-NETLIB_OBJECT(Q)
-{
-public:
- enum q_type {
- BJT_NPN,
- BJT_PNP
+ 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_CONSTRUCTOR(Q)
- , m_model(*this, "MODEL", "NPN")
- , m_qtype(BJT_NPN)
+ NETLIB_OBJECT_DERIVED(QBJT, Q)
{
- }
-
- NETLIB_IS_DYNAMIC(true)
-
- //NETLIB_RESETI();
- NETLIB_UPDATEI();
+ public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
+ { }
- 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:
+ protected:
- bjt_model_t m_model;
-private:
- q_type m_qtype;
-};
+ private:
+ };
-NETLIB_OBJECT_DERIVED(QBJT, Q)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
- { }
-protected:
-private:
-};
+ // -----------------------------------------------------------------------------
+ // nld_QBJT_switch
+ // -----------------------------------------------------------------------------
+ /*
+ * + - C
+ * B ----VVV----+ |
+ * | |
+ * Rb Rc
+ * Rb Rc
+ * Rb Rc
+ * | |
+ * +----+----+
+ * |
+ * E
+ */
-// -----------------------------------------------------------------------------
-// nld_QBJT_switch
-// -----------------------------------------------------------------------------
+ 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
+ // -----------------------------------------------------------------------------
-/*
- * + - 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)
+ NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
{
- 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);
+ 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_term("_B1", m_BC_dummy.m_P);
- //register_term("_C1", m_BC_dummy.m_N);
- connect(m_RB.m_N, m_RC.m_N);
+ // ----------------------------------------------------------------------------------------
+ // nld_Q
+ // ----------------------------------------------------------------------------------------
- connect(m_RB.m_P, m_BC_dummy.m_P);
- connect(m_RC.m_P, m_BC_dummy.m_N);
+ NETLIB_UPDATE(Q)
+ {
+ // netlist().solver()->schedule1();
}
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- nld_twoterm m_RB;
- nld_twoterm m_RC;
-
- // FIXME: this is needed so we have all terminals belong to one net list
+ // ----------------------------------------------------------------------------------------
+ // nld_QBJT_switch
+ // ----------------------------------------------------------------------------------------
- nld_twoterm m_BC_dummy;
-
-protected:
+ NETLIB_RESET(QBJT_switch)
+ {
+ NETLIB_NAME(Q)::reset();
- 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;
+ m_state_on = 0;
-private:
-};
+ m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
+ m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
-// -----------------------------------------------------------------------------
-// nld_QBJT_EB
-// -----------------------------------------------------------------------------
+ m_BC_dummy.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
+ }
-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)
+ NETLIB_UPDATE(QBJT_switch)
{
- 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);
+ 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
}
-protected:
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- generic_diode m_gD_BC;
- generic_diode m_gD_BE;
-
-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
-
- nl_double m_alpha_f;
- nl_double m_alpha_r;
-
-};
-
-
-// ----------------------------------------------------------------------------------------
-// nld_Q
-// ----------------------------------------------------------------------------------------
-
-NETLIB_UPDATE(Q)
-{
-// netlist().solver()->schedule1();
-}
-
-// ----------------------------------------------------------------------------------------
-// nld_QBJT_switch
-// ----------------------------------------------------------------------------------------
-
-
-NETLIB_RESET(QBJT_switch)
-{
- NETLIB_NAME(Q)::reset();
- m_state_on = 0;
-
- 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_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_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
-}
+ set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ nl_double alpha = BF / (1.0 + BF);
-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);
+ diode d(IS, NF);
- set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ // Assume 5mA Collector current for switch operation
- nl_double alpha = BF / (1.0 + BF);
+ m_V = d.V(0.005 / alpha);
- diode d(IS, NF);
+ /* Base current is 0.005 / beta
+ * as a rough estimate, we just scale the conductance down */
- // Assume 5mA Collector current for switch operation
+ m_gB = 1.0 / (m_V/(0.005 / BF));
- m_V = d.V(0.005 / alpha);
+ //m_gB = d.gI(0.005 / alpha);
- /* Base current is 0.005 / beta
- * as a rough estimate, we just scale the conductance down */
+ if (m_gB < exec().gmin())
+ m_gB = exec().gmin();
+ m_gC = d.gI(0.005); // very rough estimate
+ }
- m_gB = 1.0 / (m_V/(0.005 / BF));
+ 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;
+ }
+ }
- //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
-}
+ // ----------------------------------------------------------------------------------------
+ // nld_Q - Ebers Moll
+ // ----------------------------------------------------------------------------------------
-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)
+ NETLIB_UPDATE(QBJT_EB)
{
- 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;
+ 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);
+ }
-// ----------------------------------------------------------------------------------------
-// nld_Q - Ebers Moll
-// ----------------------------------------------------------------------------------------
+ }
+ 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(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();
-}
-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);
+ 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);
- set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ 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);
+ 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());
-}
+ 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());
+ }
- } //namespace analog
+} // namespace analog
- namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB)
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch)
- }
+namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB, "QBJT_EB", "MODEL")
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch, "QBJT_SW", "MODEL")
+} // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_bjt.h b/src/lib/netlist/analog/nld_bjt.h
index 9e1f82afbaa..3a8478f19f7 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_fourterm.h b/src/lib/netlist/analog/nld_fourterm.h
index b4bb5db1059..66c47c0be29 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp
new file mode 100644
index 00000000000..ea717fdefee
--- /dev/null
+++ b/src/lib/netlist/analog/nld_mosfet.cpp
@@ -0,0 +1,488 @@
+// 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
new file mode 100644
index 00000000000..32011d709d8
--- /dev/null
+++ b/src/lib/netlist/analog/nld_mosfet.h
@@ -0,0 +1,21 @@
+// 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 5f55a26f5d0..8c3c655bfa9 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 "../nl_base.h"
-#include "../nl_errstr.h"
-#include "nlid_twoterm.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_errstr.h"
#include "nlid_fourterm.h"
+#include "nlid_twoterm.h"
#include <cmath>
@@ -129,10 +129,10 @@ namespace netlist
}
else if (m_type == 3)
{
- 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)");
+ 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)");
//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.do_reset();
+ m_G1.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->do_reset();
- m_DP->do_reset();
- m_DN->do_reset();
- m_CP->do_reset();
- m_RP.do_reset();
+ m_EBUF->reset();
+ m_DP->reset();
+ m_DN->reset();
+ m_CP->reset();
+ m_RP.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)
- }
+ NETLIB_DEVICE_IMPL_NS(analog, opamp, "OPAMP", "MODEL")
+ } // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_opamps.h b/src/lib/netlist/analog/nld_opamps.h
index d05a19aa3dc..4a07f646587 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp
index 1575551f260..0e62fe13952 100644
--- a/src/lib/netlist/analog/nld_switches.cpp
+++ b/src/lib/netlist/analog/nld_switches.cpp
@@ -6,10 +6,13 @@
*/
#include "nlid_twoterm.h"
-#include "../nl_base.h"
-#include "../nl_factory.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_factory.h"
+#include "netlist/solver/nld_solver.h"
-#define R_OFF (1.0 / netlist().gmin())
+/* FIXME : convert to parameters */
+
+#define R_OFF (1.0 / exec().gmin())
#define R_ON 0.01
namespace netlist
@@ -24,7 +27,7 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(switch1)
, m_R(*this, "R")
- , m_POS(*this, "POS", 0)
+ , m_POS(*this, "POS", false)
{
register_subalias("1", m_R.m_P);
register_subalias("2", m_R.m_N);
@@ -46,6 +49,11 @@ namespace netlist
NETLIB_UPDATE(switch1)
{
+ }
+
+ NETLIB_UPDATE_PARAM(switch1)
+ {
+ m_R.solve_now();
if (!m_POS())
{
m_R.set_R(R_OFF);
@@ -54,13 +62,8 @@ namespace netlist
{
m_R.set_R(R_ON);
}
+ m_R.solve_later();
- m_R.update_dev();
- }
-
- NETLIB_UPDATE_PARAM(switch1)
- {
- update();
}
// ----------------------------------------------------------------------------------------
@@ -72,7 +75,7 @@ namespace netlist
NETLIB_CONSTRUCTOR(switch2)
, m_R1(*this, "R1")
, m_R2(*this, "R2")
- , m_POS(*this, "POS", 0)
+ , m_POS(*this, "POS", false)
{
connect(m_R1.m_N, m_R2.m_N);
@@ -110,19 +113,31 @@ namespace netlist
m_R2.set_R(R_ON);
}
- m_R1.update_dev();
- m_R2.update_dev();
+ //m_R1.update_dev(time);
+ //m_R2.update_dev(time);
}
NETLIB_UPDATE_PARAM(switch2)
{
- update();
+ 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();
}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, switch1)
- NETLIB_DEVICE_IMPL_NS(analog, switch2)
- }
+ NETLIB_DEVICE_IMPL_NS(analog, switch1, "SWITCH", "")
+ NETLIB_DEVICE_IMPL_NS(analog, switch2, "SWITCH2", "")
+ } // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_switches.h b/src/lib/netlist/analog/nld_switches.h
index 3cd561f84b1..7aa31c925ae 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index d5cf6f6d228..b175f40af97 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/analog/nlid_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp
index aa2723fe8e1..7fa6a2f3809 100644
--- a/src/lib/netlist/analog/nlid_fourterm.cpp
+++ b/src/lib/netlist/analog/nlid_fourterm.cpp
@@ -5,8 +5,8 @@
*
*/
-#include "../solver/nld_solver.h"
-#include "../nl_factory.h"
+#include "netlist/solver/nld_solver.h"
+#include "netlist/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 = NL_FCONST(1.0) / m_RI();
+ const nl_double GI = plib::constants<nl_double>::one() / m_RI();
- m_IP.set(GI);
- m_IN.set(GI);
+ m_IP.set_conductivity(GI);
+ m_IN.set_conductivity(GI);
- m_OP.set(m_mult, NL_FCONST(0.0));
- m_OP1.set(-m_mult, NL_FCONST(0.0));
+ 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_ON.set(-m_mult, NL_FCONST(0.0));
- m_ON1.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());
}
NETLIB_UPDATE(VCCS)
@@ -63,11 +63,6 @@ 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
@@ -84,11 +79,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(beta, NL_FCONST(0.0), I);
- m_OP1.set(-beta, NL_FCONST(0.0));
+ 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_ON.set(-beta, NL_FCONST(0.0), -I);
- m_ON1.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());
}
// ----------------------------------------------------------------------------------------
@@ -105,30 +100,25 @@ NETLIB_UPDATE_PARAM(CCCS)
NETLIB_NAME(VCCS)::update_param();
}
-NETLIB_UPDATE(CCCS)
-{
- NETLIB_NAME(VCCS)::update();
-}
-
// ----------------------------------------------------------------------------------------
// nld_VCVS
// ----------------------------------------------------------------------------------------
NETLIB_RESET(VCVS)
{
- m_gfac = NL_FCONST(1.0) / m_RO();
+ m_gfac = plib::constants<nl_double>::one() / m_RO();
NETLIB_NAME(VCCS)::reset();
- m_OP2.set(NL_FCONST(1.0) / m_RO());
- m_ON2.set(NL_FCONST(1.0) / m_RO());
+ m_OP2.set_conductivity(plib::constants<nl_double>::one() / m_RO());
+ m_ON2.set_conductivity(plib::constants<nl_double>::one() / m_RO());
}
} //namespace analog
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)
- }
+ 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
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h
index 641fc72427b..5ca6a747116 100644
--- a/src/lib/netlist/analog/nlid_fourterm.h
+++ b/src/lib/netlist/analog/nlid_fourterm.h
@@ -8,7 +8,8 @@
#ifndef NLID_FOURTERM_H_
#define NLID_FOURTERM_H_
-#include "../nl_base.h"
+#include "netlist/nl_base.h"
+#include "plib/putil.h"
namespace netlist {
namespace analog {
@@ -40,39 +41,32 @@ namespace netlist {
NETLIB_CONSTRUCTOR(VCCS)
, m_G(*this, "G", 1.0)
, m_RI(*this, "RI", 1e9)
- , 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_OP(*this, "OP", &m_IP)
+ , m_ON(*this, "ON", &m_IP)
+ , m_IP(*this, "IP", &m_IN) // <= this should be NULL and terminal be filtered out prior to solving...
+ , m_IN(*this, "IN", &m_IP) // <= this should be NULL and terminal be filtered out prior to solving...
+ , m_OP1(*this, "_OP1", &m_IN)
+ , m_ON1(*this, "_ON1", &m_IN)
, m_gfac(1.0)
{
- m_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 = NL_FCONST(1.0);
+ m_gfac = plib::constants<nl_double>::one();
}
+ 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;
@@ -98,14 +92,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;
};
@@ -137,12 +131,13 @@ namespace netlist {
public:
NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
{
- m_gfac = NL_FCONST(1.0) / m_RI();
+ m_gfac = plib::constants<nl_double>::one() / m_RI();
}
- protected:
- NETLIB_UPDATEI();
NETLIB_RESETI();
+
+ protected:
+ //NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
};
@@ -180,29 +175,28 @@ namespace netlist {
public:
NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
, m_RO(*this, "RO", 1.0)
- , m_OP2(*this, "_OP2")
- , m_ON2(*this, "_ON2")
+ , m_OP2(*this, "_OP2", &m_ON2)
+ , m_ON2(*this, "_ON2", &m_OP2)
{
- 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;
- protected:
+ private:
//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 f54c2b3e68f..5019c98c0e4 100644
--- a/src/lib/netlist/analog/nlid_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -5,10 +5,10 @@
*
*/
-#include "../solver/nld_solver.h"
+#include "netlist/solver/nld_solver.h"
+#include "netlist/nl_factory.h"
#include "nlid_twoterm.h"
-#include "../nl_factory.h"
#include <cmath>
@@ -16,81 +16,34 @@ namespace netlist
{
namespace analog
{
+
// ----------------------------------------------------------------------------------------
-// generic_diode
+// nld_twoterm
// ----------------------------------------------------------------------------------------
-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)
-{
- set_param(1e-15, 1, 1e-15);
-}
-
-void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double gmin)
+void NETLIB_NAME(twoterm)::solve_now()
{
- 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;
+ /* 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();
}
-void generic_diode::update_diode(const nl_double nVd)
+void NETLIB_NAME(twoterm)::solve_later(netlist_time delay)
{
- 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;
- }
+ /* 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);
}
-// ----------------------------------------------------------------------------------------
-// nld_twoterm
-// ----------------------------------------------------------------------------------------
NETLIB_UPDATE(twoterm)
{
/* only called if connected to a rail net ==> notify the solver to recalculate */
- /* 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();
+ solve_now();
}
// ----------------------------------------------------------------------------------------
@@ -100,12 +53,7 @@ NETLIB_UPDATE(twoterm)
NETLIB_RESET(R_base)
{
NETLIB_NAME(twoterm)::reset();
- set_R(1.0 / netlist().gmin());
-}
-
-NETLIB_UPDATE(R_base)
-{
- NETLIB_NAME(twoterm)::update();
+ set_R(1.0 / exec().gmin());
}
// ----------------------------------------------------------------------------------------
@@ -114,14 +62,14 @@ NETLIB_UPDATE(R_base)
NETLIB_UPDATE_PARAM(R)
{
- update_dev();
- set_R(std::max(m_R(), netlist().gmin()));
+ solve_now();
+ set_R(std::max(m_R(), exec().gmin()));
}
NETLIB_RESET(R)
{
NETLIB_NAME(twoterm)::reset();
- set_R(std::max(m_R(), netlist().gmin()));
+ set_R(std::max(m_R(), exec().gmin()));
}
// ----------------------------------------------------------------------------------------
@@ -134,21 +82,22 @@ 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, netlist().gmin()));
- m_R2.set_R(std::max(m_R() * (NL_FCONST(1.0) - v), netlist().gmin()));
+ 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()));
}
NETLIB_UPDATE_PARAM(POT)
{
- m_R1.update_dev();
- m_R2.update_dev();
+ m_R1.solve_now();
+ m_R2.solve_now();
nl_double v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
-
- 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()));
+ 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()));
}
@@ -164,13 +113,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, netlist().gmin()));
+ m_R1.set_R(std::max(m_R() * v, exec().gmin()));
}
NETLIB_UPDATE_PARAM(POT2)
{
- m_R1.update_dev();
+ m_R1.solve_now();
nl_double v = m_Dial();
@@ -178,38 +127,7 @@ 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, 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);
+ m_R1.set_R(std::max(m_R() * v, exec().gmin()));
}
// ----------------------------------------------------------------------------------------
@@ -218,9 +136,9 @@ NETLIB_TIMESTEP(C)
NETLIB_RESET(L)
{
- m_GParallel = netlist().gmin();
+ m_gmin = exec().gmin();
m_I = 0.0;
- m_G = m_GParallel;
+ m_G = m_gmin;
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);
@@ -230,16 +148,11 @@ 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_GParallel;
+ m_G = step / m_L() + m_gmin;
set_mat( m_G, -m_G, -m_I,
-m_G, m_G, m_I);
//set(m_G, 0.0, m_I);
@@ -254,8 +167,8 @@ NETLIB_RESET(D)
nl_double Is = m_model.m_IS;
nl_double n = m_model.m_N;
- m_D.set_param(Is, n, netlist().gmin());
- set(m_D.G(), 0.0, m_D.Ieq());
+ m_D.set_param(Is, n, exec().gmin(), constants::T0());
+ set_G_V_I(m_D.G(), 0.0, m_D.Ieq());
}
NETLIB_UPDATE_PARAM(D)
@@ -263,12 +176,7 @@ NETLIB_UPDATE_PARAM(D)
nl_double Is = m_model.m_IS;
nl_double n = m_model.m_N;
- m_D.set_param(Is, n, netlist().gmin());
-}
-
-NETLIB_UPDATE(D)
-{
- NETLIB_NAME(twoterm)::update();
+ m_D.set_param(Is, n, exec().gmin(), constants::T0());
}
NETLIB_UPDATE_TERMINALS(D)
@@ -281,65 +189,18 @@ 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)
- 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)
- }
+ 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
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h
index 7778f5f4585..470fb35c96e 100644
--- a/src/lib/netlist/analog/nlid_twoterm.h
+++ b/src/lib/netlist/analog/nlid_twoterm.h
@@ -33,8 +33,12 @@
#ifndef NLID_TWOTERM_H_
#define NLID_TWOTERM_H_
-#include "../nl_base.h"
-#include "../plib/pfunction.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
+#include "netlist/solver/nld_solver.h"
+#include "plib/pfunction.h"
+
+#include <cmath>
// -----------------------------------------------------------------------------
// Implementation
@@ -48,14 +52,27 @@ 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(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
+ , 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.m_otherterm = &m_N;
- m_N.m_otherterm = &m_P;
}
terminal_t m_P;
@@ -63,36 +80,36 @@ NETLIB_OBJECT(twoterm)
//NETLIB_UPDATE_TERMINALSI() { }
//NETLIB_RESETI() { }
- NETLIB_UPDATEI();
public:
- /* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
+
+ 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)
{
/* GO, GT, I */
- m_P.set( G, G, ( V) * G - I);
- m_N.set( G, G, ( -V) * G + I);
+ m_P.set_go_gt_I( -G, G, ( V) * G - I);
+ m_N.set_go_gt_I( -G, G, ( -V) * G + I);
}
- /* inline */ nl_double deltaV() const
+ 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 r1,
- const nl_double a21, const nl_double a22, const nl_double r2)
+ 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)
{
/* GO, GT, I */
- m_P.set(-a12, a11, r1);
- m_N.set(-a21, a22, r2);
+ m_P.set_go_gt_I(a12, a11, rhs1);
+ m_N.set_go_gt_I(a21, a22, rhs2);
}
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;
- }
};
@@ -106,17 +123,17 @@ NETLIB_OBJECT_DERIVED(R_base, twoterm)
{
}
-public:
- inline void set_R(const nl_double R)
+ void set_R(const nl_double R)
{
- const nl_double G = NL_FCONST(1.0) / R;
+ const nl_double G = plib::constants<nl_double>::one() / R;
set_mat( G, -G, 0.0,
-G, G, 0.0);
}
-protected:
NETLIB_RESETI();
- NETLIB_UPDATEI();
+
+protected:
+ //NETLIB_UPDATEI();
};
@@ -127,7 +144,6 @@ NETLIB_OBJECT_DERIVED(R, R_base)
{
}
- param_double_t m_R;
protected:
@@ -136,6 +152,7 @@ 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;
};
@@ -151,7 +168,8 @@ NETLIB_OBJECT(POT)
, m_R2(*this, "_R2")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", 0)
+ , m_DialIsLog(*this, "DIALLOG", false)
+ , m_Reverse(*this, "REVERSE", false)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
@@ -172,6 +190,7 @@ private:
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
+ param_logic_t m_Reverse;
};
NETLIB_OBJECT(POT2)
@@ -180,8 +199,8 @@ NETLIB_OBJECT(POT2)
, m_R1(*this, "_R1")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", 0)
- , m_Reverse(*this, "REVERSE", 0)
+ , m_DialIsLog(*this, "DIALLOG", false)
+ , m_Reverse(*this, "REVERSE", false)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
@@ -201,6 +220,83 @@ 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
@@ -211,25 +307,45 @@ NETLIB_OBJECT_DERIVED(C, twoterm)
public:
NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
, m_C(*this, "C", 1e-6)
- , m_GParallel(0.0)
+ , m_cap(*this, "m_cap")
{
- //register_term("1", m_P);
- //register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
- NETLIB_TIMESTEPI();
+ 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);
+ }
param_double_t m_C;
+ NETLIB_RESETI()
+ {
+ m_cap.setparams(exec().gmin());
+ }
protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
+ //NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI() { }
private:
- nl_double m_GParallel;
-
+ generic_capacitor<capacitor_e::CHARGE_CONSERVING> m_cap;
+ //generic_capacitor<capacitor_e::CONSTANT_CAPACITY> m_cap;
};
// -----------------------------------------------------------------------------
@@ -241,7 +357,7 @@ NETLIB_OBJECT_DERIVED(L, twoterm)
public:
NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
, m_L(*this, "L", 1e-6)
- , m_GParallel(0.0)
+ , m_gmin(0.0)
, m_G(0.0)
, m_I(0.0)
{
@@ -251,16 +367,16 @@ public:
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
-
- param_double_t m_L;
+ NETLIB_RESETI();
protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
+ //NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
- nl_double m_GParallel;
+ param_double_t m_L;
+
+ nl_double m_gmin;
nl_double m_G;
nl_double m_I;
};
@@ -269,14 +385,82 @@ 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, pstring name);
+ 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;
- void update_diode(const double nVd);
+ 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 set_param(const double Is, const double n, double gmin);
double I() const { return m_Id; }
double G() const { return m_G; }
@@ -367,15 +551,15 @@ public:
NETLIB_IS_DYNAMIC(true)
NETLIB_UPDATE_TERMINALSI();
-
- diode_model_t m_model;
+ NETLIB_RESETI();
protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
+ //NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
- generic_diode m_D;
+private:
+ diode_model_t m_model;
+ generic_diode<diode_e::BIPOLAR> m_D;
};
@@ -389,10 +573,11 @@ 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->netlist().state())
+ , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@@ -401,12 +586,26 @@ public:
}
NETLIB_IS_TIMESTEP(m_func() != "")
- NETLIB_TIMESTEPI();
+
+ NETLIB_TIMESTEPI()
+ {
+ m_t += step;
+ this->set_G_V_I(1.0 / m_R(),
+ m_compiled.evaluate(std::vector<double>({m_t})),
+ 0.0);
+ }
protected:
- NETLIB_UPDATEI();
- NETLIB_RESETI();
+ // 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);
+ }
+private:
+ state_var<double> m_t;
param_double_t m_R;
param_double_t m_V;
param_str_t m_func;
@@ -421,9 +620,10 @@ 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->netlist().state())
+ , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@@ -432,19 +632,33 @@ public:
}
NETLIB_IS_TIMESTEP(m_func() != "")
- NETLIB_TIMESTEPI();
+ 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);
+ }
+
protected:
- NETLIB_UPDATEI();
- NETLIB_RESETI();
+ //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());
+ }
+private:
+ state_var<double> m_t;
param_double_t m_I;
param_str_t m_func;
plib::pfunction m_compiled;
};
- } //namespace devices
+ } // namespace analog
} // namespace netlist
#endif /* NLD_TWOTERM_H_ */
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 807ddbd6c7a..647c7df6f12 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -12,6 +12,27 @@
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
@@ -23,7 +44,7 @@ endif
# LTO = -flto=4 -fuse-linker-plugin -flto-partition=balanced -Wodr
-CFLAGS = $(LTO) -g -O3 -std=c++11 -march=native -I../.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter $(CEXTRAFLAGS)
+CFLAGS = $(LTO) -g -O3 -std=c++11 -I$(CURDIR)/.. -I$(CURDIR)/../.. $(CEXTRAFLAGS)
LDFLAGS = $(LTO) -g -O3 -std=c++11 $(LDEXTRAFLAGS)
LIBS = -lpthread -ldl
@@ -32,6 +53,7 @@ LD = @g++
MD = @mkdir
RM = @rm
DOXYGEN = @doxygen
+CLANG_TIDY = clang-tidy-9
TARGETS = nltool nlwav
@@ -53,7 +75,6 @@ OBJS = $(POBJS) $(NLOBJS)
POBJS := \
$(POBJ)/pstring.o \
- $(POBJ)/palloc.o \
$(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
$(POBJ)/pexception.o \
@@ -73,6 +94,7 @@ 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 \
@@ -92,6 +114,7 @@ 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 \
@@ -153,10 +176,12 @@ 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
+MAKEFILE_TARGETS_WITHOUT_INCLUDE := clean doc clang mingw nvcc
# git archive HEAD --prefix=project-name-version/ \
@@ -200,19 +225,33 @@ maketree: $(sort $(OBJDIRS))
# Special targets
#-------------------------------------------------
-.PHONY: clang clang-5 mingw doc
+.PHONY: clang clang-5 mingw doc native
+
+native:
+ $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
clang:
- $(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"
+ $(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"
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" \
@@ -237,7 +276,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
@@ -248,6 +287,18 @@ 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
#-------------------------------------------------
@@ -268,3 +319,15 @@ $(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 e0f0277daac..c0353f2489a 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -9,152 +9,159 @@
****************************************************************************/
#include "net_lib.h"
-#include "../nl_factory.h"
-#include "../solver/nld_solver.h"
+#include "netlist/nl_factory.h"
+#include "netlist/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 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) }
+#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) }
namespace netlist
{
- namespace devices
- {
- void initialize_factory(factory::list_t &factory)
+namespace devices
{
- 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
+ void initialize_factory(factory::list_t &factory)
+ {
+ 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)
+ }
+
+} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index 4dead624fc2..abf58ccee16 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -35,18 +35,8 @@
#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"
@@ -60,21 +50,32 @@
#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_ne555.h"
#include "nld_mm5837.h"
+#include "nld_ne555.h"
#include "nld_r2r_dac.h"
@@ -84,16 +85,17 @@
#include "nld_log.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 "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 "nld_legacy.h"
#endif
diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp
index 5296bf2d029..0ec7132b401 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 "../nl_base.h"
+#include "netlist/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_var<uint8_t[128]> m_ram; // 1024x1 bits
+ state_array<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)
- NETLIB_DEVICE_IMPL(2102A_dip)
+ 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","")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2102A.h b/src/lib/netlist/devices/nld_2102A.h
index 52d892d4d40..aa53efde47d 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 "../nl_setup.h"
+#include "netlist/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 cb53d60e205..b021bc95003 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -92,8 +92,8 @@ namespace netlist
m_D[i].push((d >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(2716)
- NETLIB_DEVICE_IMPL(2716_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2716.h b/src/lib/netlist/devices/nld_2716.h
index f4776242e6a..363086d6a37 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 "../nl_setup.h"
+#include "netlist/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 8403d42bef2..13518f9d3cb 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();
}
- inline NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const unsigned cnt))
+ NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const unsigned cnt))
{
- /* static */ const netlist_time out_delayQn[14] = {
+ static constexpr const std::array<netlist_time, 14> out_delayQn = {
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,7 +113,8 @@ namespace netlist
m_Q[i].push((cnt >> i) & 1, out_delayQn[i]);
}
- NETLIB_DEVICE_IMPL(CD4020)
+ NETLIB_DEVICE_IMPL(CD4020, "CD4020", "")
+ NETLIB_DEVICE_IMPL_ALIAS(CD4020_WI, CD4020, "CD4020_WI", "+IP,+RESET,+VDD,+VSS")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_4020.h b/src/lib/netlist/devices/nld_4020.h
index fd6b234da46..f24251fb1dc 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 "../nl_setup.h"
+#include "netlist/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 ebd269a023a..0c7511ca438 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -5,10 +5,12 @@
*
*/
-#include "nlid_cmos.h"
-#include "../analog/nlid_twoterm.h"
#include "nld_4066.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/solver/nld_solver.h"
+#include "nlid_cmos.h"
+
namespace netlist
{
namespace devices
@@ -27,7 +29,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- public:
+ private:
NETLIB_SUB(vdd_vss) m_supply;
analog::NETLIB_SUB(R_base) m_R;
@@ -39,45 +41,36 @@ namespace netlist
{
// Start in off condition
// FIXME: is ROFF correct?
- m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
+ m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
}
NETLIB_UPDATE(CD4066_GATE)
{
nl_double sup = (m_supply.vdd() - m_supply.vss());
- nl_double low = NL_FCONST(0.45) * sup;
- nl_double high = NL_FCONST(0.55) * sup;
+ nl_double low = plib::constants<nl_double>::cast(0.45) * sup;
+ nl_double high = plib::constants<nl_double>::cast(0.55) * sup;
nl_double in = m_control() - m_supply.vss();
- nl_double rON = m_base_r() * NL_FCONST(5.0) / sup;
+ nl_double rON = m_base_r() * plib::constants<nl_double>::cast(5.0) / sup;
nl_double R = -1.0;
if (in < low)
{
- R = NL_FCONST(1.0) / netlist().gmin();
+ R = plib::constants<nl_double>::one() / exec().gmin();
}
else if (in > high)
{
R = rON;
}
- if (R > NL_FCONST(0.0))
+ if (R > plib::constants<nl_double>::zero())
{
- // 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();
- }
+ m_R.update();
+ m_R.set_R(R);
+ m_R.solve_later();
}
}
- NETLIB_DEVICE_IMPL(CD4066_GATE)
+ NETLIB_DEVICE_IMPL(CD4066_GATE, "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 e9fd579496c..d339464a108 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 "../nl_setup.h"
+#include "netlist/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 b9758ff036b..c8ee1a90643 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -5,9 +5,10 @@
*
*/
-#include "nlid_cmos.h"
-#include "../analog/nlid_twoterm.h"
#include "nld_4316.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/solver/nld_solver.h"
+#include "nlid_cmos.h"
namespace netlist { namespace devices {
@@ -37,19 +38,20 @@ namespace netlist { namespace devices {
NETLIB_RESET(CD4316_GATE)
{
- m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
+ m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
}
NETLIB_UPDATE(CD4316_GATE)
{
- m_R.update_dev();
+ m_R.update();
if (m_S() && !m_E())
m_R.set_R(m_base_r());
else
- m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
- m_R.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ m_R.set_R(plib::constants<nl_double>::one() / exec().gmin());
+ m_R.solve_later(NLTIME_FROM_NS(1));
}
- NETLIB_DEVICE_IMPL(CD4316_GATE)
+ NETLIB_DEVICE_IMPL(CD4316_GATE, "CD4316_GATE", "")
-} } // namesapce netlist::devices
+} // namespace devices
+ } // namespace netlist
diff --git a/src/lib/netlist/devices/nld_4316.h b/src/lib/netlist/devices/nld_4316.h
index eb1d13f5542..278a2793a6f 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 "../nl_setup.h"
+#include "netlist/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 c5a12a15fb4..763760e2c6a 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
namespace devices
{
- 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) };
+ 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) };
NETLIB_OBJECT(74107A)
{
@@ -22,11 +22,12 @@ 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);
@@ -43,7 +44,7 @@ namespace netlist
logic_output_t m_Q;
logic_output_t m_QQ;
- const netlist_time *m_delay;
+ netlist_time m_delay[2];
logic_input_t m_J;
logic_input_t m_K;
@@ -61,7 +62,8 @@ namespace netlist
public:
NETLIB_CONSTRUCTOR_DERIVED(74107, 74107A)
{
- m_delay = delay_107;
+ m_delay[0] = delay_107[0];
+ m_delay[1] = delay_107[1];
}
};
@@ -137,9 +139,9 @@ namespace netlist
m_clk.activate_hl();
}
- NETLIB_DEVICE_IMPL(74107)
- NETLIB_DEVICE_IMPL(74107A)
- NETLIB_DEVICE_IMPL(74107_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74107.h b/src/lib/netlist/devices/nld_74107.h
index b59848cbb05..c6f8864610a 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 "../nl_setup.h"
+#include "netlist/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 9055c5ce140..32e47a47ef2 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 "../analog/nlid_twoterm.h"
+#include "netlist/analog/nlid_twoterm.h"
#include <cmath>
@@ -257,8 +257,8 @@ namespace netlist
{
m_KP = 1.0 / (1.0 + exp(m_K()));
- m_RP.do_reset();
- m_RN.do_reset();
+ m_RP.reset();
+ m_RN.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.do_reset();
- //m_2.do_reset();
+ //m_1.reset();
+ //m_2.reset();
}
NETLIB_UPDATE(9602_dip)
@@ -289,8 +289,8 @@ namespace netlist
NETLIB_RESET(9602_dip)
{
- //m_1.do_reset();
- //m_2.do_reset();
+ //m_1.reset();
+ //m_2.reset();
}
NETLIB_UPDATE(4538_dip)
@@ -302,14 +302,14 @@ namespace netlist
NETLIB_RESET(4538_dip)
{
- m_1.do_reset();
- m_2.do_reset();
+ m_1.reset();
+ m_2.reset();
}
- NETLIB_DEVICE_IMPL(74123)
- NETLIB_DEVICE_IMPL(74123_dip)
- NETLIB_DEVICE_IMPL(4538_dip)
- NETLIB_DEVICE_IMPL(9602_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74123.h b/src/lib/netlist/devices/nld_74123.h
index dfd75f746c7..3eca141b613 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 "../nl_setup.h"
+#include "netlist/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 b74c09f8cc0..136fe61520b 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 "../nl_base.h"
+#include "netlist/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_dev();
+ m_sub.update();
}
NETLIB_UPDATE(74153_dip)
{
m_2.m_chan = m_1.m_chan = (m_A() | (m_B()<<1));
- m_1.update_dev();
- m_2.update_dev();
+ m_1.update();
+ m_2.update();
}
- NETLIB_DEVICE_IMPL(74153)
- NETLIB_DEVICE_IMPL(74153_dip)
+ NETLIB_DEVICE_IMPL(74153, "TTL_74153", "+C0,+C1,+C2,+C3,+A,+B,+G")
+ NETLIB_DEVICE_IMPL(74153_dip, "TTL_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 ee77d4224ce..f1c0f056cf7 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 "../nl_setup.h"
+#include "netlist/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 5eb711fb456..7a3b54d6368 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -85,7 +85,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr netlist_time delay[4] =
+ static constexpr const 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)
- NETLIB_DEVICE_IMPL(74161_dip)
+ NETLIB_DEVICE_IMPL(74161, "TTL_74161", "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET")
+ NETLIB_DEVICE_IMPL(74161_dip, "TTL_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 363bc3c7f0d..f3fa3eab043 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 "../nl_setup.h"
+#include "netlist/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 5b2b1d8d080..b1eb30bb1ba 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -97,8 +97,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(74164)
- NETLIB_DEVICE_IMPL(74164_dip)
+ NETLIB_DEVICE_IMPL(74164, "TTL_74164", "+A,+B,+CLRQ,+CLK")
+ NETLIB_DEVICE_IMPL(74164_dip, "TTL_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 d7f29d386de..dd4e6bd1303 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 "../nl_setup.h"
+#include "netlist/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 678c1b1782e..521bf4d63d2 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -86,6 +86,7 @@ namespace netlist
}
else if (!m_CLK() || m_CLKINH())
{
+ // FIXME: qh is overwritten below?
qh = old_qh;
}
else if (!m_last_CLK)
@@ -101,8 +102,8 @@ namespace netlist
m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing
}
- NETLIB_DEVICE_IMPL(74165)
- NETLIB_DEVICE_IMPL(74165_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74165.h b/src/lib/netlist/devices/nld_74165.h
index e38ca7bab86..d282bab622b 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 "../nl_setup.h"
+#include "netlist/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 32f075c4da5..a5049014576 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -121,8 +121,8 @@ namespace netlist
m_QH.push(qh, delay); //FIXME
}
- NETLIB_DEVICE_IMPL(74166)
- NETLIB_DEVICE_IMPL(74166_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74166.h b/src/lib/netlist/devices/nld_74166.h
index b8a8a204374..80c86bb3422 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 "../nl_setup.h"
+#include "netlist/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 5f4573942bd..83369075db6 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -134,8 +134,8 @@ namespace netlist
//m_sub.do_reset();
}
- NETLIB_DEVICE_IMPL(74174)
- NETLIB_DEVICE_IMPL(74174_dip)
+ NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ")
+ NETLIB_DEVICE_IMPL(74174_dip,"TTL_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 66824abb7aa..f1854801291 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 "../nl_setup.h"
+#include "netlist/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 5955bcb389e..a15adb5c60f 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -111,8 +111,8 @@ namespace netlist
m_data = 0xFF;
}
- NETLIB_DEVICE_IMPL(74175)
- NETLIB_DEVICE_IMPL(74175_dip)
+ NETLIB_DEVICE_IMPL(74175, "TTL_74175", "+CLK,+D1,+D2,+D3,+D4,+CLRQ")
+ NETLIB_DEVICE_IMPL(74175_dip,"TTL_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 27e01b55b05..4bc8c1175ba 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 "../nl_setup.h"
+#include "netlist/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 1af605d4776..954fc351179 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -110,7 +110,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr netlist_time delay[4] =
+ static constexpr const 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)
- NETLIB_DEVICE_IMPL(74192_dip)
+ NETLIB_DEVICE_IMPL(74192, "TTL_74192", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ NETLIB_DEVICE_IMPL(74192_dip,"TTL_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 613d463cf47..9b0139070b8 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 "../nl_setup.h"
+#include "netlist/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 55d18f3dc1b..16d7438d799 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -87,7 +87,7 @@ namespace netlist
}
// FIXME: Timing
- static constexpr netlist_time delay[4] =
+ static constexpr const 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)
- NETLIB_DEVICE_IMPL(74193_dip)
+ NETLIB_DEVICE_IMPL(74193, "TTL_74193", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD")
+ NETLIB_DEVICE_IMPL(74193_dip, "TTL_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 bb14a301f38..a4c745d5386 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 "../nl_setup.h"
+#include "netlist/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 d531e792885..9876aa6b170 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 "../nl_base.h"
+#include "netlist/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)
- NETLIB_DEVICE_IMPL(74194_dip)
+ NETLIB_DEVICE_IMPL(74194, "TTL_74194", "+CLK,+S0,+S1,+SRIN,+A,+B,+C,+D,+SLIN,+CLRQ")
+ NETLIB_DEVICE_IMPL(74194_dip, "TTL_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 5124a66bcc0..5a507982b81 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 "../nl_setup.h"
+#include "netlist/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 10456ebbc21..753f16bfd22 100644
--- a/src/lib/netlist/devices/nld_74365.cpp
+++ b/src/lib/netlist/devices/nld_74365.cpp
@@ -6,12 +6,20 @@
*/
#include "nld_74365.h"
-#include "../nl_base.h"
+#include "netlist/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)
@@ -68,8 +76,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(74365)
- NETLIB_DEVICE_IMPL(74365_dip)
+ NETLIB_DEVICE_IMPL(74365, "TTL_74365", "+G1Q,+G2Q,+A1,+A2,+A3,+A4,+A5,+A6")
+ NETLIB_DEVICE_IMPL(74365_dip, "TTL_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 ca0eacf6ba1..a50b535383f 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 "../nl_setup.h"
+#include "netlist/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 cc2e60f23b7..4500229a1c5 100644
--- a/src/lib/netlist/devices/nld_7448.cpp
+++ b/src/lib/netlist/devices/nld_7448.cpp
@@ -5,8 +5,10 @@
*
*/
-#include "nlid_truthtable.h"
#include "nld_7448.h"
+#include "nlid_truthtable.h"
+
+#include <array>
namespace netlist
{
@@ -133,9 +135,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 uint8_t tab7448[16] =
+ static constexpr const std::array<uint8_t, 16> tab7448 =
{
BITS7( 1, 1, 1, 1, 1, 1, 0 ), /* 00 - not blanked ! */
BITS7( 0, 1, 1, 0, 0, 0, 0 ), /* 01 */
@@ -188,11 +190,13 @@ namespace netlist
NETLIB_RESET(7448)
{
m_state = 0;
- m_A.inactivate();
- m_B.inactivate();
- m_C.inactivate();
- m_D.inactivate();
- m_RBIQ.inactivate();
+#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
}
NETLIB_FUNC_VOID(7448, update_outputs, (unsigned v))
@@ -211,8 +215,8 @@ namespace netlist
#endif
- NETLIB_DEVICE_IMPL(7448)
- NETLIB_DEVICE_IMPL(7448_dip)
+ NETLIB_DEVICE_IMPL(7448, "TTL_7448", "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ")
+ NETLIB_DEVICE_IMPL(7448_dip, "TTL_7448_DIP", "")
} //namespace devices
diff --git a/src/lib/netlist/devices/nld_7448.h b/src/lib/netlist/devices/nld_7448.h
index 89528707bc1..b9c03ae6360 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 "../nl_setup.h"
+#include "netlist/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 af9b9afada1..aacab46a021 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -68,10 +68,10 @@ namespace netlist
m_B.activate();
m_C.activate();
m_D.activate();
- unsigned t1 = m_A() & m_B();
- unsigned t2 = m_C() & m_D();
+ auto t1 = m_A() & m_B();
+ auto t2 = m_C() & m_D();
- const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
+ const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
uint_fast8_t res = 0;
if (t1 ^ 1)
@@ -85,18 +85,20 @@ namespace netlist
m_A.inactivate();
m_B.inactivate();
}
- } else {
+ }
+ else
+ {
if (t2 ^ 1)
{
m_C.inactivate();
m_D.inactivate();
}
}
- m_Q.push(res, times[1 - res]);// ? 22000 : 15000);
+ m_Q.push(res, times[res]);// ? 22000 : 15000);
}
- NETLIB_DEVICE_IMPL(7450)
- NETLIB_DEVICE_IMPL(7450_dip)
+ NETLIB_DEVICE_IMPL(7450, "TTL_7450_ANDORINVERT", "+A,+B,+C,+D")
+ NETLIB_DEVICE_IMPL(7450_dip, "TTL_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 652516758ad..6718afd8f9e 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 "../nl_setup.h"
+#include "netlist/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 d9efb9fb710..c8abd829264 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 "../nl_base.h"
+#include "netlist/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)
- NETLIB_DEVICE_IMPL(7473A)
- NETLIB_DEVICE_IMPL(7473_dip)
- NETLIB_DEVICE_IMPL(7473A_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7473.h b/src/lib/netlist/devices/nld_7473.h
index 5313d18570c..3fbaaf4efbc 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 "../nl_setup.h"
+#include "netlist/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 9d020663f46..740af6ad3c1 100644
--- a/src/lib/netlist/devices/nld_7474.cpp
+++ b/src/lib/netlist/devices/nld_7474.cpp
@@ -1,3 +1,4 @@
+
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
@@ -6,60 +7,47 @@
*/
#include "nld_7474.h"
-#include "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
namespace devices
{
- NETLIB_OBJECT(7474sub)
+
+ NETLIB_OBJECT(7474)
{
- NETLIB_CONSTRUCTOR(7474sub)
- , m_CLK(*this, "CLK")
+ NETLIB_CONSTRUCTOR(7474)
+ , m_D(*this, "D")
+ , m_CLRQ(*this, "CLRQ")
+ , m_PREQ(*this, "PREQ")
+ , m_CLK(*this, "CLK", NETLIB_DELEGATE(7474, clk))
, m_Q(*this, "Q")
, m_QQ(*this, "QQ")
, m_nextD(*this, "m_nextD", 0)
{
}
+ private:
NETLIB_RESETI();
NETLIB_UPDATEI();
+ NETLIB_HANDLERI(clk);
- public:
+ logic_input_t m_D;
+ logic_input_t m_CLRQ;
+ logic_input_t m_PREQ;
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);
- private:
-
- };
+ state_var<netlist_sig_t> m_nextD;
- NETLIB_OBJECT(7474)
- {
- NETLIB_CONSTRUCTOR(7474)
- , sub(*this, "sub")
- , m_D(*this, "D")
- , m_CLRQ(*this, "CLRQ")
- , m_PREQ(*this, "PREQ")
+ void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ)
{
- register_subalias("CLK", sub.m_CLK);
-
- register_subalias("Q", sub.m_Q);
- register_subalias("QQ", sub.m_QQ);
+ // 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]);
}
-
- 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)
@@ -68,20 +56,20 @@ namespace netlist
, m_1(*this, "1")
, m_2(*this, "2")
{
- 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("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("7", ); ==> GND
- 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("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("14", ); ==> VCC
}
NETLIB_UPDATEI();
@@ -92,77 +80,47 @@ namespace netlist
NETLIB_SUB(7474) m_2;
};
- inline void NETLIB_NAME(7474sub)::newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ)
+ NETLIB_HANDLER(7474, clk)
{
- // 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();
- }
+ newstate(m_nextD, !m_nextD);
+ m_CLK.inactivate();
}
NETLIB_UPDATE(7474)
{
- if (m_PREQ() && m_CLRQ())
+ const auto preq(m_PREQ());
+ const auto clrq(m_CLRQ());
+ if (preq & clrq)
{
m_D.activate();
- 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();
+ m_nextD = m_D();
+ m_CLK.activate_lh();
}
else
{
- sub.newstate(1, 1);
- sub.m_CLK.inactivate();
+ newstate(preq ^ 1, clrq ^ 1);
+ 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)
- NETLIB_DEVICE_IMPL(7474_dip)
+ NETLIB_DEVICE_IMPL(7474, "TTL_7474", "+CLK,+D,+CLRQ,+PREQ")
+ NETLIB_DEVICE_IMPL(7474_dip, "TTL_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 aa48e240387..48fd4f3d842 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 "../nl_setup.h"
+#include "netlist/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 b2d28048513..63fd355d406 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -101,7 +101,7 @@ namespace netlist
{
unsigned start_q = m_last_Q;
- NETLIB_PARENT_UPDATE(7477);
+ NETLIB_NAME(7477)::update();
for (std::size_t i=0; i<4; i++)
{
@@ -148,10 +148,10 @@ namespace netlist
}
- NETLIB_DEVICE_IMPL(7475)
- NETLIB_DEVICE_IMPL(7475_dip)
- NETLIB_DEVICE_IMPL(7477)
- NETLIB_DEVICE_IMPL(7477_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7475.h b/src/lib/netlist/devices/nld_7475.h
index 51d09e75a66..b16fabe61b6 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 "../nl_setup.h"
+#include "netlist/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 72c86c003d5..5f820162209 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -16,14 +16,16 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(7483)
, m_C0(*this, "C0")
- , 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_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_lastr(*this, "m_lastr", 0)
, m_S1(*this, "S1")
, m_S2(*this, "S2")
@@ -34,6 +36,8 @@ namespace netlist
}
NETLIB_RESETI();
NETLIB_UPDATEI();
+ NETLIB_HANDLERI(upd_a);
+ NETLIB_HANDLERI(upd_b);
protected:
logic_input_t m_C0;
@@ -46,7 +50,9 @@ namespace netlist
logic_input_t m_B3;
logic_input_t m_B4;
- state_var<unsigned> m_lastr;
+ state_var_u8 m_a;
+ state_var_u8 m_b;
+ state_var_u8 m_lastr;
logic_output_t m_S1;
logic_output_t m_S2;
@@ -87,12 +93,21 @@ namespace netlist
m_lastr = 0;
}
- NETLIB_UPDATE(7483)
+ NETLIB_HANDLER(7483, upd_a)
{
- 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);
+ m_a = static_cast<uint8_t>((m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3));
+ NETLIB_NAME(7483)::update();
+ }
- unsigned r = a + b + m_C0();
+ 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());
if (r != m_lastr)
{
@@ -105,8 +120,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(7483)
- NETLIB_DEVICE_IMPL(7483_dip)
+ NETLIB_DEVICE_IMPL(7483, "TTL_7483", "+A1,+A2,+A3,+A4,+B1,+B2,+B3,+B4,+C0")
+ NETLIB_DEVICE_IMPL(7483_dip, "TTL_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 24952bf0501..ba82d5bbb9c 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 "../nl_setup.h"
+#include "netlist/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 320cf762f26..cadb73000ff 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -101,8 +101,8 @@ namespace netlist
update_outputs(1, 1, 0);
}
- NETLIB_DEVICE_IMPL(7485)
- NETLIB_DEVICE_IMPL(7485_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7485.h b/src/lib/netlist/devices/nld_7485.h
index 61b87c37ba3..7890f4dbd2a 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 "../nl_setup.h"
+#include "netlist/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 13e69c6aa31..acbe0fa4d7a 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 "../nl_base.h"
+#include "netlist/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", m_B);
- register_subalias("2", m_R1);
- register_subalias("3", m_R2);
+ register_subalias("1", "B");
+ register_subalias("2", "R1");
+ register_subalias("3", "R2");
// register_subalias("4", ); --> NC
// register_subalias("5", ); --> VCC
- register_subalias("6", m_R91);
- register_subalias("7", m_R92);
+ register_subalias("6", "R91");
+ register_subalias("7", "R92");
- register_subalias("8", m_Q[2]);
- register_subalias("9", m_Q[1]);
+ register_subalias("8", "QC");
+ register_subalias("9", "QB");
// register_subalias("10", ); --> GND
- register_subalias("11", m_Q[3]);
- register_subalias("12", m_Q[0]);
+ register_subalias("11", "QD");
+ register_subalias("12", "QA");
// register_subalias("13", ); --> NC
- register_subalias("14", m_A);
+ register_subalias("14", "A");
}
};
@@ -78,12 +78,13 @@ namespace netlist
m_last_B = 0;
}
- static C14CONSTEXPR const netlist_time delay[4] =
+ static constexpr 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)
{
@@ -119,14 +120,14 @@ namespace netlist
m_last_B = new_B;
}
- NETLIB_FUNC_VOID(7490, update_outputs, (void))
+ NETLIB_FUNC_VOID(7490, update_outputs, ())
{
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
}
- NETLIB_DEVICE_IMPL(7490)
- NETLIB_DEVICE_IMPL(7490_dip)
+ NETLIB_DEVICE_IMPL(7490, "TTL_7490", "+A,+B,+R1,+R2,+R91,+R92")
+ NETLIB_DEVICE_IMPL(7490_dip, "TTL_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 5ff18543b03..e2fa5094911 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 "../nl_setup.h"
+#include "netlist/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 f3c68f7a5c2..f26e1c237d5 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -6,23 +6,22 @@
*/
#include "nld_7493.h"
-#include "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
namespace devices
{
- 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);
+ 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);
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))
@@ -35,35 +34,51 @@ namespace netlist
}
private:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
+ 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_HANDLERI(updA)
+ NETLIB_UPDATEI()
{
- if (m_reset)
+ if (!(m_R1() & m_R2()))
+ {
+ m_CLKA.activate_hl();
+ m_CLKB.activate_hl();
+ }
+ else
{
- m_a ^= 1;
- m_QA.push(m_a, out_delay);
+ 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;
}
}
+ NETLIB_HANDLERI(updA)
+ {
+ m_a ^= 1;
+ m_QA.push(m_a, out_delay);
+ }
+
NETLIB_HANDLERI(updB)
{
- 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);
- }
+ 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);
}
logic_input_t m_R1;
logic_input_t m_R2;
- state_var_sig m_reset;
state_var_sig m_a;
- state_var_sig m_bcd;
+ state_var_u8 m_bcd;
logic_input_t m_CLKA;
logic_input_t m_CLKB;
@@ -97,37 +112,9 @@ 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)
- NETLIB_DEVICE_IMPL(7493_dip)
+ NETLIB_DEVICE_IMPL(7493, "TTL_7493", "+CLKA,+CLKB,+R1,+R2")
+ NETLIB_DEVICE_IMPL(7493_dip, "TTL_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 ce9566aa28f..68ad90885ec 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 "../nl_setup.h"
+#include "netlist/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
new file mode 100644
index 00000000000..1432884b8dd
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7497.cpp
@@ -0,0 +1,174 @@
+// 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
new file mode 100644
index 00000000000..8d14e08a49b
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7497.h
@@ -0,0 +1,57 @@
+// 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 d6dc268ed28..b7bb729b334 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 "../analog/nlid_twoterm.h"
+#include "netlist/analog/nlid_twoterm.h"
namespace netlist
{
@@ -100,11 +100,14 @@ namespace netlist
{
m_R_FC.set_R(90000.0);
m_R_RNG.set_R(90000.0);
- m_clock.do_reset();
+ m_clock.reset();
}
NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI() { update_dev(); }
+ NETLIB_UPDATE_PARAMI()
+ {
+ /* update param may be called from anywhere, update_dev(time) is not a good idea */
+ }
public:
NETLIB_SUB(SN74LS629clk) m_clock;
@@ -145,8 +148,8 @@ namespace netlist
NETLIB_RESETI()
{
- m_1.do_reset();
- m_2.do_reset();
+ m_1.reset();
+ m_2.reset();
}
private:
@@ -207,7 +210,7 @@ namespace netlist
freq += k9 * v_rng * v_freq_3;
freq += k10 * v_rng * v_freq_4;
- freq *= NL_FCONST(0.1e-6) / m_CAP();
+ freq *= plib::constants<nl_double>::cast(0.1e-6) / m_CAP();
// FIXME: we need a possibility to remove entries from queue ...
// or an exact model ...
@@ -231,8 +234,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(SN74LS629)
- NETLIB_DEVICE_IMPL(SN74LS629_dip)
+ NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP")
+ NETLIB_DEVICE_IMPL(SN74LS629_dip, "SN74LS629_DIP", "1.CAP1,2.CAP2")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74ls629.h b/src/lib/netlist/devices/nld_74ls629.h
index 3351524a60b..30d15d70865 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 "../nl_setup.h"
+#include "netlist/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 2e24bbf9fed..8ae6cbb6097 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 "../nl_base.h"
+#include "netlist/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)
- NETLIB_DEVICE_IMPL(82S115_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S115.h b/src/lib/netlist/devices/nld_82S115.h
index ef7f1ec3910..8c13fd8b51e 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 "../nl_setup.h"
+#include "netlist/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 a8a6bfc9b57..4a80b57e349 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -77,8 +77,8 @@ namespace netlist
m_O[i].push((o >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(82S123)
- NETLIB_DEVICE_IMPL(82S123_dip)
+ NETLIB_DEVICE_IMPL(82S123, "PROM_82S123", "+CEQ,+A0,+A1,+A2,+A3,+A4")
+ NETLIB_DEVICE_IMPL(82S123_dip, "PROM_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 dbf6bf63180..2c18377934d 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 "../nl_setup.h"
+#include "netlist/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 dcacd1ec876..b1752908645 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -79,8 +79,8 @@ namespace netlist
m_O[i].push((o >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(82S126)
- NETLIB_DEVICE_IMPL(82S126_dip)
+ NETLIB_DEVICE_IMPL(82S126, "PROM_82S126", "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7")
+ NETLIB_DEVICE_IMPL(82S126_dip, "PROM_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 3079bb8e2e0..ed7aa131819 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 "../nl_setup.h"
+#include "netlist/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 7441f6c677e..e3176c7b30f 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -15,19 +15,55 @@ namespace netlist
NETLIB_OBJECT(82S16)
{
NETLIB_CONSTRUCTOR(82S16)
- , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }})
- , m_CE1Q(*this, "CE1Q")
- , m_CE2Q(*this, "CE2Q")
- , m_CE3Q(*this, "CE3Q")
+ , 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_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;
@@ -38,7 +74,9 @@ namespace netlist
logic_input_t m_DIN;
logic_output_t m_DOUTQ;
- state_var<uint64_t[4]> m_ram; // 256 bits
+ state_array<uint64_t, 4> m_ram; // 256 bits
+ state_var_u8 m_addr; // 256 bits
+ state_var_sig m_enq;
};
NETLIB_OBJECT_DERIVED(82S16_dip, 82S16)
@@ -69,22 +107,9 @@ namespace netlist
// FIXME: optimize device (separate address decoder!)
NETLIB_UPDATE(82S16)
{
- if (m_CE1Q() || m_CE2Q() || m_CE3Q())
+ if (!m_enq)
{
- // 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);
- }
-
+ const auto adr(m_addr);
if (!m_WEQ())
{
m_ram[adr >> 6] = (m_ram[adr >> 6]
@@ -101,10 +126,12 @@ namespace netlist
{
m_ram[i] = 0;
}
+ m_addr = 0;
+ m_enq = 0;
}
- NETLIB_DEVICE_IMPL(82S16)
- NETLIB_DEVICE_IMPL(82S16_dip)
+ NETLIB_DEVICE_IMPL(82S16, "TTL_82S16", "")
+ NETLIB_DEVICE_IMPL(82S16_dip, "TTL_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 d1117246d87..47d6189a79b 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 "../nl_setup.h"
+#include "netlist/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 ad752adb605..b416015df24 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 "../nl_base.h"
+#include "netlist/nl_base.h"
#define MAXCNT 9
@@ -14,6 +14,7 @@ namespace netlist
{
namespace devices
{
+ //FIXME: Convert sub devices into NETDEV_DELEGATE logic
NETLIB_OBJECT(9310_subABCD)
{
NETLIB_CONSTRUCTOR(9310_subABCD)
@@ -139,8 +140,8 @@ namespace netlist
NETLIB_RESET(9310)
{
- sub.do_reset();
- subABCD.do_reset();
+ sub.reset();
+ subABCD.reset();
}
NETLIB_RESET(9310_subABCD)
@@ -157,32 +158,35 @@ namespace netlist
NETLIB_UPDATE(9310_sub)
{
+ auto cnt(m_cnt);
+
if (m_loadq)
{
- if (m_cnt < MAXCNT - 1)
+ if (cnt < MAXCNT - 1)
{
- ++m_cnt;
- update_outputs(m_cnt);
+ ++cnt;
+ update_outputs(cnt);
}
- else if (m_cnt == MAXCNT - 1)
+ else if (cnt == MAXCNT - 1)
{
- m_cnt = MAXCNT;
+ 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));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
+ cnt = 0;
+ update_outputs_all(cnt, NLTIME_FROM_NS(20));
}
}
else
{
- 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));
+ 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 = cnt;
}
NETLIB_UPDATE(9310)
@@ -223,10 +227,10 @@ namespace netlist
#if 0
// for (int i=0; i<4; i++)
// m_Q[i], (cnt >> i) & 1, delay[i]);
- 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);
+ 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);
#else
if ((cnt & 1) == 1)
m_QA.push(1, out_delay);
@@ -262,8 +266,8 @@ namespace netlist
#endif
}
- NETLIB_DEVICE_IMPL(9310)
- NETLIB_DEVICE_IMPL(9310_dip)
+ NETLIB_DEVICE_IMPL(9310, "TTL_9310", "")
+ NETLIB_DEVICE_IMPL(9310_dip, "TTL_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 02cb45b2d86..65df9c04ce4 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 "../nl_setup.h"
+#include "netlist/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 7c478fd4b05..2b17eabb3ec 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -20,31 +20,72 @@ 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, 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_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_Q(*this, {{ "QA", "QB", "QC", "QD" }})
- , m_RC(*this, "RC")
+ , m_cnt(*this, "m_cnt", 0)
+ , m_abcd(*this, "m_abcd", 0)
+ , m_loadq(*this, "m_loadq", 0)
+ , m_ent(*this, "m_ent", 0)
{
}
private:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_HANDLERI(clk);
- NETLIB_HANDLERI(noop) { }
+ NETLIB_RESETI()
+ {
+ m_CLK.set_state(logic_t::STATE_INP_LH);
+ m_cnt = 0;
+ m_abcd = 0;
+ }
- logic_input_t m_CLK;
+ 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));
+ }
+
+ logic_input_t m_CLK;
logic_input_t m_ENT;
- logic_input_t m_LOADQ;
- state_var<unsigned> m_cnt;
+ logic_output_t m_RC;
+
+ logic_input_t m_LOADQ;
logic_input_t m_ENP;
logic_input_t m_CLRQ;
@@ -55,12 +96,15 @@ 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;
- 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
+ void update_outputs_all(unsigned cnt, netlist_time out_delay) noexcept
{
m_Q[0].push((cnt >> 0) & 1, out_delay);
m_Q[1].push((cnt >> 1) & 1, out_delay);
@@ -93,63 +137,9 @@ 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)
- NETLIB_DEVICE_IMPL(9316_dip)
+ NETLIB_DEVICE_IMPL(9316, "TTL_9316", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D")
+ NETLIB_DEVICE_IMPL(9316_dip, "TTL_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 8deb21dfccd..8ab1789d7c7 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 "../nl_setup.h"
+#include "netlist/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 6c408498be7..abf9bf9f6ef 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -105,14 +105,14 @@ namespace netlist
NETLIB_UPDATE(9322)
{
- m_1.update_dev();
- m_2.update_dev();
- m_3.update_dev();
- m_4.update_dev();
+ m_1.update();
+ m_2.update();
+ m_3.update();
+ m_4.update();
}
- NETLIB_DEVICE_IMPL(9322)
- NETLIB_DEVICE_IMPL(9322_dip)
+ NETLIB_DEVICE_IMPL(9322, "TTL_9322", "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE")
+ NETLIB_DEVICE_IMPL(9322_dip, "TTL_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 7de0f053b05..986c6b9e7f7 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 "../nl_setup.h"
+#include "netlist/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 5d0c5cb71a3..825696f0938 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -30,7 +30,7 @@ namespace netlist
logic_input_t m_RC;
logic_input_t m_IN;
- state_var<uint16_t[5]> m_buffer;
+ state_array<uint16_t, 5> m_buffer;
logic_output_t m_OUT;
};
@@ -116,7 +116,7 @@ namespace netlist
/* do nothing */
}
- inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
+ NETLIB_FUNC_VOID(Am2847_shifter, shift, ())
{
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)
- NETLIB_DEVICE_IMPL(AM2847_dip)
+ NETLIB_DEVICE_IMPL(AM2847, "TTL_AM2847", "+CP,+INA,+INB,+INC,+IND,+RCA,+RCB,+RCC,+RCD")
+ NETLIB_DEVICE_IMPL(AM2847_dip, "TTL_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 70d288d3eec..ff4a95b8e81 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 "../nl_setup.h"
+#include "netlist/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 fd3b8666078..93b958de539 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -107,8 +107,8 @@ namespace netlist
}
}
- NETLIB_DEVICE_IMPL(9314)
- NETLIB_DEVICE_IMPL(9314_dip)
+ NETLIB_DEVICE_IMPL(9314, "TTL_9314", "+EQ,+MRQ,+S0Q,+S1Q,+S2Q,+S3Q,+D0,+D1,+D2,+D3")
+ NETLIB_DEVICE_IMPL(9314_dip, "TTL_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 6188bbef42f..59c60591ce7 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 "../nl_setup.h"
+#include "netlist/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 8dceded5390..c08ce53efed 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -143,8 +143,8 @@ namespace netlist
m_Q[i].push((q >> i) & 1, delay);
}
- NETLIB_DEVICE_IMPL(9334)
- NETLIB_DEVICE_IMPL(9334_dip)
+ NETLIB_DEVICE_IMPL(9334, "TTL_9334", "+CQ,+EQ,+D,+A0,+A1,+A2")
+ NETLIB_DEVICE_IMPL(9334_dip, "TTL_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 1a07e051333..e54208e3ba4 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 "../nl_setup.h"
+#include "netlist/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 28fe0ad8188..738230646e0 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -25,7 +25,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- protected:
+ private:
logic_input_t m_S;
logic_input_t m_R;
@@ -49,7 +49,7 @@ namespace netlist
NETLIB_RESETI();
NETLIB_UPDATEI();
- protected:
+ private:
logic_input_t m_I;
logic_output_t m_Q;
@@ -100,8 +100,8 @@ namespace netlist
m_last = nval;
}
- NETLIB_DEVICE_IMPL(nicRSFF)
- NETLIB_DEVICE_IMPL(nicDelay)
+ NETLIB_DEVICE_IMPL(nicRSFF, "NETDEV_RSFF", "")
+ NETLIB_DEVICE_IMPL(nicDelay, "NETDEV_DELAY", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_legacy.h b/src/lib/netlist/devices/nld_legacy.h
index 33f7d0caaf8..aa3aec6f147 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp
index 29218aaa09a..6b1b3d8efc1 100644
--- a/src/lib/netlist/devices/nld_log.cpp
+++ b/src/lib/netlist/devices/nld_log.cpp
@@ -5,10 +5,10 @@
*
*/
-#include "../nl_base.h"
-#include "../plib/pstream.h"
-#include "../plib/pfmtlog.h"
+#include "netlist/nl_base.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(plib::pfmt("{1}.log")(this->name()))
- , m_writer(m_strm)
+ , m_strm(pstring(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(netlist().time().as_double()).e(static_cast<double>(m_I())));
+ m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().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(netlist().time().as_double()).e(static_cast<double>(m_I() - m_I2())));
+ m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_double()).e(static_cast<double>(m_I() - m_I2())));
}
NETLIB_RESETI() { }
@@ -89,8 +89,8 @@ namespace netlist
#endif
- NETLIB_DEVICE_IMPL(log)
- NETLIB_DEVICE_IMPL(logD)
+ NETLIB_DEVICE_IMPL(log, "LOG", "+I")
+ NETLIB_DEVICE_IMPL(logD, "LOGD", "+I,+I2")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_log.h b/src/lib/netlist/devices/nld_log.h
index 6364022cea2..13c71ea7257 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
#define LOG(name, cI) \
- NET_REGISTER_DEV(??PG, name) \
+ NET_REGISTER_DEV(LOG, 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 e97ae41e437..f6c2566bd43 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 "../solver/nld_matrix_solver.h"
-#include "../analog/nlid_twoterm.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/solver/nld_matrix_solver.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(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
+ m_RV.set_G_V_I(plib::constants<nl_double>::one() / 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()->is_timestep();
+ m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
}
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_dev();
- m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
- m_RV.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ 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));
}
}
- NETLIB_DEVICE_IMPL(MM5837_dip)
+ NETLIB_DEVICE_IMPL(MM5837_dip, "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 4af397d9965..8f764aa651f 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 "../nl_setup.h"
+#include "netlist/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 8795197bd57..5e990d2e974 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 "../analog/nlid_twoterm.h"
-#include "../solver/nld_solver.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/solver/nld_solver.h"
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
@@ -62,31 +62,37 @@ 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") // Pin 3
+ , m_OUT(*this, "_OUT") // to Pin 3 via ROUT
, 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();
- protected:
+ private:
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;
@@ -94,52 +100,51 @@ 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;
- inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
-
+ 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;
+ }
};
NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
{
NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555)
{
- 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
+ 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
}
};
- 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.do_reset();
- m_R2.do_reset();
- m_R3.do_reset();
- m_RDIS.do_reset();
+ m_R1.reset();
+ m_R2.reset();
+ m_R3.reset();
+ m_ROUT.reset();
+ m_RDIS.reset();
- /* FIXME make resistance a parameter, properly model other variants */
+ /* FIXME make resistances a parameter, properly model other variants */
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
+ m_ROUT.set_R(20);
m_RDIS.set_R(R_OFF);
m_last_out = true;
@@ -149,39 +154,47 @@ namespace netlist
{
// FIXME: assumes GND is connected to 0V.
- 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));
+ const auto reset = m_RESET();
- if (!btrig)
+ if (!reset && m_last_reset)
{
- m_ff = true;
+ m_ff = false;
}
- else if (bthresh)
+ else
{
- m_ff = false;
+ 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;
}
- bool out = (!m_RESET() ? false : m_ff);
+ const bool out = (!reset ? false : m_ff);
if (m_last_out && !out)
{
- m_RDIS.update_dev();
+ m_RDIS.update();
m_OUT.push(m_R3.m_N());
m_RDIS.set_R(R_ON);
}
else if (!m_last_out && out)
{
- m_RDIS.update_dev();
+ m_RDIS.update();
// 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)
- NETLIB_DEVICE_IMPL(NE555_dip)
+ NETLIB_DEVICE_IMPL(NE555, "NE555", "")
+ NETLIB_DEVICE_IMPL(NE555_dip, "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 c629253f08f..fc575d914b7 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
#define NE555(name) \
NET_REGISTER_DEV(NE555, name)
@@ -12,4 +12,10 @@
#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 4c29389d491..284b6673f76 100644
--- a/src/lib/netlist/devices/nld_r2r_dac.cpp
+++ b/src/lib/netlist/devices/nld_r2r_dac.cpp
@@ -5,9 +5,9 @@
*
*/
-#include "../nl_base.h"
-#include "../nl_factory.h"
-#include "../analog/nlid_twoterm.h"
+#include "netlist/nl_base.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/nl_factory.h"
namespace netlist
{
@@ -39,17 +39,17 @@ namespace netlist
NETLIB_UPDATE_PARAM(r2r_dac)
{
- update_dev();
+ solve_now();
double V = m_VIN() / static_cast<double>(1 << m_num())
* static_cast<double>(m_val());
- this->set(1.0 / m_R(), V, 0.0);
+ this->set_G_V_I(1.0 / m_R(), V, 0.0);
}
} //namespace analog
namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, r2r_dac)
- }
+ NETLIB_DEVICE_IMPL_NS(analog, r2r_dac, "R2R_DAC", "VIN,R,N")
+ } // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_r2r_dac.h b/src/lib/netlist/devices/nld_r2r_dac.h
index 18e5bddc053..8a4257a3cbf 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 "../nl_setup.h"
+#include "netlist/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 4bc41075f89..f219d215520 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 "../nl_base.h"
-#include "../nl_errstr.h"
-#include "../analog/nlid_twoterm.h"
-#include "../solver/nld_solver.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_errstr.h"
+#include "netlist/solver/nld_solver.h"
#include <cmath>
@@ -82,11 +82,11 @@ namespace netlist
NETLIB_RESETI()
{
m_last_state = 1;
- m_RVI.do_reset();
- m_RVO.do_reset();
+ m_RVI.reset();
+ m_RVO.reset();
m_is_timestep = m_RVO.m_P.net().solver()->has_timestep_devices();
- 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);
+ 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);
}
NETLIB_UPDATEI()
@@ -97,9 +97,9 @@ namespace netlist
{
m_last_state = 0;
if (m_is_timestep)
- 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));
+ 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();
}
}
else
@@ -108,9 +108,9 @@ namespace netlist
{
m_last_state = 1;
if (m_is_timestep)
- 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));
+ 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();
}
}
}
@@ -125,7 +125,7 @@ namespace netlist
bool m_is_timestep;
};
- NETLIB_DEVICE_IMPL(schmitt_trigger)
+ NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "MODEL")
} // namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_schmitt.h b/src/lib/netlist/devices/nld_schmitt.h
index ecce59be616..20666b29cf7 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index eabc4b4fbff..03aa5c678f1 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -5,8 +5,8 @@
*
*/
-#include "../solver/nld_solver.h"
-#include "../solver/nld_matrix_solver.h"
+#include "netlist/solver/nld_solver.h"
+#include "netlist/solver/nld_matrix_solver.h"
#include "nlid_system.h"
namespace netlist
@@ -40,54 +40,40 @@ 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_UPDATE(extclock)
+ NETLIB_HANDLER(extclock, clk2)
{
- m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
- m_off = netlist_time::zero();
+ m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
if (++m_cnt >= m_size)
m_cnt = 0;
}
- // ----------------------------------------------------------------------------------------
- // logic_input
- // ----------------------------------------------------------------------------------------
-
- NETLIB_RESET(logic_input)
- {
- m_Q.initial(0);
- }
-
- NETLIB_UPDATE(logic_input)
+ NETLIB_HANDLER(extclock, clk2_pow2)
{
- m_Q.push(m_IN() & 1, netlist_time::from_nsec(1));
+ m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]);
+ m_cnt = (++m_cnt) & (m_size-1);
}
- NETLIB_UPDATE_PARAM(logic_input)
- {
- }
-
- // ----------------------------------------------------------------------------------------
- // analog_input
- // ----------------------------------------------------------------------------------------
-
- NETLIB_RESET(analog_input)
+ NETLIB_UPDATE(extclock)
{
- m_Q.initial(0.0);
- }
+ 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_UPDATE(analog_input)
- {
- m_Q.push(m_IN());
- }
+ // continue with optimized clock handlers ....
- NETLIB_UPDATE_PARAM(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);
}
-
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
@@ -106,19 +92,10 @@ namespace netlist
m_last_state = state;
const nl_double R = state ? m_RON() : m_ROFF();
- // 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();
- }
+ // 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();
}
}
@@ -141,17 +118,19 @@ namespace netlist
}
- 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)
+ 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")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_system.h b/src/lib/netlist/devices/nld_system.h
index 69a7c75dbf3..5158e098cfa 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
diff --git a/src/lib/netlist/devices/nld_tms4800.cpp b/src/lib/netlist/devices/nld_tms4800.cpp
index 29a9bd836ab..24729b10e72 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 "../nl_base.h"
+#include "netlist/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)
- NETLIB_DEVICE_IMPL(tms4800_dip)
+ 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", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_tms4800.h b/src/lib/netlist/devices/nld_tms4800.h
index dc72354cb03..c5bcd1337f0 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 "../nl_setup.h"
+#include "netlist/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 74fbb206feb..b05d09ea71e 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 "../nl_base.h"
+#include "netlist/nl_base.h"
namespace netlist
{
@@ -70,8 +70,8 @@ namespace netlist
m_Q.push(q, NLTIME_FROM_NS(1));
}
- NETLIB_DEVICE_IMPL(tristate)
- NETLIB_DEVICE_IMPL(tristate3)
+ NETLIB_DEVICE_IMPL(tristate, "TTL_TRISTATE", "+CEQ1,+D1,+CEQ2,+D2")
+ NETLIB_DEVICE_IMPL(tristate3, "TTL_TRISTATE3", "")
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_tristate.h b/src/lib/netlist/devices/nld_tristate.h
index a5ff22fac96..71f97d9812d 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 "../nl_setup.h"
+#include "netlist/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 f9999aebcc0..d91d691453a 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 "../nl_setup.h"
-#include "../nl_base.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 4c3ec6f67aa..a2fd18e85a7 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 "../solver/nld_solver.h"
+#include "netlist/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_t &anetlist, const pstring &name,
+ nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name,
logic_t *inout_proxied, detail::core_terminal_t *proxy_inout)
: device_t(anetlist, name)
{
@@ -29,33 +29,23 @@ 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_t &anetlist, const pstring &name,
+ nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_state_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_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_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(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)
{
}
@@ -81,39 +71,32 @@ namespace netlist
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
- nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name,
+ nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_state_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_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_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(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 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);
+ const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
register_subalias("Q", m_RV.m_P);
connect(m_RV.m_N, m_GNDHack);
bool f = false;
- for (int i = 0; i < 3; i++)
+ for (auto & pwr_sym : power_syms)
{
pstring devname = out_proxied->device().name();
- auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
+ auto tp = setup().find_terminal(devname + "." + pwr_sym.first,
detail::terminal_type::INPUT, false);
- auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
+ auto tn = setup().find_terminal(devname + "." + pwr_sym.second,
detail::terminal_type::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
@@ -126,11 +109,6 @@ 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
}
@@ -142,15 +120,15 @@ namespace netlist
//m_Q.initial(0.0);
m_last_state = -1;
- m_RV.do_reset();
+ m_RV.reset();
m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
- m_RV.set(NL_FCONST(1.0) / logic_family()->R_low(),
+ m_RV.set_G_V_I(plib::constants<nl_double>::one() / logic_family()->R_low(),
logic_family()->low_V(0.0, supply_V), 0.0);
}
NETLIB_UPDATE(d_to_a_proxy)
{
- const int state = static_cast<int>(m_I());
+ const auto state = static_cast<int>(m_I());
if (state != m_last_state)
{
// FIXME: Variable voltage
@@ -163,10 +141,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_dev();
+ m_RV.update();
}
- m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
- m_RV.m_P.schedule_solve_after(NLTIME_FROM_NS(1));
+ m_RV.set_G_V_I(plib::constants<nl_double>::one() / R, V, 0.0);
+ m_RV.solve_later();
}
}
diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h
index 821cfa56d9d..9543b8db234 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 "../nl_setup.h"
-#include "../analog/nlid_twoterm.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/nl_setup.h"
namespace netlist
{
@@ -26,11 +26,9 @@ namespace netlist
NETLIB_OBJECT(base_proxy)
{
public:
- nld_base_proxy(netlist_t &anetlist, const pstring &name,
+ nld_base_proxy(netlist_state_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; }
@@ -49,13 +47,11 @@ 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_t &anetlist, const pstring &name,
+ nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name,
logic_input_t *in_proxied, detail::core_terminal_t *in_proxy);
private:
@@ -67,9 +63,7 @@ namespace netlist
NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_a_to_d_proxy)
{
public:
- nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied);
-
- virtual ~nld_a_to_d_proxy() override;
+ nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *in_proxied);
analog_input_t m_I;
@@ -88,24 +82,20 @@ 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_t &anetlist, const pstring &name,
+ nld_base_d_to_a_proxy(netlist_state_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_t &anetlist, const pstring &name, logic_output_t *out_proxied);
- virtual ~nld_d_to_a_proxy() override {}
+ nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *out_proxied);
protected:
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index 326cd3dbf2c..f1f2af1b31e 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 "../nl_base.h"
-#include "../nl_setup.h"
-#include "../analog/nlid_twoterm.h"
-#include "../plib/putil.h"
+#include "netlist/analog/nlid_twoterm.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
+#include "plib/putil.h"
namespace netlist
{
@@ -27,7 +27,8 @@ namespace netlist
NETLIB_OBJECT(netlistparams)
{
NETLIB_CONSTRUCTOR(netlistparams)
- , m_use_deactivate(*this, "USE_DEACTIVATE", 0)
+ , m_use_deactivate(*this, "USE_DEACTIVATE", false)
+ , m_startup_strategy(*this, "STARTUP_STRATEGY", 1)
{
}
NETLIB_UPDATEI() { }
@@ -35,6 +36,7 @@ namespace netlist
//NETLIB_UPDATE_PARAMI() { }
public:
param_logic_t m_use_deactivate;
+ param_int_t m_startup_strategy;
};
// -----------------------------------------------------------------------------
@@ -52,7 +54,7 @@ namespace netlist
NETLIB_RESETI()
{
- m_Q.net().set_time(netlist_time::zero());
+ m_Q.net().set_next_scheduled_time(netlist_time::zero());
}
NETLIB_UPDATE_PARAMI()
@@ -65,16 +67,14 @@ namespace netlist
logic_net_t &net = m_Q.net();
// this is only called during setup ...
net.toggle_new_Q();
- net.set_time(netlist().time() + m_inc);
+ net.set_next_scheduled_time(exec().time() + m_inc);
}
public:
logic_output_t m_Q;
-
- param_double_t m_freq;
netlist_time m_inc;
-
- inline static void mc_update(logic_net_t &net);
+ private:
+ param_double_t m_freq;
};
// -----------------------------------------------------------------------------
@@ -96,7 +96,7 @@ namespace netlist
//NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
- protected:
+ private:
logic_input_t m_feedback;
logic_output_t m_Q;
@@ -127,31 +127,35 @@ namespace netlist
std::vector<pstring> pat(plib::psplit(m_pattern(),","));
m_off = netlist_time::from_double(m_offset());
- unsigned long pati[32];
- for (int pI = 0; pI < 32; pI++)
- {
- pati[pI] = 0;
- }
+ std::array<std::int64_t, 32> pati = { 0 };
+
m_size = static_cast<std::uint8_t>(pat.size());
- unsigned long total = 0;
+ netlist_time::mult_type total = 0;
for (unsigned i=0; i<m_size; i++)
{
- pati[i] = static_cast<unsigned long>(pat[i].as_long());
+ // FIXME: use pstonum_ne
+ //pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]);
+ pati[i] = plib::pstonum<std::int64_t>(pat[i]);
total += pati[i];
}
netlist_time ttotal = netlist_time::zero();
- for (unsigned i=0; i<m_size - 1; i++)
+ auto sm1 = static_cast<uint8_t>(m_size - 1);
+ for (unsigned i=0; i < sm1; i++)
{
m_inc[i] = base * pati[i];
ttotal += m_inc[i];
}
- m_inc[m_size - 1] = base * total - ttotal;
+ m_inc[sm1] = base * total - ttotal;
}
}
NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
- protected:
+
+ NETLIB_HANDLERI(clk2);
+ NETLIB_HANDLERI(clk2_pow2);
+
+ private:
param_double_t m_freq;
param_str_t m_pattern;
@@ -162,7 +166,7 @@ namespace netlist
state_var_u8 m_cnt;
std::uint8_t m_size;
state_var<netlist_time> m_off;
- netlist_time m_inc[32];
+ std::array<netlist_time, 32> m_inc;
};
// -----------------------------------------------------------------------------
@@ -173,20 +177,19 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(logic_input)
, m_Q(*this, "Q")
- , m_IN(*this, "IN", 0)
+ , m_IN(*this, "IN", false)
/* 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_UPDATE_AFTER_PARAM_CHANGE()
-
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATEI() { }
+ NETLIB_RESETI() { m_Q.initial(0); }
+ NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); }
- protected:
+ private:
logic_output_t m_Q;
param_logic_t m_IN;
@@ -200,12 +203,12 @@ namespace netlist
, m_IN(*this, "IN", 0.0)
{
}
- NETLIB_UPDATE_AFTER_PARAM_CHANGE()
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
- protected:
+ NETLIB_UPDATEI() { }
+ NETLIB_RESETI() { m_Q.initial(0.0); }
+ NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }
+
+ private:
analog_output_t m_Q;
param_double_t m_IN;
};
@@ -278,8 +281,8 @@ namespace netlist
NETLIB_RESETI()
{
- m_RIN.set(1.0 / m_p_RIN(),0,0);
- m_ROUT.set(1.0 / m_p_ROUT(),0,0);
+ 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);
}
NETLIB_UPDATEI()
@@ -310,13 +313,13 @@ namespace netlist
, m_N(*this, "N", 1)
, m_func(*this, "FUNC", "A0")
, m_Q(*this, "Q")
- , m_compiled(this->name() + ".FUNCC", this, this->netlist().state())
+ , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
{
std::vector<pstring> inps;
for (int i=0; i < m_N(); i++)
{
pstring n = plib::pfmt("A{1}")(i);
- m_I.push_back(plib::make_unique<analog_input_t>(*this, n));
+ m_I.push_back(pool().make_poolptr<analog_input_t>(*this, n));
inps.push_back(n);
m_vals.push_back(0.0);
}
@@ -333,7 +336,7 @@ namespace netlist
param_int_t m_N;
param_str_t m_func;
analog_output_t m_Q;
- std::vector<std::unique_ptr<analog_input_t>> m_I;
+ std::vector<pool_owned_ptr<analog_input_t>> m_I;
std::vector<double> m_vals;
plib::pfunction m_compiled;
@@ -357,16 +360,17 @@ 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;
- 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 bf7d03fe3d7..2221d855880 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 "../plib/plists.h"
-#include "../nl_setup.h"
-#include "../plib/palloc.h"
+#include "netlist/nl_setup.h"
+#include "plib/palloc.h"
+#include "plib/plists.h"
#include <bitset>
@@ -24,7 +24,7 @@ namespace netlist
template <typename T>
struct sbitset
{
- typedef T type;
+ using type = T;
sbitset() : m_bs(0) { }
/* explicit */ sbitset(T v) : m_bs(v) { }
@@ -77,8 +77,8 @@ namespace netlist
return ret;
}
- static constexpr sbitset all_bits() { return sbitset(~static_cast<T>(0)); }
- static constexpr sbitset no_bits() { return sbitset(static_cast<T>(0)); }
+ 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)); }
private:
T m_bs;
};
@@ -122,8 +122,18 @@ namespace netlist
}
}
- uint_least64_t mask() const { return static_cast<uint_least64_t>(-1); }
-
+ 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
+ }
+ }
private:
void *m_data;
size_t m_size;
@@ -134,7 +144,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_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
+ m_out_state(outs), m_timing(timing), m_timing_nt(timing_nt),
m_num_bits(m_NI),
m_size(1 << (m_num_bits))
{
@@ -151,7 +161,7 @@ namespace netlist
unsigned m_NO;
unsigned m_NI;
bool *m_initialized;
- packed_int m_outs;
+ packed_int m_out_state;
uint_least8_t *m_timing;
netlist_time *m_timing_nt;
@@ -178,51 +188,27 @@ 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> out(plib::psplit(io[1], ","));
- nl_assert_always(out.size() == m_NO, "output count wrong");
+ std::vector<pstring> outputs(plib::psplit(io[1], ","));
+ nl_assert_always(outputs.size() == m_NO, "output count wrong");
for (std::size_t i=0; i < m_NI; i++)
{
- inout[i] = inout[i].trim();
+ inout[i] = plib::trim(inout[i]);
m_I.emplace(i, *this, inout[i]);
}
for (std::size_t i=0; i < m_NO; 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];
+ 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];
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
}
// ----------------------------------------------------------------------------------------
@@ -238,15 +224,20 @@ namespace netlist
: netlist_base_factory_truthtable_t(name, classname, def_param, sourcefile)
{ }
- plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
+ pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override
{
- typedef nld_truthtable_t<m_NI, m_NO> tt_type;
+ using tt_type = nld_truthtable_t<m_NI, m_NO>;
truthtable_parser desc_s(m_NO, m_NI, &m_ttbl.m_initialized,
- packed_int(m_ttbl.m_outs, sizeof(m_ttbl.m_outs[0]) * 8),
- m_ttbl.m_timing, m_ttbl.m_timing_nt);
+ 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());
desc_s.parse(m_desc);
- return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, m_ttbl, 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);
}
private:
typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
@@ -259,7 +250,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_outs[state] == m_outs[tt_bitset(state).set(j)])
+ if (m_out_state[state] == m_out_state[tt_bitset(state).set(j)])
ignore.set(j);
}
@@ -285,7 +276,7 @@ namespace netlist
{
tt_bitset b = tign.expand_and(k);
// will any of the inputs ignored change the output if changed?
- if (m_outs[state] != m_outs[(state & tign.invert()) | b])
+ if (m_out_state[state] != m_out_state[(state & tign.invert()) | b])
{
t[j] = true;
break;
@@ -318,21 +309,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 = list[cur].trim();
+ pstring elem = plib::trim(list[cur]);
uint_least64_t start = 0;
uint_least64_t end = 0;
- if (elem.equals("0"))
+ if (elem == "0")
{
start = 0;
end = 0;
}
- else if (elem.equals("1"))
+ else if (elem == "1")
{
start = 1;
end = 1;
}
- else if (elem.equals("X"))
+ else if (elem == "X")
{
start = 0;
end = 1;
@@ -352,10 +343,10 @@ void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list,
else
{
// cutoff previous inputs and outputs for ignore
- 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);
+ 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);
for (std::size_t j=0; j<m_NO; j++)
m_timing[nstate * m_NO + j] = timing_index[j];
}
@@ -375,12 +366,12 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
line++;
for (unsigned j=0; j < m_size; j++)
- m_outs.set(j, tt_bitset::all_bits());
+ m_out_state.set(j, tt_bitset::all_bits());
for (int j=0; j < 16; j++)
m_timing_nt[j] = netlist_time::zero();
- while (!ttline.equals(""))
+ while (!(ttline == ""))
{
std::vector<pstring> io(plib::psplit(ttline,"|"));
// checks
@@ -402,12 +393,13 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
*/
for (unsigned j=0; j<m_NO; j++)
{
- pstring outs = out[j].trim();
- if (outs.equals("1"))
+ pstring outs = plib::trim(out[j]);
+ if (outs == "1")
val.set(j);
else
- 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()));
+ 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])));
uint_least8_t k=0;
while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t)
k++;
@@ -450,9 +442,9 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
}
for (size_t i=0; i<m_size; i++)
{
- if (m_outs[i] == m_outs.mask())
+ if (m_out_state[i] == m_out_state.mask())
throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
- m_outs.set(i, m_outs[i] | (ign[i] << m_NO));;
+ m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO));
}
*m_initialized = true;
@@ -460,26 +452,21 @@ 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(family_TTL())
-{
-}
-
-netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
+: factory::element_t(name, classname, def_param, sourcefile), m_family_desc(family_TTL())
{
}
-
#define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
- ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
+ ret = plib::make_unique<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)
-void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
+plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &desc, const pstring &sourcefile)
{
- netlist_base_factory_truthtable_t *ret;
+ plib::unique_ptr<netlist_base_factory_truthtable_t> ret;
switch (desc.ni * 100 + desc.no)
{
@@ -500,9 +487,9 @@ void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
nl_assert_always(false, msg);
}
ret->m_desc = desc.desc;
- 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));
+ ret->m_family_name = desc.family;
+
+ return ret;
}
} //namespace devices
diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h
index 311f5ebd8ca..1217d7ee873 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 "../nl_setup.h"
-#include "../nl_base.h"
-#include "../plib/putil.h"
+#include "netlist/nl_base.h"
+#include "netlist/nl_setup.h"
+#include "plib/putil.h"
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT> \
@@ -29,17 +29,9 @@
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
{
@@ -52,11 +44,35 @@ namespace netlist
};
template<unsigned bits> struct uint_for_size;
- 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<> 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<std::size_t m_NI, std::size_t m_NO>
NETLIB_OBJECT(truthtable_t)
@@ -65,22 +81,23 @@ namespace netlist
detail::family_setter_t m_fam;
public:
- typedef typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type type_t;
+ using type_t = typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type;
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_initialized(false)
+ : m_timing_index{0}
+ , 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>
@@ -90,7 +107,6 @@ namespace netlist
: 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);
@@ -100,13 +116,14 @@ namespace netlist
NETLIB_RESETI()
{
- m_active = 0;
+ int active_outputs = 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)
- m_active++;
+ active_outputs++;
+ set_active_outputs(active_outputs);
}
NETLIB_UPDATEI()
@@ -116,28 +133,14 @@ namespace netlist
void inc_active() NL_NOEXCEPT override
{
- if (m_NI >= m_min_devices_for_deactivate)
- if (++m_active == 1)
- {
- process<false>();
- }
+ process<false>();
}
void dec_active() NL_NOEXCEPT override
{
- /* 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;
- }
+ 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;
@@ -153,46 +156,44 @@ namespace netlist
netlist_time mt(netlist_time::zero());
type_t nstate(0);
- if (m_NI >= m_min_devices_for_deactivate)
- {
- 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;
- }
- }
+ 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 (!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);
+ 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);
}
+ else
+ nstate = aa<m_NI, type_t>().f(m_I, ign);
+#endif
- const type_t outstate(m_ttp.m_outs[nstate]);
+ const type_t outstate(m_ttp.m_out_state[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[timebase]);
- const auto *tim = m_ttp.m_timing_nt;
+ const auto *t(&m_ttp.m_timing_index[timebase]);
+ const auto *tim = m_ttp.m_timing_nt.data();
if (doOUT)
for (std::size_t i = 0; i < m_NO; out >>= 1, ++i)
@@ -201,18 +202,14 @@ namespace netlist
for (std::size_t i = 0; i < m_NO; out >>= 1, ++i)
m_Q[i].set_Q_time(out & 1, mt + tim[t[i]]);
- 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();
- }
+ 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;
};
@@ -222,15 +219,15 @@ namespace netlist
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;
- const logic_family_desc_t *m_family;
+ pstring m_family_name;
+ const logic_family_desc_t *m_family_desc;
};
- void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile);
+ /* 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);
- } //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 8ea6f148864..86f2450d301 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 "../nl_setup.h"
-#include "../devices/net_lib.h"
+#include "netlist/nl_setup.h"
+#include "netlist/devices/net_lib.h"
#include "nlm_base.h"
/* ----------------------------------------------------------------------------
@@ -12,9 +12,14 @@ 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)")
@@ -26,9 +31,16 @@ 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)")
- NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1)")
+ 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("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)")
@@ -46,6 +58,8 @@ 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()
/* ----------------------------------------------------------------------------
@@ -74,19 +88,22 @@ 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(family_models);
- INCLUDE(TTL74XX_lib);
- INCLUDE(CD4XXX_lib);
- INCLUDE(OPAMP_lib);
- INCLUDE(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)
NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_base.h b/src/lib/netlist/macro/nlm_base.h
index 5ecf8071e98..6a88ad5a1be 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
/* ----------------------------------------------------------------------------
* Netlist Macros
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index 9ce786ca85e..5ebd5593123 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 "../devices/nld_system.h"
-#include "../devices/nld_4020.h"
-#include "../devices/nld_4066.h"
-#include "../devices/nld_4316.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"
/*
* 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 527336c1e8e..d4d9c97fdc2 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
/*
* Devices:
diff --git a/src/lib/netlist/macro/nlm_opamp.cpp b/src/lib/netlist/macro/nlm_opamp.cpp
index 122b324f777..849f7820046 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 "../devices/net_lib.h"
+#include "netlist/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 9cffbb29c87..fbd7547c976 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 "../nl_setup.h"
+#include "netlist/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 7e31ae27bb4..ea0eb1539a8 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 "../devices/nld_system.h"
+#include "netlist/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 7c38d8ad363..ee231fbd6db 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 "../nl_setup.h"
+#include "netlist/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 df1b873a468..58cab049ae7 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 "../devices/nld_schmitt.h"
-#include "../devices/nld_system.h"
+#include "netlist/devices/nld_schmitt.h"
+#include "netlist/devices/nld_system.h"
/*
@@ -825,8 +825,9 @@ 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("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("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 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 c8868e45f7f..21ff99f2efe 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 "../nl_setup.h"
+#include "netlist/nl_setup.h"
#ifndef __PLIB_PREPROCESSOR__
diff --git a/src/lib/netlist/netlist_types.h b/src/lib/netlist/netlist_types.h
deleted file mode 100644
index 0bd32be21be..00000000000
--- a/src/lib/netlist/netlist_types.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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 9a513c00804..ad048e899bf 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -8,18 +8,19 @@
#include "solver/nld_matrix_solver.h"
#include "solver/nld_solver.h"
-#include "plib/putil.h"
#include "plib/palloc.h"
+#include "plib/pmempool.h"
+#include "plib/putil.h"
-#include "nl_base.h"
-#include "devices/nlid_system.h"
#include "devices/nlid_proxy.h"
+#include "devices/nlid_system.h"
#include "macro/nlm_base.h"
+#include "nl_base.h"
#include "nl_errstr.h"
-#include <cstring>
#include <cmath>
+#include <cstring>
#include <limits>
namespace netlist
@@ -27,14 +28,13 @@ namespace netlist
namespace detail
{
- static plib::mempool *pool()
- {
- static plib::mempool *s_pool = nullptr;
- if (s_pool == nullptr)
- s_pool = new plib::mempool(65536, 16);
- return s_pool;
- }
+ //static plib::mempool *pool()
+ //{
+ // static plib::mempool s_pool(655360, 32);
+ // return &s_pool;
+ //}
+#if 0
void * object_t::operator new (size_t size)
{
void *ret = nullptr;
@@ -44,38 +44,30 @@ 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
-}
-
-nl_exception::~nl_exception()
-{
-}
+} // namespace detail
// ----------------------------------------------------------------------------------------
// 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:
@@ -90,17 +82,17 @@ public:
m_R_low = 1.0;
m_R_high = 130.0;
}
- 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> 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;
};
-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
+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
{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-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
+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
{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
class logic_family_cd4xxx_t : public logic_family_desc_t
@@ -117,17 +109,18 @@ public:
m_R_low = 10.0;
m_R_high = 10.0;
}
- 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> 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;
};
-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
+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
{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-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
+
+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
{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
const logic_family_desc_t *family_TTL()
@@ -146,10 +139,10 @@ const logic_family_desc_t *family_CD4XXX()
// queue_t
// ----------------------------------------------------------------------------------------
-detail::queue_t::queue_t(netlist_t &nl)
- : timed_queue<pqentry_t<net_t *, netlist_time>, false>(512)
+detail::queue_t::queue_t(netlist_state_t &nl)
+ : timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>(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)
@@ -158,52 +151,56 @@ detail::queue_t::queue_t(netlist_t &nl)
void detail::queue_t::register_state(plib::state_manager_t &manager, const pstring &module)
{
- netlist().log().debug("register_state\n");
+ //state().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()
+void detail::queue_t::on_pre_save(plib::state_manager_t &manager)
{
- netlist().log().debug("on_pre_save\n");
+ plib::unused_var(manager);
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] = netlist().find_net_id(this->listptr()[i].m_object);
+ m_net_ids[i] = state().find_net_id(this->listptr()[i].m_object);
}
}
-void detail::queue_t::on_post_load()
+void detail::queue_t::on_post_load(plib::state_manager_t &manager)
{
+ 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 = netlist().m_nets[m_net_ids[i]].get();
+ detail::net_t *n = state().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(plib::make_unique<pstring>(aname))
+// : m_name(aname)
{
+ name_hash().insert({this, aname});
}
-detail::object_t::~object_t()
+pstring detail::object_t::name() const
{
-}
-
-const pstring &detail::object_t::name() const
-{
- return *m_name;
+ return name_hash().find(this)->second;
+ //return m_name;
}
// ----------------------------------------------------------------------------------------
@@ -230,7 +227,7 @@ detail::terminal_type detail::core_terminal_t::type() const
return terminal_type::OUTPUT;
else
{
- netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
+ state().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
return terminal_type::TERMINAL; // please compiler
}
}
@@ -239,159 +236,38 @@ detail::terminal_type detail::core_terminal_t::type() const
// netlist_t
// ----------------------------------------------------------------------------------------
-netlist_t::netlist_t(const pstring &aname)
- : m_time(netlist_time::zero())
- , m_queue(*this)
- , m_mainclock(nullptr)
+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_params(nullptr)
- , m_name(aname)
- , m_log(*this)
- , m_lib(nullptr)
- , m_state()
-{
- 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()
-{
- m_nets.clear();
- m_devices.clear();
-}
-
-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_time(netlist_time::zero())
+ , m_mainclock(nullptr)
+ , m_queue(*m_state)
{
- 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()
- );
+ 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");
}
+// ----------------------------------------------------------------------------------------
+// netlist_t
+// ----------------------------------------------------------------------------------------
-
-void netlist_t::start()
+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))
{
- 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()
{
log().debug("Printing statistics ...\n");
@@ -401,7 +277,7 @@ void netlist_t::stop()
m_solver->stop();
}
-detail::net_t *netlist_t::find_net(const pstring &name) const
+detail::net_t *netlist_state_t::find_net(const pstring &name) const
{
for (auto & net : m_nets)
if (net->name() == name)
@@ -410,7 +286,7 @@ detail::net_t *netlist_t::find_net(const pstring &name) const
return nullptr;
}
-std::size_t netlist_t::find_net_id(const detail::net_t *net) const
+std::size_t netlist_state_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)
@@ -420,7 +296,7 @@ std::size_t netlist_t::find_net_id(const detail::net_t *net) const
-void netlist_t::rebuild_lists()
+void netlist_state_t::rebuild_lists()
{
for (auto & net : m_nets)
net->rebuild_list();
@@ -429,32 +305,44 @@ void netlist_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_time(netlist_time::zero());
+ m_mainclock->m_Q.net().set_next_scheduled_time(netlist_time::zero());
//if (m_solver != nullptr)
- // m_solver->do_reset();
-
- std::unordered_map<core_device_t *, bool> m;
+ // m_solver->reset();
- for (auto &d : m_devices)
- {
- m[d.get()] = d->get_hint_deactivate();
- }
+ m_state->reset();
+}
+void netlist_state_t::reset()
+{
+ //FIXME: never used ???
+ std::unordered_map<core_device_t *, bool> m;
// Reset all nets once !
- for (auto & n : m_nets)
+ log().verbose("Call reset on all nets:");
+ for (auto & n : nets())
n->reset();
// Reset all devices once !
+ log().verbose("Call reset on all devices:");
for (auto & dev : m_devices)
- dev->do_reset();
+ dev.second->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->update_param();
+ dev.second->update_param();
// Step all devices once !
/*
@@ -462,9 +350,9 @@ void netlist_t::reset()
* variations are explicitly stated in the breakout manual.
*/
- const unsigned startup_strategy = 1; //! \note make this a parameter
+ auto *netlist_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
- switch (startup_strategy)
+ switch (netlist_params->m_startup_strategy())
{
case 0:
{
@@ -472,7 +360,7 @@ void netlist_t::reset()
std::vector<nldelegate *> t;
log().verbose("Using default startup strategy");
for (auto &n : m_nets)
- for (auto & term : n->m_core_terms)
+ for (auto & term : n->core_terms())
if (term->m_delegate.has_object())
{
if (!plib::container::contains(t, &term->m_delegate))
@@ -480,70 +368,68 @@ void netlist_t::reset()
t.push_back(&term->m_delegate);
term->m_delegate();
}
- core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ auto *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
if (!plib::container::contains(d, dev))
d.push_back(dev);
}
- log().verbose("Call update on devices which need parameter update:");
- for (auto & dev : m_devices)
- if (dev->needs_update_after_param_change())
- {
- 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();
+ if (!plib::container::contains(d, dev.second.get()))
+ {
+ log().verbose("\t ...{1}", dev.second->name());
+ dev.second->update();
+ }
}
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]->update_dev();
+ m_devices[--i].second->update();
+
+ for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
+ n->update_inputs();
+
}
break;
case 2: // brute force forward
{
+ log().verbose("Using brute force forward startup strategy");
for (auto &d : m_devices)
- d->update_dev();
+ d.second->update();
}
break;
}
#if 1
/* the above may screw up m_active and the list */
- for (auto &n : m_nets)
- n->rebuild_list();
+ rebuild_lists();
#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.top());
- m_queue.pop();
+ detail::queue_t::entry_t e(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.top();
- m_queue.pop();
+ e = m_queue.pop();
m_time = e.m_exec_time;
}
}
@@ -551,9 +437,7 @@ 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.time());
-
- detail::queue_t::entry_t e;
+ netlist_time mc_time(mc_net.next_scheduled_time());
do
{
@@ -565,37 +449,37 @@ void netlist_t::process_queue(const netlist_time &delta) NL_NOEXCEPT
mc_time += inc;
}
- e = m_queue.top();
- m_queue.pop();
+ detail::queue_t::entry_t e(m_queue.pop());
m_time = e.m_exec_time;
if (e.m_object != nullptr)
{
e.m_object->update_devs();
m_perf_out_processed.inc();
}
- } while (e.m_object != nullptr);
- mc_net.set_time(mc_time);
+ else
+ break;
+ } while (true); //while (e.m_object != nullptr);
+ mc_net.set_next_scheduled_time(mc_time);
}
- m_stat_mainloop.stop();
}
void netlist_t::print_stats() const
{
- if (nperftime_t::enabled)
+ if (nperftime_t<NL_KEEP_STATISTICS>::enabled)
{
std::vector<size_t> index;
- for (size_t i=0; i<m_devices.size(); i++)
+ for (size_t i=0; i < m_state->m_devices.size(); i++)
index.push_back(i);
std::sort(index.begin(), index.end(),
- [&](size_t i1, size_t i2) { return m_devices[i1]->m_stat_total_time.total() < m_devices[i2]->m_stat_total_time.total(); });
+ [&](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(); });
- nperftime_t::type total_time(0);
- uint_least64_t total_count(0);
+ nperftime_t<NL_KEEP_STATISTICS>::type total_time(0);
+ nperftime_t<NL_KEEP_STATISTICS>::ctype total_count(0);
for (auto & j : index)
{
- auto entry = m_devices[j].get();
+ auto entry = m_state->m_devices[j].second.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());
@@ -603,22 +487,27 @@ void netlist_t::print_stats() const
total_count += entry->m_stat_total_time.count();
}
- nperftime_t overhead;
- nperftime_t test;
- overhead.start();
- for (int j=0; j<100000;j++)
+ 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;
{
- test.start();
- test.stop();
+ auto overhead_guard(overhead.guard());
+ for (int j=0; j<100000;j++)
+ {
+ auto test_guard(test.guard());
+ }
}
- overhead.stop();
- nperftime_t::type total_overhead = overhead()
- * static_cast<nperftime_t::type>(total_count)
- / static_cast<nperftime_t::type>(200000);
+ 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);
- log().verbose("Queue Pushes {1:15}", queue().m_prof_call());
- log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove());
+ 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("Total loop {1:15}", m_stat_mainloop());
/* Only one serialization should be counted in total time */
@@ -627,29 +516,36 @@ 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::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
- / static_cast<nperftime_t::type>(queue().m_prof_call());
+ 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());
log().verbose("Overhead per pop {1:11}", overhead_per_pop );
log().verbose("");
- for (auto &entry : m_devices)
+
+ auto trigger = total_count * 200 / 1000000; // 200 ppm
+ for (auto &entry : m_state->m_devices)
{
- if (entry->m_stat_inc_active() > 3 * entry->m_stat_total_time.count())
- log().verbose("HINT({}, NO_DEACTIVATE)", entry->name());
+ 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());
}
}
}
-core_device_t *netlist_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const
+core_device_t *netlist_state_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.get()))
+ if (cc(d.second.get()))
{
if (ret != nullptr)
- this->log().fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
+ m_log.fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
else
- ret = d.get();
+ ret = d.second.get();
}
}
return ret;
@@ -660,11 +556,12 @@ core_device_t *netlist_t::get_single_device(const pstring &classname, bool (*cc)
// core_device_t
// ----------------------------------------------------------------------------------------
-core_device_t::core_device_t(netlist_t &owner, const pstring &name)
+core_device_t::core_device_t(netlist_state_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());
@@ -673,17 +570,14 @@ core_device_t::core_device_t(netlist_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.netlist())
+ , netlist_ref(owner.state())
, 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());
- owner.netlist().register_dev(plib::owned_ptr<core_device_t>(this, false));
-}
-
-core_device_t::~core_device_t()
-{
+ state().add_dev(this->name(), pool_owned_ptr<core_device_t>(this, false));
}
void core_device_t::set_default_delegate(detail::core_terminal_t &term)
@@ -692,16 +586,16 @@ void core_device_t::set_default_delegate(detail::core_terminal_t &term)
term.m_delegate.set(&core_device_t::update, this);
}
-plib::plog_base<netlist_t, NL_DEBUG> &core_device_t::log()
+log_type & core_device_t::log()
{
- return netlist().log();
+ return state().log();
}
// ----------------------------------------------------------------------------------------
// device_t
// ----------------------------------------------------------------------------------------
-device_t::device_t(netlist_t &owner, const pstring &name)
+device_t::device_t(netlist_state_t &owner, const pstring &name)
: core_device_t(owner, name)
{
}
@@ -711,14 +605,14 @@ device_t::device_t(core_device_t &owner, const pstring &name)
{
}
-device_t::~device_t()
+setup_t &device_t::setup()
{
- //log().debug("~net_device_t\n");
+ return state().setup();
}
-setup_t &device_t::setup()
+const setup_t &device_t::setup() const
{
- return netlist().setup();
+ return state().setup();
}
void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term)
@@ -762,9 +656,14 @@ 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.netlist().setup().family_from_model(desc));
+ dev.set_logic_family(dev.setup().family_from_model(desc));
}
detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc)
@@ -776,81 +675,45 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
+detail::net_t::net_t(netlist_state_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", QS_DELIVERED)
- , m_active(*this, "m_active", 0)
- , m_time(*this, "m_time", netlist_time::zero())
+ , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED)
+ , m_next_scheduled_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->state() != logic_t::STATE_INP_PASSIVE)
+ if (term->terminal_state() != logic_t::STATE_INP_PASSIVE)
{
m_list_active.push_back(term);
- cnt++;
+ term->set_copied_input(m_cur_Q);
}
- m_active = cnt;
}
-
-void detail::net_t::process(unsigned Mask)
+template <typename T>
+void detail::net_t::process(const T mask, netlist_sig_t sig)
{
+ m_cur_Q = sig;
+
for (auto & p : m_list_active)
{
+ p.set_copied_input(sig);
+
p.device().m_stat_call_count.inc();
- if ((p.state() & Mask) != 0)
+ if ((p.terminal_state() & mask))
{
- p.device().m_stat_total_time.start();
+ auto g(p.device().m_stat_total_time.guard());
+ //p.device().m_stat_total_time.start();
p.m_delegate();
- p.device().m_stat_total_time.stop();
+ //p.device().m_stat_total_time.stop();
}
}
}
@@ -859,67 +722,59 @@ void detail::net_t::update_devs() NL_NOEXCEPT
{
nl_assert(this->isRailNet());
- const unsigned mask((m_new_Q << core_terminal_t::INP_LH_SHIFT)
- | (m_cur_Q<<core_terminal_t::INP_HL_SHIFT));
+ const auto new_Q(m_new_Q);
- m_in_queue = QS_DELIVERED; /* mark as taken ... */
+ const auto mask((new_Q << core_terminal_t::INP_LH_SHIFT)
+ | (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
+ 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:
- m_cur_Q = m_new_Q;
- process(core_terminal_t::STATE_INP_LH | core_terminal_t::STATE_INP_ACTIVE);
+ process(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q);
break;
default:
+ /* do nothing */
break;
}
}
void detail::net_t::reset()
{
- m_time = netlist_time::zero();
- m_active = 0;
- m_in_queue = QS_DELIVERED;
+ m_next_scheduled_time = netlist_time::zero();
+ m_in_queue = queue_status::DELIVERED;
m_new_Q = 0;
m_cur_Q = 0;
- analog_net_t *p = dynamic_cast<analog_net_t *>(this);
+ auto *p = dynamic_cast<analog_net_t *>(this);
if (p != nullptr)
p->m_cur_Analog = 0.0;
- /* rebuild m_list */
+ /* rebuild m_list and reset terminals to active or analog out state */
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();
-
- for (core_terminal_t *ct : m_core_terms)
- if (ct->state() != logic_t::STATE_INP_PASSIVE)
- m_active++;
+ if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE)
+ m_list_active.push_back(ct);
+ ct->set_copied_input(m_cur_Q);
+ }
}
void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
{
for (auto &t : m_core_terms)
if (t == &terminal)
- netlist().log().fatal(MF_2_NET_1_DUPLICATE_TERMINAL_2, name(),
+ state().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)
@@ -930,10 +785,8 @@ void detail::net_t::remove_terminal(detail::core_terminal_t &terminal)
plib::container::remove(m_core_terms, &terminal);
}
else
- netlist().log().fatal(MF_2_REMOVE_TERMINAL_1_FROM_NET_2, terminal.name(),
+ state().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)
@@ -941,37 +794,28 @@ 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_t &nl, const pstring &aname, detail::core_terminal_t *mr)
+logic_net_t::logic_net_t(netlist_state_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_t &nl, const pstring &aname, detail::core_terminal_t *mr)
+analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr)
: net_t(nl, aname, mr)
, m_cur_Analog(*this, "m_cur_Analog", 0.0)
, m_solver(nullptr)
{
}
-analog_net_t::~analog_net_t()
-{
-}
-
// ----------------------------------------------------------------------------------------
// core_terminal_t
// ----------------------------------------------------------------------------------------
@@ -981,42 +825,19 @@ 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)
@@ -1025,26 +846,18 @@ 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::terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm)
: analog_t(dev, aname, STATE_BIDIR)
-, m_otherterm(nullptr)
, m_Idr1(nullptr)
, m_go1(nullptr)
, m_gt1(nullptr)
+, m_connected_terminal(otherterm)
{
- netlist().setup().register_term(*this);
-}
-
-terminal_t::~terminal_t()
-{
+ state().setup().register_term(*this);
}
void terminal_t::solve_now()
@@ -1055,7 +868,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())
@@ -1077,16 +890,12 @@ 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.netlist(), name() + ".net", this)
+ , m_my_net(dev.state(), name() + ".net", this)
{
this->set_net(&m_my_net);
- netlist().m_nets.push_back(plib::owned_ptr<logic_net_t>(&m_my_net, false));
+ state().register_net(pool_owned_ptr<logic_net_t>(&m_my_net, false));
set_logic_family(dev.logic_family());
- netlist().setup().register_term(*this);
-}
-
-logic_output_t::~logic_output_t()
-{
+ state().setup().register_term(*this);
}
void logic_output_t::initial(const netlist_sig_t val)
@@ -1102,11 +911,7 @@ 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)
{
- netlist().setup().register_term(*this);
-}
-
-analog_input_t::~analog_input_t()
-{
+ state().setup().register_term(*this);
}
// ----------------------------------------------------------------------------------------
@@ -1115,17 +920,13 @@ analog_input_t::~analog_input_t()
analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
: analog_t(dev, aname, STATE_OUT)
- , m_my_net(dev.netlist(), name() + ".net", this)
+ , m_my_net(dev.state(), name() + ".net", this)
{
- netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(&m_my_net, false));
+ state().register_net(pool_owned_ptr<analog_net_t>(&m_my_net, false));
this->set_net(&m_my_net);
//net().m_cur_Analog = NL_FCONST(0.0);
- netlist().setup().register_term(*this);
-}
-
-analog_output_t::~analog_output_t()
-{
+ state().setup().register_term(*this);
}
void analog_output_t::initial(const nl_double val)
@@ -1142,11 +943,7 @@ 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());
- netlist().setup().register_term(*this);
-}
-
-logic_input_t::~logic_input_t()
-{
+ state().setup().register_term(*this);
}
// ----------------------------------------------------------------------------------------
@@ -1156,11 +953,7 @@ logic_input_t::~logic_input_t()
param_t::param_t(device_t &device, const pstring &name)
: device_object_t(device, device.name() + "." + name)
{
- device.setup().register_param(this->name(), *this);
-}
-
-param_t::~param_t()
-{
+ device.setup().register_param_t(this->name(), *this);
}
param_t::param_type_t param_t::param_type() const
@@ -1177,7 +970,7 @@ param_t::param_type_t param_t::param_type() const
return POINTER;
else
{
- netlist().log().fatal(MF_1_UNKNOWN_PARAM_TYPE, name());
+ state().log().fatal(MF_1_UNKNOWN_PARAM_TYPE, name());
return POINTER; /* Please compiler */
}
}
@@ -1186,50 +979,28 @@ param_t::param_type_t param_t::param_type() const
void param_t::update_param()
{
device().update_param();
- if (device().needs_update_after_param_change())
- device().update_dev();
}
-const pstring param_model_t::model_type()
+pstring param_t::get_initial(const device_t &dev, bool *found)
{
- if (m_map.size() == 0)
- netlist().setup().model_parse(this->Value(), m_map);
- return m_map["COREMODEL"];
+ pstring res = dev.setup().get_initial_param_val(this->name(), "");
+ *found = (res != "");
+ return res;
}
-param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val)
-: param_t(device, name)
-{
- 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)
+const pstring param_model_t::model_type()
{
- m_param = device.setup().get_initial_param_val(this->name(),val);
- netlist().save(*this, m_param, "m_param");
+ return state().setup().models().model_type(value());
}
-param_int_t::param_int_t(device_t &device, const pstring &name, const int val)
+param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &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)
+void param_str_t::changed()
{
- 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)
@@ -1241,53 +1012,25 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val)
void param_model_t::changed()
{
- netlist().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
- m_map.clear();
+ state().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
}
const pstring param_model_t::model_value_str(const pstring &entity)
{
- if (m_map.size() == 0)
- netlist().setup().model_parse(this->Value(), m_map);
- return netlist().setup().model_value_str(m_map, entity);
+ return state().setup().models().model_value_str(value(), entity);
}
nl_double param_model_t::model_value(const pstring &entity)
{
- if (m_map.size() == 0)
- netlist().setup().model_parse(this->Value(), m_map);
- return netlist().setup().model_value(m_map, entity);
+ return state().setup().models().model_value(value(), entity);
}
-param_data_t::param_data_t(device_t &device, const pstring &name)
-: param_str_t(device, name, "")
-{
-}
-
-void param_data_t::changed()
-{
-}
-std::unique_ptr<plib::pistream> param_data_t::stream()
+plib::unique_ptr<plib::pistream> param_data_t::stream()
{
- return device().netlist().setup().get_data_stream(Value());
+ return device().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 e56fde89f88..9d0eed869e0 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -9,27 +9,25 @@
#ifndef NLBASE_H_
#define NLBASE_H_
-#include "nl_lists.h"
-#include "nl_time.h"
+#ifdef NL_PROHIBIT_BASEH_INCLUDE
+#error "nl_base.h included. Please correct."
+#endif
+
#include "plib/palloc.h" // owned_ptr
#include "plib/pdynlib.h"
-#include "plib/pstate.h"
#include "plib/pfmtlog.h"
-#include "plib/pstream.h"
+#include "plib/pmempool.h"
#include "plib/ppmf.h"
+#include "plib/pstate.h"
+#include "plib/pstream.h"
-#include <unordered_map>
-
-#ifdef NL_PROHIBIT_BASEH_INCLUDE
-#error "nl_base.h included. Please correct."
-#endif
-
-// ----------------------------------------------------------------------------------------
-// Type definitions
-// ----------------------------------------------------------------------------------------
+#include "nl_errstr.h"
+#include "nl_lists.h"
+#include "nltypes.h"
+#include "plib/ptime.h"
-/*! netlist_sig_t is the type used for logic signals. */
-using netlist_sig_t = std::uint32_t;
+#include <unordered_map>
+#include <vector>
//============================================================
// MACROS / New Syntax
@@ -73,7 +71,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)()
+#define NETLIB_DESTRUCTOR(name) public: virtual ~NETLIB_NAME(name)() noexcept
/*! Define an extended constructor and add further parameters to it.
* The macro allows to add further parameters to a device constructor. This is
@@ -85,14 +83,15 @@ 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; }
@@ -127,36 +126,30 @@ 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() 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_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_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step)
#define NETLIB_SUB(chip) nld_ ## chip
-#define NETLIB_SUBXX(ns, chip) std::unique_ptr< ns :: nld_ ## chip >
+#define NETLIB_SUBXX(ns, chip) pool_owned_ptr< ns :: nld_ ## chip >
-#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name(void) NL_NOEXCEPT
+#define NETLIB_HANDLER(chip, name) void NETLIB_NAME(chip) :: name() 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(void)
+#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param()
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params
-#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals(void)
+#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals()
//============================================================
// Asserts
@@ -169,7 +162,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(plib::pfmt("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("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}", msg, __FILE__, __LINE__, #x); } while (0)
//============================================================
// Namespace starts
@@ -177,6 +170,11 @@ class NETLIB_NAME(name) : public device_t
namespace netlist
{
+ /*! Delegate type for device notification.
+ *
+ */
+ using nldelegate = plib::pmfp<void>;
+
// -----------------------------------------------------------------------------
// forward definitions
// -----------------------------------------------------------------------------
@@ -191,27 +189,23 @@ 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;
- class net_t;
- }
+ } // namespace detail
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
@@ -229,9 +223,12 @@ namespace netlist
explicit nl_exception(const pstring &text //!< text to be passed
)
: plib::pexception(text) { }
- /*! Copy constructor. */
- nl_exception(const nl_exception &e) : plib::pexception(e) { }
- virtual ~nl_exception();
+
+ 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)...)) { }
};
/*! Logic families descriptors are used to create proxy devices.
@@ -242,18 +239,21 @@ namespace netlist
{
public:
logic_family_desc_t();
- virtual ~logic_family_desc_t();
- virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist, const pstring &name,
+ 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,
logic_output_t *proxied) const = 0;
- virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name,
+ virtual 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 = 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 { return VN + m_low_VO; }
- double high_V(const double VN, const double VP) const { return VP - m_high_VO; }
+ 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 R_low() const { return m_R_low; }
double R_high() const { return m_R_high; }
@@ -282,12 +282,14 @@ 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() { } // prohibit polymorphic destruction
+ ~logic_family_t() noexcept = default; // prohibit polymorphic destruction
const logic_family_desc_t *m_logic_family;
};
@@ -317,12 +319,15 @@ 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) noexcept = default;
+ constexpr state_var(const state_var &rhs) = 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) noexcept = default;
+ C14CONSTEXPR state_var &operator=(const state_var &rhs) = 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.
@@ -345,25 +350,29 @@ namespace netlist
* Please refer to \ref state_var.
*/
template <typename T, std::size_t N>
- struct state_var<T[N]>
+ struct state_array
{
public:
//! Constructor.
template <typename O>
- state_var(O &owner, //!< owner must have a netlist() method.
+ state_array(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_var(const state_var &rhs) NL_NOEXCEPT = default;
+ state_array(const state_array &rhs) noexcept = default;
+ //! Destructor.
+ ~state_array() noexcept = default;
//! Move Constructor.
- 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]; }
+ 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]; }
private:
- T m_value[N];
+ std::array<T, N> m_value;
};
// -----------------------------------------------------------------------------
@@ -382,164 +391,324 @@ namespace netlist
/*! predefined state variable type for sig_t */
using state_var_sig = state_var<netlist_sig_t>;
- // -----------------------------------------------------------------------------
- // object_t
- // -----------------------------------------------------------------------------
+ namespace detail {
- /*! 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:
+ // -----------------------------------------------------------------------------
+ // object_t
+ // -----------------------------------------------------------------------------
- /*! Constructor.
+ /*! The base class for netlist devices, terminals and parameters.
*
- * Every class derived from the object_t class must have a name.
+ * 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.
*/
- explicit object_t(const pstring &aname /*!< string containing name of the object */);
+ class object_t
+ {
+ public:
- /*! return name of the object
- *
- * \returns name of the object.
- */
- const pstring &name() const;
+ /*! 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
- 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
+ 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;
+ }
+ };
- private:
- std::unique_ptr<pstring> m_name;
- };
+ struct netlist_ref
+ {
+ explicit netlist_ref(netlist_state_t &nl);
- struct detail::netlist_ref
- {
- explicit constexpr netlist_ref(netlist_t &nl) : m_netlist(nl) { }
+ COPYASSIGNMOVE(netlist_ref, delete)
- C14CONSTEXPR netlist_t & netlist() NL_NOEXCEPT { return m_netlist; }
- constexpr const netlist_t & netlist() const NL_NOEXCEPT { return m_netlist; }
+ netlist_state_t & state() noexcept;
+ const netlist_state_t & state() const noexcept;
- protected:
- ~netlist_ref() = default; // prohibit polymorphic destruction
+ setup_t & setup() noexcept;
+ const setup_t & setup() const noexcept;
- private:
- netlist_t & m_netlist;
+ netlist_t & exec() noexcept { return m_netlist; }
+ const netlist_t & exec() const noexcept { return m_netlist; }
- };
+ protected:
+ ~netlist_ref() noexcept = default; // prohibit polymorphic destruction
- // -----------------------------------------------------------------------------
- // device_object_t
- // -----------------------------------------------------------------------------
+ private:
+ netlist_t & m_netlist;
- /*! 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.
+ };
+
+ // -----------------------------------------------------------------------------
+ // 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.
*
- * \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);
+ 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;
- /*! 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; }
+ private:
+ core_device_t & m_device;
+ };
- /*! The netlist owning the owner of this object.
- * \returns reference to netlist object.
+ // -----------------------------------------------------------------------------
+ // core_terminal_t
+ // -----------------------------------------------------------------------------
+
+ /*! Base class for all terminals.
+ *
+ * All terminals are derived from this class.
+ *
*/
- netlist_t &netlist() NL_NOEXCEPT;
- const netlist_t &netlist() const NL_NOEXCEPT;
- private:
- core_device_t & m_device;
-};
+ class net_t;
- /*! Delegate type for device notification.
- *
- */
- typedef plib::pmfp<void> nldelegate;
+ class core_terminal_t : public device_object_t,
+ public plib::linkedlist_t<core_terminal_t>::element_t
+ {
+ public:
- // -----------------------------------------------------------------------------
- // core_terminal_t
- // -----------------------------------------------------------------------------
+ using list_t = std::vector<core_terminal_t *>;
- /*! 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:
+ 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); }
+
+ const net_t & net() const noexcept { return *m_net;}
+ net_t & net() noexcept { return *m_net;}
- using list_t = std::vector<core_terminal_t *>;
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
- static constexpr const unsigned INP_HL_SHIFT = 0;
- static constexpr const unsigned INP_LH_SHIFT = 1;
- static constexpr const unsigned INP_ACTIVE_SHIFT = 2;
+ 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; }
- 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
+ void reset() noexcept { set_state(is_type(OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); }
+
+ nldelegate m_delegate;
+ #if USE_COPY_INSTEAD_OF_REFERENCE
+ void set_copied_input(netlist_sig_t val)
+ {
+ m_Q = val;
+ }
+
+ state_var_sig m_Q;
+ #else
+ void set_copied_input(netlist_sig_t val) const { plib::unused_var(val); }
+ #endif
+
+ private:
+ net_t * m_net;
+ state_var<state_e> m_state;
};
- core_terminal_t(core_device_t &dev, const pstring &aname,
- const state_e state, nldelegate delegate = nldelegate());
- virtual ~core_terminal_t();
+ // -----------------------------------------------------------------------------
+ // net_t
+ // -----------------------------------------------------------------------------
- /*! 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); }
+ class net_t :
+ public object_t,
+ public netlist_ref
+ {
+ public:
- void set_net(net_t *anet);
- void clear_net();
- bool has_net() const NL_NOEXCEPT { return (m_net != nullptr); }
+ enum class queue_status
+ {
+ DELAYED_DUE_TO_INACTIVE = 0,
+ QUEUED,
+ DELIVERED
+ };
- const net_t & net() const NL_NOEXCEPT { return *m_net;}
- net_t & net() NL_NOEXCEPT { return *m_net;}
+ net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr = nullptr);
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
+ COPYASSIGNMOVE(net_t, delete)
- 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; }
+ virtual ~net_t() noexcept = default;
- void reset();
+ void reset();
- nldelegate m_delegate;
+ void toggle_new_Q() noexcept { m_new_Q = (m_cur_Q ^ 1); }
- private:
- net_t * m_net;
- state_var<state_e> m_state;
- };
+ 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:
+
+ /* only used for logic nets */
+ netlist_sig_t Q() const noexcept { return m_cur_Q; }
+
+ /* only used for logic nets */
+ void initial(const netlist_sig_t val) noexcept
+ {
+ m_cur_Q = m_new_Q = val;
+ update_inputs();
+ }
+
+ /* 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);
+ }
+ }
+
+ /* 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();
+ }
+
+ /* 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(); }
+
+ 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;
+
+ 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 ...
+
+ template <typename T>
+ void process(const T mask, netlist_sig_t sig);
+ };
+ } // namespace detail
// -----------------------------------------------------------------------------
// analog_t
@@ -550,7 +719,6 @@ 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;
@@ -564,53 +732,44 @@ namespace netlist
{
public:
- terminal_t(core_device_t &dev, const pstring &aname);
- virtual ~terminal_t();
+ terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm);
nl_double operator ()() const NL_NOEXCEPT;
- void set(const nl_double &G) NL_NOEXCEPT
+ void set_conductivity(const nl_double G) noexcept
{
- set(G,G, 0.0);
+ set_go_gt_I(-G, G, 0.0);
}
- void set(const nl_double &GO, const nl_double &GT) NL_NOEXCEPT
+ void set_go_gt(const nl_double GO, const nl_double GT) noexcept
{
- set(GO, GT, 0.0);
+ set_go_gt_I(GO, GT, 0.0);
}
- void set(const nl_double &GO, const nl_double &GT, const nl_double &I) NL_NOEXCEPT
+ void set_go_gt_I(const nl_double GO, const nl_double GT, const nl_double I) noexcept
{
- set_ptr(m_Idr1, I);
- set_ptr(m_go1, GO);
- set_ptr(m_gt1, GT);
+ 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;
+ }
}
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) NL_NOEXCEPT
- {
- m_gt1 = gt;
- m_go1 = go;
- m_Idr1 = Idr;
- }
-
- terminal_t *m_otherterm;
+ void set_ptrs(nl_double *gt, nl_double *go, nl_double *Idr) noexcept;
+ 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;
+
};
@@ -623,7 +782,6 @@ 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; }
@@ -647,7 +805,6 @@ 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
{
@@ -679,9 +836,6 @@ namespace netlist
const pstring &aname /*!< name of terminal */
);
- /*! Destructor */
- virtual ~analog_input_t();
-
/*! returns voltage at terminal.
* \returns voltage at terminal.
*/
@@ -694,124 +848,18 @@ 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_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(); }
+ logic_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
- protected:
- private:
+ 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;
};
@@ -823,9 +871,7 @@ namespace netlist
friend class detail::net_t;
- analog_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
-
- virtual ~analog_net_t();
+ analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
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; }
@@ -849,21 +895,15 @@ 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 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
+ 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
}
@@ -876,7 +916,6 @@ 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);
@@ -904,13 +943,17 @@ namespace netlist
param_t(device_t &device, const pstring &name);
+ COPYASSIGNMOVE(param_t, delete)
+
param_type_t param_type() const;
protected:
- virtual ~param_t(); /* not intended to be destroyed */
+ virtual ~param_t() noexcept = default; /* 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)
{
@@ -923,53 +966,51 @@ namespace netlist
};
- class param_ptr_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); }
- private:
- std::uint8_t* m_param;
- };
+ // -----------------------------------------------------------------------------
+ // numeric parameter template
+ // -----------------------------------------------------------------------------
- class param_logic_t final: public param_t
+ template <typename T>
+ class param_num_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;
- };
+ param_num_t(device_t &device, const pstring &name, const T val);
- class param_int_t final: public param_t
- {
- public:
- 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); }
+ const T operator()() const NL_NOEXCEPT { return m_param; }
+ void setTo(const T &param) { set(m_param, param); }
private:
- int m_param;
+ T m_param;
};
- class param_double_t final: public param_t
+ /* 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_ptr_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); }
+ 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:
- double m_param;
+ std::uint8_t* m_param;
};
+ // -----------------------------------------------------------------------------
+ // string parameter
+ // -----------------------------------------------------------------------------
+
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)
@@ -981,11 +1022,16 @@ 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:
@@ -997,8 +1043,8 @@ namespace netlist
: m_value(param.model_value(name))
{
}
- const double &operator()() const NL_NOEXCEPT { return m_value; }
- operator const double&() const NL_NOEXCEPT { return m_value; }
+ double operator()() const noexcept { return m_value; }
+ operator double() const noexcept { return m_value; }
private:
const double m_value;
};
@@ -1010,24 +1056,29 @@ 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:
- virtual void changed() override;
+ 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_data_t(device_t &device, const pstring &name)
+ : param_str_t(device, name, "")
+ {
+ }
- std::unique_ptr<plib::pistream> stream();
+ plib::unique_ptr<plib::pistream> stream();
protected:
- virtual void changed() override;
+ void changed() override { }
};
// -----------------------------------------------------------------------------
@@ -1041,15 +1092,15 @@ namespace netlist
param_rom_t(device_t &device, const pstring &name);
- const ST & operator[] (std::size_t n) NL_NOEXCEPT { return m_data[n]; }
+ ST operator[] (std::size_t n) const NL_NOEXCEPT { return m_data[n]; }
protected:
- virtual void changed() override
+ void changed() override
{
- stream()->read(&m_data[0],1<<AW);
+ stream()->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW);
}
private:
- ST m_data[1 << AW];
+ std::array<ST, 1 << AW> m_data;
};
// -----------------------------------------------------------------------------
@@ -1062,68 +1113,67 @@ namespace netlist
public detail::netlist_ref
{
public:
- core_device_t(netlist_t &owner, const pstring &name);
+ core_device_t(netlist_state_t &owner, const pstring &name);
core_device_t(core_device_t &owner, const pstring &name);
- virtual ~core_device_t();
+ COPYASSIGNMOVE(core_device_t, delete)
- void update_dev() NL_NOEXCEPT
- {
- do_update();
- }
+ virtual ~core_device_t() noexcept = default;
void do_inc_active() NL_NOEXCEPT
{
if (m_hint_deactivate)
{
- m_stat_inc_active.inc();
- inc_active();
+ if (++m_active_outputs == 1)
+ {
+ m_stat_inc_active.inc();
+ inc_active();
+ }
}
}
void do_dec_active() NL_NOEXCEPT
{
if (m_hint_deactivate)
- dec_active();
+ if (--m_active_outputs == 0)
+ {
+ 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 m_stat_total_time;
- nperfcount_t m_stat_call_count;
- nperfcount_t m_stat_inc_active;
+ 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;
+ 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() { }
- void do_update() NL_NOEXCEPT
- {
- update();
- }
-
- plib::plog_base<netlist_t, NL_DEBUG> &log();
+ log_type & log();
public:
- virtual void timestep(ATTR_UNUSED const nl_double st) { }
+ virtual void timestep(const nl_double st) { plib::unused_var(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;
+ bool m_hint_deactivate;
+ state_var_s32 m_active_outputs;
};
// -----------------------------------------------------------------------------
@@ -1134,17 +1184,20 @@ namespace netlist
{
public:
- device_t(netlist_t &owner, const pstring &name);
+ device_t(netlist_state_t &owner, const pstring &name);
device_t(core_device_t &owner, const pstring &name);
- virtual ~device_t() override;
+ COPYASSIGNMOVE(device_t, delete)
+
+ ~device_t() noexcept override = default;
setup_t &setup();
+ const setup_t &setup() const;
template<class C, typename... Args>
- void register_sub(const pstring &name, std::unique_ptr<C> &dev, const Args&... args)
+ void create_and_register_subdevice(const pstring &name, pool_owned_ptr<C> &dev, Args&&... args)
{
- dev.reset(plib::palloc<C>(*this, name, args...));
+ dev = pool().make_poolptr<C>(*this, name, std::forward<Args>(args)...);
}
void register_subalias(const pstring &name, detail::core_terminal_t &term);
@@ -1167,13 +1220,18 @@ namespace netlist
struct detail::family_setter_t
{
- 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(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)
@@ -1190,19 +1248,25 @@ namespace netlist
* solvers will update inputs after parallel processing.
*/
class detail::queue_t :
- public timed_queue<pqentry_t<net_t *, netlist_time>, false>,
+ public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
public detail::netlist_ref,
public plib::state_manager_t::callback_t
{
public:
- typedef pqentry_t<net_t *, netlist_time> entry_t;
- explicit queue_t(netlist_t &nl);
+ 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;
protected:
void register_state(plib::state_manager_t &manager, const pstring &module) override;
- void on_pre_save() override;
- void on_post_load() override;
+ void on_pre_save(plib::state_manager_t &manager) override;
+ void on_post_load(plib::state_manager_t &manager) override;
private:
std::size_t m_qsize;
@@ -1211,139 +1275,214 @@ namespace netlist
};
// -----------------------------------------------------------------------------
- // netlist_t
+ // netlist_state__t
// -----------------------------------------------------------------------------
-
- class netlist_t : private plib::nocopyassignmove
+ class netlist_state_t
{
public:
- explicit netlist_t(const pstring &aname);
- virtual ~netlist_t();
+ using nets_collection_type = std::vector<pool_owned_ptr<detail::net_t>>;
- /* run functions */
+ /* 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);
- const netlist_time &time() const NL_NOEXCEPT { return m_time; }
- devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; }
+ COPYASSIGNMOVE(netlist_state_t, delete)
- /* never use this in constructors! */
- nl_double gmin() const NL_NOEXCEPT;
+ ~netlist_state_t() noexcept = default;
- 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)); }
+ friend class netlist_t; // allow access to private members
- /* Control functions */
+ template<class C>
+ static bool check_class(core_device_t *p)
+ {
+ return dynamic_cast<C *>(p) != nullptr;
+ }
- void start();
- void stop();
- void reset();
+ template<class C>
+ C *get_single_device(const pstring &classname) const
+ {
+ return dynamic_cast<C *>(get_single_device(classname, check_class<C>));
+ }
- const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
- detail::queue_t &queue() NL_NOEXCEPT { return m_queue; }
+ /* logging and name */
- /* netlist build functions */
+ pstring name() const { return m_name; }
- setup_t &setup() NL_NOEXCEPT { return *m_setup; }
+ log_type & log() { return m_log; }
+ const log_type &log() const { return m_log; }
+
+ plib::dynlib &lib() { return *m_lib; }
+
+ netlist_t &exec() { return m_netlist; }
+ const netlist_t &exec() const { return m_netlist; }
- void register_dev(plib::owned_ptr<core_device_t> dev);
- void remove_dev(core_device_t *dev);
+ /* state handling */
+ plib::state_manager_t &run_state_manager() { return m_state; }
+
+ 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);
+ }
+
+ core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const;
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>
- std::vector<device_class *> get_device_list() const
+ inline std::vector<device_class *> get_device_list()
{
std::vector<device_class *> tmp;
for (auto &d : m_devices)
{
- device_class *dev = dynamic_cast<device_class *>(d.get());
+ auto dev = dynamic_cast<device_class *>(d.second.get());
if (dev != nullptr)
tmp.push_back(dev);
}
return tmp;
}
- template<class C>
- static bool check_class(core_device_t *p)
+ template <typename T>
+ void add_dev(const pstring &name, pool_owned_ptr<T> &&dev)
{
- return dynamic_cast<C *>(p) != nullptr;
+ 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) });
}
- template<class C>
- C *get_single_device(const pstring &classname) const
+ /**
+ * @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)
{
- return dynamic_cast<C *>(get_single_device(classname, check_class<C>));
+ 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;
+ }
}
- /* logging and name */
+ /* sole use is to manage lifetime of family objects */
+ std::vector<std::pair<pstring, plib::unique_ptr<logic_family_desc_t>>> m_family_cache;
- 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; }
+ setup_t &setup() NL_NOEXCEPT { return *m_setup; }
+ const setup_t &setup() const NL_NOEXCEPT { return *m_setup; }
- /* state related */
+ nets_collection_type & nets() { return m_nets; }
+ devices_collection_type & devices() { return m_devices; }
- plib::state_manager_t &state() { return m_state; }
+ // FIXME: make a postload member and include code there
+ void rebuild_lists(); /* must be called after post_load ! */
- 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);
- }
+ private:
- plib::dynlib &lib() { return *m_lib; }
+ void reset();
- // FIXME: find something better
+ 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;
+
+ nets_collection_type m_nets;
/* sole use is to manage lifetime of net objects */
- 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;
+ devices_collection_type m_devices;
- // FIXME: sort rebuild_lists out
- void rebuild_lists(); /* must be called after post_load ! */
- /* logging callback */
- virtual void vlog(const plib::plog_level &l, const pstring &ls) const = 0;
- protected:
+ };
- void print_stats() const;
+ // -----------------------------------------------------------------------------
+ // netlist_t
+ // -----------------------------------------------------------------------------
- private:
+ class netlist_t
+ {
+ public:
- /* 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; }
+ explicit netlist_t(const pstring &aname, plib::unique_ptr<callbacks_t> callbacks);
- core_device_t *get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const;
+ COPYASSIGNMOVE(netlist_t, delete)
- /* mostly rw */
- netlist_time m_time;
- detail::queue_t m_queue;
+ ~netlist_t() noexcept = default;
- /* mostly ro */
+ /* run functions */
- devices::NETLIB_NAME(mainclock) * m_mainclock;
- devices::NETLIB_NAME(solver) * m_solver;
- devices::NETLIB_NAME(netlistparams) *m_params;
+ netlist_time time() const NL_NOEXCEPT { return m_time; }
- 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
+ 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)); }
- plib::state_manager_t m_state;
+ const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
+ detail::queue_t &queue() NL_NOEXCEPT { return m_queue; }
- // performance
- nperftime_t m_stat_mainloop;
- nperfcount_t m_perf_out_processed;
+ /* Control functions */
+
+ void stop();
+ void reset();
+
+ /* state handling */
+
+ plib::state_manager_t &run_state_manager() { return m_state->run_state_manager(); }
+
+ /* only used by nltool to create static c-code */
+ devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; }
+
+ /* 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();
+ }
+
+ netlist_state_t &nlstate() NL_NOEXCEPT { return *m_state; }
+ const netlist_state_t &nlstate() const { return *m_state; }
+
+ log_type & log() { return m_state->log(); }
+ const log_type &log() const { return m_state->log(); }
+
+ void print_stats() const;
+
+ private:
+ plib::unique_ptr<netlist_state_t> m_state;
+ devices::NETLIB_NAME(solver) * m_solver;
+
+ /* mostly rw */
+ PALIGNAS_CACHELINE()
+ netlist_time m_time;
+ devices::NETLIB_NAME(mainclock) * m_mainclock;
- std::vector<plib::owned_ptr<core_device_t>> m_devices;
+ PALIGNAS_CACHELINE()
+ detail::queue_t m_queue;
+
+ // performance
+ nperftime_t<NL_KEEP_STATISTICS> m_stat_mainloop;
+ nperfcount_t<NL_KEEP_STATISTICS> m_perf_out_processed;
};
// -----------------------------------------------------------------------------
@@ -1356,12 +1495,13 @@ namespace netlist
public:
struct init
{
- const char *p[N];
+ std::array<const char *, N> p;
};
- object_array_t(core_device_t &dev, init names)
+ template<typename... Args>
+ object_array_t(core_device_t &dev, init names, Args&&... args)
{
for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, pstring(names.p[i], pstring::UTF8));
+ this->emplace(i, dev, pstring(names.p[i]), std::forward<Args>(args)...);
}
};
@@ -1369,15 +1509,56 @@ 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>
- inline param_rom_t<ST, AW, DW>::param_rom_t(device_t &device, const pstring &name)
+ 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(&m_data[0],1<<AW);
+ f->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW);
else
- device.netlist().log().warning("Rom {1} not found", Value());
+ device.state().log().warning("Rom {1} not found", value());
}
inline void logic_input_t::inactivate() NL_NOEXCEPT
@@ -1385,7 +1566,7 @@ namespace netlist
if (!is_state(STATE_INP_PASSIVE))
{
set_state(STATE_INP_PASSIVE);
- net().dec_active(*this);
+ net().remove_from_active_list(*this);
}
}
@@ -1393,7 +1574,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().inc_active(*this);
+ net().add_to_active_list(*this);
set_state(STATE_INP_ACTIVE);
}
}
@@ -1402,7 +1583,7 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().inc_active(*this);
+ net().add_to_active_list(*this);
set_state(STATE_INP_HL);
}
}
@@ -1411,24 +1592,68 @@ namespace netlist
{
if (is_state(STATE_INP_PASSIVE))
{
- net().inc_active(*this);
+ net().add_to_active_list(*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())
- 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));
+ 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);
}
}
+ 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());
@@ -1441,6 +1666,18 @@ 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());
@@ -1453,8 +1690,14 @@ namespace netlist
inline netlist_sig_t logic_input_t::Q() const NL_NOEXCEPT
{
- nl_assert(state() != STATE_INP_PASSIVE);
+ 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
return net().Q();
+#endif
}
inline nl_double analog_input_t::Q_Analog() const NL_NOEXCEPT
@@ -1471,14 +1714,24 @@ namespace netlist
}
}
- inline netlist_t &detail::device_object_t::netlist() NL_NOEXCEPT
+ 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
{
- return m_device.netlist();
+ return m_device.exec();
}
- inline const netlist_t &detail::device_object_t::netlist() const NL_NOEXCEPT
+ inline const netlist_t &detail::device_object_t::exec() const NL_NOEXCEPT
{
- return m_device.netlist();
+ return m_device.exec();
}
template <typename T>
@@ -1486,18 +1739,18 @@ namespace netlist
state_var<T>::state_var(O &owner, const pstring &name, const T &value)
: m_value(value)
{
- owner.netlist().save(owner, m_value, name);
+ owner.state().save(owner, m_value, owner.name(), name);
}
template <typename T, std::size_t N>
template <typename O>
- state_var<T[N]>::state_var(O &owner, const pstring &name, const T & value)
+ state_array<T,N>::state_array(O &owner, const pstring &name, const T & value)
{
- owner.netlist().save(owner, m_value, name);
+ owner.state().save(owner, m_value, owner.name(), name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
}
-}
+} // namespace netlist
namespace plib
{
@@ -1505,7 +1758,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 6a65abac40a..faa5008ff56 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -26,10 +26,21 @@
* 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 (0)
+#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)
/*
* FIXME: Using truthtable is a lot slower than the explicit device
@@ -43,23 +54,13 @@
#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
@@ -86,24 +87,19 @@
#endif // !defined(USE_OPENMP)
// Use nano-second resolution - Sufficient for now
-#define NETLIST_INTERNAL_RES (UINT64_C(1000000000))
-#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
+
+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(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 b0ebdb2e371..48695e393ec 100644
--- a/src/lib/netlist/nl_dice_compat.h
+++ b/src/lib/netlist/nl_dice_compat.h
@@ -29,6 +29,7 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
#include "analog/nld_twoterm.h"
#include <cmath>
+
#endif
@@ -111,8 +112,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)
@@ -131,9 +132,9 @@ public:
NET_C(name.6, name ## _R.1) \
NET_C(name.6, name ## _C.1) \
NET_C(name ## _R.2, V5) \
- NET_CSTR(# name "_C.2", "GND") \
+ NET_C(name ## _C.2, GND) \
NET_C(name.8, V5) \
- NET_CSTR(# name ".1", "GND")
+ NET_C(name.1, GND)
#define CHIP_555_Astable(name, pdesc) \
NE555_DIP(name) \
@@ -146,9 +147,9 @@ public:
NET_C(name.6, name ## _C.1) \
NET_C(name.2, name ## _C.1) \
NET_C(name ## _R1.2, V5) \
- NET_CSTR(# name "_C.2", "GND") \
+ NET_C(name ## _C.2, GND) \
NET_C(name.8, V5) \
- NET_CSTR(# name ".1", "GND")
+ NET_C(name.1, GND)
#define CHIP_9602_Mono(name, pdesc) \
CHIP(# name, 9602) \
@@ -178,13 +179,13 @@ public:
#define CHIP_INPUT_ACTIVE_LOW(name) \
SWITCH2(name ## _SW) \
NET_C(name ## _SW.1, V5) \
- NET_CSTR(# name "_SW.2", "GND") \
+ NET_C(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_CSTR(# name "_SW.1", "GND") \
+ NET_C(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 35b1e4f6c60..ee3c47f3339 100644
--- a/src/lib/netlist/nl_errstr.h
+++ b/src/lib/netlist/nl_errstr.h
@@ -58,7 +58,8 @@
//#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_ADDING_ALI1_TO_ALIAS_LIST "Error adding alias {1} to alias list"
+#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_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 2bb49590c4b..1f0ac35c6c4 100644
--- a/src/lib/netlist/nl_factory.cpp
+++ b/src/lib/netlist/nl_factory.cpp
@@ -10,102 +10,84 @@
#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_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
+ 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)
{
}
-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>")
+ {
+ }
-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)
-{
-}
-
-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>")
-{
-}
-
-element_t::~element_t()
-{
-}
-
-// ----------------------------------------------------------------------------------------
-// net_device_t_base_factory
-// ----------------------------------------------------------------------------------------
-
-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));
-}
+ // ----------------------------------------------------------------------------------------
+ // net_device_t_base_factory
+ // ----------------------------------------------------------------------------------------
-factory::element_t * list_t::factory_by_name(const pstring &devname)
-{
- for (auto & e : *this)
+ list_t::list_t(log_type &alog)
+ : m_log(alog)
{
- 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
-// -----------------------------------------------------------------------------
+ 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));
+ }
-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);
-}
+ 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
+ }
-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();
-}
+ // -----------------------------------------------------------------------------
+ // factory_lib_entry_t: factory class to wrap macro based chips/elements
+ // -----------------------------------------------------------------------------
-NETLIB_RESET(wrapper)
-{
-}
+ 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);
+ }
-NETLIB_UPDATE(wrapper)
-{
-}
+ void library_element_t::macro_actions(nlparse_t &nparser, const pstring &name)
+ {
+ nparser.namespace_push(name);
+ nparser.include(this->name());
+ nparser.namespace_pop();
+ }
-} }
+} // namespace factory
+ } // namespace netlist
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 6dad6c5e171..271bf72bf90 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -9,46 +9,58 @@
#ifndef NLFACTORY_H_
#define NLFACTORY_H_
+#include "nltypes.h"
#include "plib/palloc.h"
#include "plib/ptypes.h"
-#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);
+#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) \
- static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
- const pstring &name, const pstring &classname, const pstring &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_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) \
{ \
- return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
+ return plib::make_unique<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(p_name, classname, p_def_param, pstring(__FILE__)); \
} \
- factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
+ \
+ factory::constructor_ptr_t decl_ ## p_alias = NETLIB_NAME(p_alias ## _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 : plib::nocopyassignmove
+ class element_t
{
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();
+ virtual ~element_t() = default;
- virtual plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) = 0;
- virtual void macro_actions(netlist_t &anetlist, const pstring &name) {}
+ 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);
+ }
const pstring &name() const { return m_name; }
const pstring &classname() const { return m_classname; }
@@ -73,26 +85,28 @@ namespace factory {
const pstring &def_param, const pstring &sourcefile)
: element_t(name, classname, def_param, sourcefile) { }
- plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
+ pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override
{
- return plib::owned_ptr<device_t>::Create<C>(anetlist, name);
+ return pool().make_poolptr<C>(anetlist, name);
}
};
- class list_t : public std::vector<std::unique_ptr<element_t>>
+ class list_t : public std::vector<plib::unique_ptr<element_t>>
{
public:
- explicit list_t(setup_t &m_setup);
- ~list_t();
+ explicit list_t(log_type &alog);
+ ~list_t() = default;
+
+ COPYASSIGNMOVE(list_t, delete)
template<class device_class>
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(std::unique_ptr<element_t>(plib::palloc<device_element_t<device_class>>(name, classname, def_param)));
+ register_device(plib::make_unique<device_element_t<device_class>>(name, classname, def_param));
}
- void register_device(std::unique_ptr<element_t> &&factory);
+ void register_device(plib::unique_ptr<element_t> &&factory);
element_t * factory_by_name(const pstring &devname);
@@ -103,21 +117,20 @@ namespace factory {
}
private:
- setup_t &m_setup;
+ log_type &m_log;
};
// -----------------------------------------------------------------------------
// factory_creator_ptr_t
// -----------------------------------------------------------------------------
- using constructor_ptr_t = std::unique_ptr<element_t> (*)(const pstring &name, const pstring &classname,
- const pstring &def_param);
+ using constructor_ptr_t = plib::unique_ptr<element_t> (*)(const pstring &classname);
template <typename T>
- std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
+ plib::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return std::unique_ptr<element_t>(plib::palloc<device_element_t<T>>(name, classname, def_param));
+ return plib::make_unique<device_element_t<T>>(name, classname, def_param);
}
// -----------------------------------------------------------------------------
@@ -128,22 +141,24 @@ namespace factory {
{
public:
- library_element_t(setup_t &setup, const pstring &name, const pstring &classname,
+ library_element_t(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)
+ {
+ }
- plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override;
+ pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override;
- void macro_actions(netlist_t &anetlist, const pstring &name) override;
+ void macro_actions(nlparse_t &nparser, 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 1eae38b25fb..325f8a67c72 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -10,32 +10,24 @@
#ifndef NLLISTS_H_
#define NLLISTS_H_
-#include "nl_config.h"
-#include "netlist_types.h"
-#include "plib/plists.h"
#include "plib/pchrono.h"
+#include "plib/plists.h"
#include "plib/ptypes.h"
+#include "nl_config.h"
+#include "nltypes.h"
+
+#include <algorithm>
#include <atomic>
-#include <thread>
#include <mutex>
-#include <algorithm>
+#include <thread>
#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
@@ -43,10 +35,11 @@ namespace netlist
class pspin_mutex
{
public:
- pspin_mutex() noexcept { }
+ pspin_mutex() noexcept = default;
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;
};
@@ -62,10 +55,11 @@ 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) { }
+ constexpr pqentry_t(const Time t, const Element o) noexcept : m_exec_time(t), m_object(o) { }
+#if 0
~pqentry_t() = default;
constexpr pqentry_t(const pqentry_t &e) noexcept = default;
- constexpr pqentry_t(pqentry_t &&e) = default;
+ constexpr pqentry_t(pqentry_t &&e) noexcept = default;
pqentry_t& operator=(pqentry_t && other) noexcept = default;
pqentry_t& operator=(const pqentry_t &other) noexcept = default;
@@ -74,91 +68,97 @@ namespace netlist
std::swap(m_exec_time, other.m_exec_time);
std::swap(m_object, other.m_object);
}
-
+#endif
struct QueueOp
{
- static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
+ inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time < rhs.m_exec_time);
}
- static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
+ 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
{
return lhs.m_object == rhs.m_object;
}
- static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
+ inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
{
return lhs.m_object == rhs;
}
- static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
+ inline 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, class QueueOp = typename T::QueueOp>
- class timed_queue : plib::nocopyassignmove
+ template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
+ class timed_queue_linear : plib::nocopyassignmove
{
public:
- explicit timed_queue(const std::size_t list_size)
+ explicit timed_queue_linear(const std::size_t list_size)
: m_list(list_size)
{
clear();
}
- constexpr std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
- constexpr bool empty() const noexcept { return (m_end == &m_list[1]); }
+ std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
+ bool empty() const noexcept { return (m_end == &m_list[1]); }
- void push(T &&e) noexcept
+ void push(T && e) noexcept
{
/* Lock */
- tqlock lck(m_lock);
- T * i(m_end);
- for (; QueueOp::less(*(i - 1), e); --i)
+ lock_guard_type lck(m_lock);
+ T * i(m_end-1);
+ for (; QueueOp::less(*(i), e); --i)
{
- *(i) = std::move(*(i-1));
+ *(i+1) = *(i);
m_prof_sortmove.inc();
}
- *i = std::move(e);
+ *(i+1) = std::move(e);
++m_end;
m_prof_call.inc();
}
- void pop() noexcept { --m_end; }
+ T pop() noexcept { return *(--m_end); }
const T &top() const noexcept { return *(m_end-1); }
template <class R>
void remove(const R &elem) noexcept
{
/* Lock */
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
+ m_prof_remove.inc();
+
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem))
{
- --m_end;
- for (;i < m_end; ++i)
- *i = std::move(*(i+1));
+ std::copy(i+1, m_end--, i);
return;
}
}
}
- void retime(const T &elem) noexcept
+ void retime(T && elem) noexcept
{
/* Lock */
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
+ m_prof_retime.inc();
+
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem)) // partial equal!
{
- *i = elem;
+ *i = std::move(elem);
while (QueueOp::less(*(i-1), *i))
{
std::swap(*(i-1), *i);
@@ -174,9 +174,9 @@ namespace netlist
}
}
- void clear()
+ void clear() noexcept
{
- tqlock lck(m_lock);
+ lock_guard_type 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,55 +188,61 @@ namespace netlist
// save state support & mame disasm
- 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]; }
+ 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]; }
private:
- using tqmutex = pspin_mutex<TS>;
- using tqlock = std::lock_guard<tqmutex>;
+ using mutex_type = pspin_mutex<TS>;
+ using lock_guard_type = std::lock_guard<mutex_type>;
- tqmutex m_lock;
- T * m_end;
- std::vector<T> m_list;
+ mutex_type m_lock;
+ PALIGNAS_CACHELINE()
+ T * m_end;
+ //std::vector<T> m_list;
+ plib::aligned_vector<T> m_list;
public:
// profiling
- nperfcount_t m_prof_sortmove;
- nperfcount_t m_prof_call;
+ nperfcount_t<KEEPSTAT> m_prof_sortmove;
+ nperfcount_t<KEEPSTAT> m_prof_call;
+ nperfcount_t<KEEPSTAT> m_prof_remove;
+ nperfcount_t<KEEPSTAT> m_prof_retime;
};
-#else
- template <class T, bool TS, class QueueOp = typename T::QueueOp>
- class timed_queue : plib::nocopyassignmove
+
+ template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
+ class timed_queue_heap : plib::nocopyassignmove
{
public:
struct compare
{
- constexpr bool operator()(const T &a, const T &b) const { return QueueOp::less(b,a); }
+ constexpr bool operator()(const T &a, const T &b) const { return QueueOp::lessequal(b,a); }
};
- explicit timed_queue(const std::size_t list_size)
+ explicit timed_queue_heap(const std::size_t list_size)
: m_list(list_size)
{
clear();
}
- constexpr std::size_t capacity() const noexcept { return m_list.capacity(); }
- constexpr bool empty() const noexcept { return &m_list[0] == m_end; }
+ std::size_t capacity() const noexcept { return m_list.capacity(); }
+ bool empty() const noexcept { return &m_list[0] == m_end; }
void push(T &&e) noexcept
{
/* Lock */
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
*m_end++ = e;
std::push_heap(&m_list[0], m_end, compare());
m_prof_call.inc();
}
- void pop() noexcept
+ T 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]; }
@@ -245,7 +251,7 @@ namespace netlist
void remove(const R &elem) noexcept
{
/* Lock */
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem))
@@ -262,7 +268,7 @@ namespace netlist
void retime(const T &elem) noexcept
{
/* Lock */
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem)) // partial equal!
@@ -276,7 +282,7 @@ namespace netlist
void clear()
{
- tqlock lck(m_lock);
+ lock_guard_type lck(m_lock);
m_list.clear();
m_end = &m_list[0];
}
@@ -287,19 +293,28 @@ 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 tqmutex = pspin_mutex<TS>;
- using tqlock = std::lock_guard<tqmutex>;
+ using mutex_type = pspin_mutex<TS>;
+ using lock_guard_type = std::lock_guard<mutex_type>;
- tqmutex m_lock;
+ mutex_type m_lock;
std::vector<T> m_list;
T *m_end;
public:
// profiling
- nperfcount_t m_prof_sortmove;
- nperfcount_t m_prof_call;
+ nperfcount_t<KEEPSTAT> m_prof_sortmove;
+ nperfcount_t<KEEPSTAT> m_prof_call;
};
-#endif
-}
+
+ /*
+ * 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 /* NLLISTS_H_ */
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index 4685a13c354..cecfbe862bf 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_factory.h"
-#include "nl_errstr.h"
#include "nl_base.h"
+#include "nl_errstr.h"
+#include "nl_factory.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)
{
- 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("/*", "*/", "//");
+ 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("/*", "*/", "//");
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 (pstring tp : paramlist)
+ for (const pstring &tp : paramlist)
{
require_token(m_tok_comma);
- if (tp.startsWith("+"))
+ if (plib::startsWith(tp, "+"))
{
pstring output_name = get_identifier();
m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
@@ -395,18 +395,15 @@ 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 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;
+ 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;
nl_double ret;
- pstring val;
- for (i=1; i<6;i++)
- if (tok.str().equals(macs[i]))
+ for (std::size_t i=1; i<macs.size();i++)
+ if (tok.str() == macs[i])
f = i;
if (f>0)
{
@@ -416,13 +413,13 @@ nl_double parser_t::eval_param(const token_t tok)
}
else
{
- val = tok.str();
- ret = val.as_double(&e);
- if (e)
- error(plib::pfmt("Parameter value <{1}> not double \n")(val));
+ bool err;
+ ret = plib::pstonum_ne<nl_double>(tok.str(), err);
+ if (err)
+ error(plib::pfmt("Parameter value <{1}> not double \n")(tok.str()));
}
return ret * facs[f];
}
-}
+} // namespace netlist
diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h
index a813629faa0..92459c4b87b 100644
--- a/src/lib/netlist/nl_parser.h
+++ b/src/lib/netlist/nl_parser.h
@@ -16,8 +16,12 @@ namespace netlist
class parser_t : public plib::ptokenizer
{
public:
- parser_t(plib::putf8_reader &strm, setup_t &setup)
- : plib::ptokenizer(strm), m_setup(setup) {}
+ template <typename T>
+ parser_t(T &&strm, nlparse_t &setup)
+ : plib::ptokenizer(std::forward<T>(strm))
+ , m_setup(setup)
+ {
+ }
bool parse(const pstring &nlname = "");
@@ -39,12 +43,12 @@ namespace netlist
void net_truthtable_start(const pstring &nlname);
/* for debugging messages */
- netlist_t &netlist() { return m_setup.netlist(); }
+ //netlist_state_t &netlist() { return m_setup.netlist(); }
- virtual void verror(const pstring &msg, int line_num, const pstring &line) override;
+ 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;
@@ -68,9 +72,9 @@ namespace netlist
token_id_t m_tok_TT_LINE;
token_id_t m_tok_TT_FAMILY;
- setup_t &m_setup;
+ nlparse_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 df761bc3f88..b9300f5ad9c 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -6,128 +6,243 @@
*/
#include "plib/palloc.h"
-#include "plib/putil.h"
+#include "analog/nld_twoterm.h"
+#include "devices/nlid_proxy.h"
+#include "devices/nlid_system.h"
+#include "devices/nlid_truthtable.h"
#include "nl_base.h"
-#include "nl_setup.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 "nl_parser.h"
+#include "nl_setup.h"
+#include "plib/putil.h"
#include "solver/nld_solver.h"
-#include "devices/nlid_truthtable.h"
-// ----------------------------------------------------------------------------------------
-// setup_t
-// ----------------------------------------------------------------------------------------
+#include <cmath>
namespace netlist
{
-setup_t::setup_t(netlist_t &netlist)
- : m_netlist(netlist)
- , m_factory(*this)
- , m_proxy_cnt(0)
+ // ----------------------------------------------------------------------------------------
+ // nl_parse_t
+ // ----------------------------------------------------------------------------------------
+
+ nlparse_t::nlparse_t(setup_t &setup, log_type &log)
+ : m_factory(log)
+ , m_setup(setup)
+ , m_log(log)
, m_frontier_cnt(0)
-{
- devices::initialize_factory(m_factory);
-}
+ { }
-setup_t::~setup_t()
-{
- m_links.clear();
- m_alias.clear();
- m_params.clear();
- m_terminals.clear();
- m_param_values.clear();
+ 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);
+ }
- m_sources.clear();
-}
+ 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]);
+ }
+ }
-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;
-}
+ 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 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_link(const pstring &sin, const pstring &sout)
+ {
+ register_link_fqn(build_fqn(sin), build_fqn(sout));
+ }
-void setup_t::namespace_pop()
-{
- m_namespace_stack.pop();
-}
+ 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 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));
-}
+ 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 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 setup_t::device_exists(const pstring &name) const
-{
- for (auto e : m_device_factory)
+ void nlparse_t::namespace_push(const pstring &aname)
{
- if (e.first == name)
- return true;
+ 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);
}
- return false;
-}
+ void nlparse_t::namespace_pop()
+ {
+ m_namespace_stack.pop();
+ }
-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 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 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);
-}
+ 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;
+ }
+ }
+
+ 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));
+ }
+
+ 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");
+ }
+
+ 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 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 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 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_alias(const pstring &alias, const pstring &out)
+ bool nlparse_t::device_exists(const pstring &name) const
+ {
+ for (auto &d : m_device_factory)
+ if (d.first == name)
+ return true;
+ return false;
+ }
+
+ bool nlparse_t::parse_stream(plib::unique_ptr<plib::pistream> &&istrm, const pstring &name)
+ {
+ return parser_t(std::move(plib::ppreprocessor(&m_defines).process(std::move(istrm))), *this).parse(name);
+ }
+
+ 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
+ // ----------------------------------------------------------------------------------------
+
+
+setup_t::setup_t(netlist_state_t &nlstate)
+ : nlparse_t(*this, nlstate.log())
+ , m_nlstate(nlstate)
+ , m_netlist_params(nullptr)
+ , m_proxy_cnt(0)
{
- pstring alias_fqn = build_fqn(alias);
- pstring out_fqn = build_fqn(out);
- register_alias_nofqn(alias_fqn, out_fqn);
}
-void setup_t::register_dippins_arr(const pstring &terms)
+setup_t::~setup_t() noexcept
{
- 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]);
- }
+ // FIXME: can't see a need any longer
+ m_links.clear();
+ m_params.clear();
+ m_terminals.clear();
+ m_param_values.clear();
+ m_sources.clear();
}
pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
@@ -145,7 +260,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)
+pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def) const
{
auto i = m_param_values.find(name);
if (i != m_param_values.end())
@@ -154,40 +269,6 @@ 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)
@@ -196,30 +277,6 @@ 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);
@@ -241,59 +298,14 @@ 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(const pstring &param, const double value)
+void setup_t::register_param_t(const pstring &name, param_t &param)
{
- register_param(param, plib::pfmt("{1:.9}").e(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);
}
-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
{
@@ -311,6 +323,42 @@ 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);
@@ -377,7 +425,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
{
nl_assert(out.is_logic());
- logic_output_t &out_cast = static_cast<logic_output_t &>(out);
+ auto &out_cast = static_cast<logic_output_t &>(out);
devices::nld_base_proxy *proxy = out_cast.get_proxy();
if (proxy == nullptr)
@@ -385,28 +433,25 @@ 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(netlist(), x, &out_cast);
+ out_cast.logic_family()->create_d_a_proxy(m_nlstate, x, &out_cast);
m_proxy_cnt++;
-
- //new_proxy->start_dev();
-
/* connect all existing terminals to new net */
- for (auto & p : out.net().m_core_terms)
+ for (auto & p : out.net().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().m_core_terms.clear(); // clear the list
+ out.net().core_terms().clear(); // clear the list
out.net().add_terminal(new_proxy->in());
out_cast.set_proxy(proxy);
proxy = new_proxy.get();
- netlist().register_dev(std::move(new_proxy));
+ m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
}
return proxy;
}
@@ -415,7 +460,7 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
nl_assert(inp.is_logic());
- logic_input_t &incast = dynamic_cast<logic_input_t &>(inp);
+ auto &incast = dynamic_cast<logic_input_t &>(inp);
devices::nld_base_proxy *proxy = incast.get_proxy();
if (proxy != nullptr)
@@ -424,7 +469,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(netlist(), x, &incast);
+ auto new_proxy = incast.logic_family()->create_a_d_proxy(m_nlstate, 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++;
@@ -435,17 +480,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().m_core_terms)
+ for (auto & p : inp.net().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().m_core_terms.clear(); // clear the list
+ inp.net().core_terms().clear(); // clear the list
}
ret->out().net().add_terminal(inp);
- netlist().register_dev(std::move(new_proxy));
+ m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
return ret;
}
}
@@ -568,11 +613,12 @@ 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 = 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);
+ 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);
}
}
@@ -580,7 +626,7 @@ static detail::core_terminal_t &resolve_proxy(detail::core_terminal_t &term)
{
if (term.is_logic())
{
- logic_t &out = dynamic_cast<logic_t &>(term);
+ auto &out = dynamic_cast<logic_t &>(term);
if (out.has_proxy())
return out.get_proxy()->proxy_term();
}
@@ -596,7 +642,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().m_core_terms)
+ for (auto & t : t1.net().core_terms())
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t2, *t);
@@ -611,7 +657,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().m_core_terms)
+ for (auto & t : t2.net().core_terms())
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t1, *t);
@@ -623,8 +669,6 @@ 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());
@@ -712,18 +756,7 @@ void setup_t::resolve_inputs()
// 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());
+ delete_empty_nets();
pstring errstr("");
@@ -744,7 +777,7 @@ void setup_t::resolve_inputs()
}
-void setup_t::start_devices()
+void setup_t::register_dynamic_log_devices()
{
pstring env = plib::util::environment("NL_LOGS", "");
@@ -752,41 +785,43 @@ void setup_t::start_devices()
{
log().debug("Creating dynamic logs ...");
std::vector<pstring> loglist(plib::psplit(env, ":"));
- for (pstring ll : loglist)
+ for (const pstring &ll : loglist)
{
pstring name = "log_" + ll;
- auto nc = factory().factory_by_name("LOG")->Create(netlist(), name);
+ auto nc = factory().factory_by_name("LOG")->Create(m_nlstate, name);
register_link(name + ".I", ll);
log().debug(" dynamic link {1}: <{2}>\n",ll, name);
- netlist().register_dev(std::move(nc));
+ m_nlstate.add_dev(nc->name(), std::move(nc));
}
}
}
-plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log()
+log_type &setup_t::log()
{
- return netlist().log();
+ return m_nlstate.log();
}
-const plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log() const
+const log_type &setup_t::log() const
{
- return netlist().log();
+ return m_nlstate.log();
}
// ----------------------------------------------------------------------------------------
-// Model
+// Models
// ----------------------------------------------------------------------------------------
-static pstring model_string(detail::model_map_t &map)
+void models_t::register_model(pstring model_in)
{
- pstring ret = map["COREMODEL"] + "(";
- for (auto & i : map)
- ret = ret + i.first + "=" + i.second + " ";
-
- return ret + ")";
+ 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);
}
-void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
+void models_t::model_parse(const pstring &model_in, model_map_t &map)
{
pstring model = model_in;
std::size_t pos = 0;
@@ -797,15 +832,15 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
pos = model.find("(");
if (pos != pstring::npos) break;
- key = model.ucase();
+ key = plib::ucase(model);
auto i = m_models.find(key);
if (i == m_models.end())
- log().fatal(MF_1_MODEL_NOT_FOUND, model);
+ throw nl_exception(MF_1_MODEL_NOT_FOUND, model);
model = i->second;
}
- pstring xmodel = model.left(pos);
+ pstring xmodel = plib::left(model, pos);
- if (xmodel.equals("_"))
+ if (xmodel == "_")
map["COREMODEL"] = key;
else
{
@@ -813,46 +848,65 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
if (i != m_models.end())
model_parse(xmodel, map);
else
- log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
+ throw nl_exception(MF_1_MODEL_NOT_FOUND, model_in);
}
- pstring remainder = model.substr(pos + 1).trim();
- if (!remainder.endsWith(")"))
- log().fatal(MF_1_MODEL_ERROR_1, model);
+ pstring remainder = plib::trim(model.substr(pos + 1));
+ if (!plib::endsWith(remainder, ")"))
+ throw nl_exception(MF_1_MODEL_ERROR_1, model);
// FIMXE: Not optimal
- remainder = remainder.left(remainder.length() - 1);
+ remainder = plib::left(remainder, remainder.size() - 1);
std::vector<pstring> pairs(plib::psplit(remainder," ", true));
for (pstring &pe : pairs)
{
auto pose = pe.find("=");
if (pose == pstring::npos)
- log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
- map[pe.left(pose).ucase()] = pe.substr(pose + 1);
+ throw nl_exception(MF_1_MODEL_ERROR_ON_PAIR_1, model);
+ map[plib::ucase(plib::left(pe, pose))] = pe.substr(pose + 1);
}
}
-const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
+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)
{
+ model_map_t &map = m_cache[model];
+
+ if (map.size() == 0)
+ model_parse(model , map);
+
pstring ret;
- if (entity != entity.ucase())
- log().fatal(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
+ if (entity != plib::ucase(entity))
+ throw nl_exception(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
model_string(map));
if (map.find(entity) == map.end())
- log().fatal(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
+ throw nl_exception(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
else
ret = map[entity];
return ret;
}
-nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
+nl_double models_t::model_value(pstring model, pstring entity)
{
- pstring tmp = model_value_str(map, entity);
+ model_map_t &map = m_cache[model];
+
+ if (map.size() == 0)
+ model_parse(model , map);
- nl_double factor = NL_FCONST(1.0);
- auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.length() - 1));
+ 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));
switch (*p)
{
case 'M': factor = 1e6; break;
@@ -865,85 +919,69 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
case 'a': factor = 1e-18; break;
default:
if (*p < '0' || *p > '9')
- log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
+ throw nl_exception(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
}
- if (factor != NL_FCONST(1.0))
- tmp = tmp.left(tmp.length() - 1);
- return tmp.as_double() * factor;
+ 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;
}
class logic_family_std_proxy_t : public logic_family_desc_t
{
public:
- logic_family_std_proxy_t() { }
- virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
+ logic_family_std_proxy_t() = default;
+ 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;
- 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_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
};
-plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
+pool_owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_state_t &anetlist,
const pstring &name, logic_output_t *proxied) const
{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-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
+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
{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<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 (model_value_str(map, "TYPE") == "TTL")
+ if (m_models.model_value_str(model, "TYPE") == "TTL")
return family_TTL();
- if (model_value_str(map, "TYPE") == "CD4XXX")
+ if (m_models.model_value_str(model, "TYPE") == "CD4XXX")
return family_CD4XXX();
- for (auto & e : netlist().m_family_cache)
+ for (auto & e : m_nlstate.m_family_cache)
if (e.first == model)
return e.second.get();
- auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
+ auto ret = plib::make_unique<logic_family_std_proxy_t>();
- 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");
+ 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");
auto retp = ret.get();
- netlist().m_family_cache.emplace_back(model, std::move(ret));
+ m_nlstate.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
// ----------------------------------------------------------------------------------------
-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)
+plib::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
{
for (auto &source : m_sources)
{
@@ -955,77 +993,189 @@ std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
}
}
log().warning(MW_1_DATA_1_NOT_FOUND, name);
- return std::unique_ptr<plib::pistream>(nullptr);
+ return plib::unique_ptr<plib::pistream>(nullptr);
}
-bool setup_t::parse_stream(plib::putf8_reader &istrm, const pstring &name)
-{
- plib::pomemstream ostrm;
- plib::putf8_writer owrt(ostrm);
+// ----------------------------------------------------------------------------------------
+// Device handling
+// ----------------------------------------------------------------------------------------
- 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::delete_empty_nets()
+{
+ 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());
}
-void setup_t::register_define(pstring defstr)
+// ----------------------------------------------------------------------------------------
+// Run preparation
+// ----------------------------------------------------------------------------------------
+
+void setup_t::prepare_to_run()
{
- auto p = defstr.find("=");
- if (p != pstring::npos)
- register_define(defstr.left(p), defstr.substr(p+1));
+ 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);
+ }
else
- register_define(defstr, "1");
+ 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);
+ }
+
}
// ----------------------------------------------------------------------------------------
// base sources
// ----------------------------------------------------------------------------------------
-bool source_t::parse(const pstring &name)
+bool source_t::parse(nlparse_t &setup, const pstring &name)
{
if (m_type != SOURCE)
return false;
else
{
- auto rstream = stream(name);
- plib::putf8_reader reader(*rstream);
- return m_setup.parse_stream(reader, name);
+ return setup.parse_stream(stream(name), name);
}
}
-std::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
+ plib::unused_var(name);
+ return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
}
-std::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
+ plib::unused_var(name);
+ return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
}
-std::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pifilestream>(m_filename);
+ plib::unused_var(name);
+ return plib::make_unique<plib::pifilestream>(m_filename);
}
-bool source_proc_t::parse(const pstring &name)
+bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
{
if (name == m_setup_func_name)
{
- m_setup_func(setup());
+ m_setup_func(setup);
return true;
}
else
return false;
}
-std::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
{
- std::unique_ptr<plib::pistream> p(nullptr);
+ plib::unused_var(name);
+ plib::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 d0359928711..ed0248a48e6 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -8,18 +8,20 @@
#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_factory.h"
#include "nl_config.h"
-#include "netlist_types.h"
+#include "nl_factory.h"
+#include "nltypes.h"
+#include <memory>
#include <stack>
+#include <unordered_map>
#include <vector>
-#include <memory>
+
//============================================================
// MACROS / inline netlist definitions
@@ -27,46 +29,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::setup_t &setup);
+ void NETLIST_NAME(name)(netlist::nlparse_t &setup);
#define NETLIST_START(name) \
-void NETLIST_NAME(name)(netlist::setup_t &setup) \
+void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
{
#define NETLIST_END() }
#define LOCAL_SOURCE(name) \
- setup.register_source(plib::make_unique_base<netlist::source_t, netlist::source_proc_t>(setup, # name, &NETLIST_NAME(name)));
+ setup.register_source(plib::make_unique<netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
#define LOCAL_LIB_ENTRY(name) \
LOCAL_SOURCE(name) \
@@ -80,7 +82,7 @@ void NETLIST_NAME(name)(netlist::setup_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);
// -----------------------------------------------------------------------------
@@ -98,10 +100,10 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
desc.family = "";
#define TT_HEAD(x) \
- desc.desc.push_back(x);
+ desc.desc.emplace_back(x);
#define TT_LINE(x) \
- desc.desc.push_back(x);
+ desc.desc.emplace_back(x);
#define TT_FAMILY(x) \
desc.family = x;
@@ -110,22 +112,23 @@ void NETLIST_NAME(name)(netlist::setup_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;
@@ -136,6 +139,7 @@ namespace netlist
struct tt_desc
{
+ tt_desc() : ni(0), no(0) { }
pstring name;
pstring classname;
unsigned long ni;
@@ -168,138 +172,222 @@ namespace netlist
class source_t
{
public:
+
+ friend class setup_t;
+
enum type_t
{
SOURCE,
DATA
};
- using list_t = std::vector<std::unique_ptr<source_t>>;
+ using list_t = std::vector<plib::unique_ptr<source_t>>;
- source_t(setup_t &setup, const type_t type = SOURCE)
- : m_setup(setup), m_type(type)
+ source_t(const type_t type = SOURCE)
+ : m_type(type)
{}
- virtual ~source_t() { }
+ COPYASSIGNMOVE(source_t, delete)
- virtual bool parse(const pstring &name);
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) = 0;
+ virtual ~source_t() noexcept = default;
+
+ virtual bool parse(nlparse_t &setup, const pstring &name);
- 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;
};
+
// ----------------------------------------------------------------------------------------
- // setup_t
+ // Collection of models
// ----------------------------------------------------------------------------------------
-
- class setup_t : plib::nocopyassignmove
+ class models_t
{
public:
+ void register_model(pstring model_in);
+ /* model / family related */
- using link_t = std::pair<pstring, pstring>;
+ pstring model_value_str(pstring model, pstring entity);
- explicit setup_t(netlist_t &netlist);
- ~setup_t();
+ double model_value(pstring model, pstring entity);
- netlist_t &netlist() { return m_netlist; }
- const netlist_t &netlist() const { return m_netlist; }
+ pstring model_type(pstring model) { return model_value_str(model, "COREMODEL"); }
- pstring build_fqn(const pstring &obj_name) const;
+ private:
+ using model_map_t = std::unordered_map<pstring, pstring>;
- 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);
+ void model_parse(const pstring &model, model_map_t &map);
+ pstring model_string(model_map_t &map);
- void register_term(detail::core_terminal_t &obj);
+ std::unordered_map<pstring, pstring> m_models;
+ std::unordered_map<pstring, model_map_t> m_cache;
+ };
- void register_dev(const pstring &classname, const pstring &name);
+ // ----------------------------------------------------------------------------------------
+ // nlparse_t
+ // ----------------------------------------------------------------------------------------
- void register_lib_entry(const pstring &name, const pstring &sourcefile);
+ class nlparse_t
+ {
+ public:
+ using link_t = std::pair<pstring, pstring>;
+
+ nlparse_t(setup_t &netlist, log_type &log);
- void register_model(const pstring &model_in);
+ void register_model(const pstring &model_in) { m_models.register_model(model_in); }
void register_alias(const pstring &alias, const pstring &out);
void register_dippins_arr(const pstring &terms);
-
- 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_dev(const pstring &classname, const pstring &name);
void register_link(const pstring &sin, const pstring &sout);
-
+ void register_link_arr(const pstring &terms);
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);
- void remove_connections(const pstring &attach);
-
- 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;
+ /* register a source */
+ void register_source(plib::unique_ptr<source_t> &&src)
+ {
+ m_sources.push_back(std::move(src));
+ }
- void start_devices();
- void resolve_inputs();
+ void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
/* handle namespace */
void namespace_push(const pstring &aname);
void namespace_pop();
- /* parse a source */
+ /* include other files */
void include(const pstring &netlist_name);
- std::unique_ptr<plib::pistream> get_data_stream(const pstring &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);
- bool parse_stream(plib::putf8_reader &istrm, const pstring &name);
+ /* used from netlist.cpp (mame) */
+ bool device_exists(const pstring &name) const;
- /* register a source */
+ /* FIXME: used by source_t - need a different approach at some time */
+ bool parse_stream(plib::unique_ptr<plib::pistream> &&istrm, const pstring &name);
- void register_source(std::unique_ptr<source_t> &&src)
+ void add_define(const pstring &def, const pstring &val)
{
- m_sources.push_back(std::move(src));
+ m_defines.insert({ def, plib::ppreprocessor::define_t(def, val)});
}
- void register_define(pstring def, pstring val) { m_defines.push_back(plib::ppreprocessor::define_t(def, val)); }
- void register_define(pstring defstr);
+ void add_define(const pstring &defstr);
factory::list_t &factory() { return m_factory; }
const factory::list_t &factory() const { return m_factory; }
- /* model / family related */
+ 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);
- const pstring model_value_str(detail::model_map_t &map, const pstring &entity);
- double model_value(detail::model_map_t &map, const pstring &entity);
+ bool connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
- void model_parse(const pstring &model, detail::model_map_t &map);
+ param_t *find_param(const pstring &param_in, bool required = true) const;
+ /* get family */
const logic_family_desc_t *family_from_model(const pstring &model);
- void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
+ 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; }
/* helper - also used by nltool */
const pstring resolve_alias(const pstring &name) const;
- 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;
+ /* needed by nltool */
+ std::vector<pstring> get_terminals_for_device_name(const pstring &devname);
- 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;
+ log_type &log();
+ const log_type &log() const;
/* 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);
@@ -318,35 +406,30 @@ 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);
- 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::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
- std::stack<pstring> m_namespace_stack;
- source_t::list_t m_sources;
- std::vector<plib::ppreprocessor::define_t> m_defines;
+ netlist_state_t &m_nlstate;
+ devices::nld_netlistparams *m_netlist_params;
+ std::unordered_map<pstring, param_ref_t> m_params;
unsigned m_proxy_cnt;
- unsigned m_frontier_cnt;
-};
+ };
// ----------------------------------------------------------------------------------------
// base sources
// ----------------------------------------------------------------------------------------
-
class source_string_t : public source_t
{
public:
- source_string_t(setup_t &setup, const pstring &source)
- : source_t(setup), m_str(source)
+ source_string_t(const pstring &source)
+ : source_t(), m_str(source)
{
}
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ protected:
+ plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_str;
@@ -356,12 +439,13 @@ namespace netlist
{
public:
- source_file_t(setup_t &setup, const pstring &filename)
- : source_t(setup), m_filename(filename)
+ source_file_t(const pstring &filename)
+ : source_t(), m_filename(filename)
{
}
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ protected:
+ plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_filename;
@@ -370,12 +454,13 @@ namespace netlist
class source_mem_t : public source_t
{
public:
- source_mem_t(setup_t &setup, const char *mem)
- : source_t(setup), m_str(mem, pstring::UTF8)
+ source_mem_t(const char *mem)
+ : source_t(), m_str(mem)
{
}
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ protected:
+ plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_str;
@@ -384,22 +469,28 @@ namespace netlist
class source_proc_t : public source_t
{
public:
- source_proc_t(setup_t &setup, pstring name, void (*setup_func)(setup_t &))
- : source_t(setup),
+ source_proc_t(const pstring &name, void (*setup_func)(nlparse_t &))
+ : source_t(),
m_setup_func(setup_func),
m_setup_func_name(name)
{
}
- virtual bool parse(const pstring &name) override;
- virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
+ bool parse(nlparse_t &setup, const pstring &name) override;
+
+ protected:
+ plib::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
- void (*m_setup_func)(setup_t &);
+ void (*m_setup_func)(nlparse_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
deleted file mode 100644
index 7c81f890e07..00000000000
--- a/src/lib/netlist/nl_time.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// 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
new file mode 100644
index 00000000000..7d7582774b1
--- /dev/null
+++ b/src/lib/netlist/nltypes.h
@@ -0,0 +1,147 @@
+// 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
new file mode 100644
index 00000000000..2c357e97624
--- /dev/null
+++ b/src/lib/netlist/plib/gmres.h
@@ -0,0 +1,450 @@
+// 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
new file mode 100644
index 00000000000..4cc027f0d8f
--- /dev/null
+++ b/src/lib/netlist/plib/mat_cr.h
@@ -0,0 +1,530 @@
+// 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
deleted file mode 100644
index e4d31985b23..00000000000
--- a/src/lib/netlist/plib/palloc.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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 a35bc50ff17..15fede3a99b 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -8,172 +8,427 @@
#ifndef PALLOC_H_
#define PALLOC_H_
+#include "pconfig.h"
#include "pstring.h"
+#include "ptypes.h"
-#include <vector>
+#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
namespace plib {
-//============================================================
-// 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)
+ //============================================================
+ // 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
{
- 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;
+ 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);
}
- owned_ptr(owned_ptr &&r) noexcept
+ //============================================================
+ // Memory allocation
+ //============================================================
+
+ struct aligned_arena
{
- m_is_owned = r.m_is_owned;
- m_ptr = r.m_ptr;
- r.m_is_owned = false;
- r.m_ptr = nullptr;
+ 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
}
- template<typename DC>
- owned_ptr(owned_ptr<DC> &&r) noexcept
+ template <typename T, std::size_t ALIGN>
+ constexpr const T *assume_aligned_ptr(const T *p) noexcept
{
- m_ptr = static_cast<SC *>(r.get());
- m_is_owned = r.is_owned();
- r.release();
+ 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
}
- ~owned_ptr()
+ // FIXME: remove
+ template<typename T, typename... Args>
+ inline T *pnew(Args&&... args)
{
- if (m_is_owned && (m_ptr != nullptr))
- delete m_ptr;
- m_is_owned = false;
- m_ptr = nullptr;
+ auto *p = aligned_arena::allocate(alignof(T), sizeof(T));
+ return new(p) T(std::forward<Args>(args)...);
}
- template<typename DC, typename... Args>
- static owned_ptr Create(Args&&... args)
+
+ template<typename T>
+ inline void pdelete(T *ptr)
{
- owned_ptr a;
- DC *x = new DC(std::forward<Args>(args)...);
- a.m_ptr = static_cast<SC *>(x);
- return std::move(a);
+ ptr->~T();
+ aligned_arena::deallocate(ptr);
}
- template<typename... Args>
- static owned_ptr Create(Args&&... args)
+
+ 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)
{
- owned_ptr a;
- a.m_ptr = new SC(std::forward<Args>(args)...);
- return std::move(a);
+ return plib::unique_ptr<T>(pnew<T>(std::forward<Args>(args)...));
}
- SC * release()
+
+#if 0
+ template<typename T, typename... Args>
+ static owned_ptr<T> make_owned(Args&&... args)
{
- SC *tmp = m_ptr;
- m_is_owned = false;
- m_ptr = nullptr;
- return tmp;
+ return owned_ptr<T>(pnew<T>(std::forward<Args>(args)...), true);
}
+#endif
+
- bool is_owned() const { return m_is_owned; }
+ template <class T, std::size_t ALIGN = alignof(T)>
+ using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>;
- 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;
-};
+ //============================================================
+ // traits to determine alignment size and stride size
+ // from types supporting alignment
+ //============================================================
-class mempool
-{
-private:
- struct block
+ PDEFINE_HAS_MEMBER(has_align, align_size);
+
+ template <typename T, typename X = void>
+ struct align_traits
{
- 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;
+ 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;
};
- size_t new_block();
- size_t mininfosize();
-
- struct info
+ template <typename T>
+ struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type>
{
- info() : m_block(0) { }
- size_t m_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;
};
- size_t m_min_alloc;
- size_t m_min_align;
+ //============================================================
+ // Aligned vector
+ //============================================================
- std::vector<block> m_blocks;
+ // 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>>
+ {
+ public:
+ using base = std::vector<T, aligned_allocator<T, ALIGN>>;
+
+ 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;
-public:
- mempool(size_t min_alloc, size_t min_align);
- ~mempool();
+ using base::base;
- void *alloc(size_t size);
- void free(void *ptr);
+ 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];
+ }
-};
+ pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
+ const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
+
+ };
-}
+} // namespace plib
#endif /* PALLOC_H_ */
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h
new file mode 100644
index 00000000000..1be37b908cd
--- /dev/null
+++ b/src/lib/netlist/plib/parray.h
@@ -0,0 +1,126 @@
+// 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 971d19b3645..953d948e062 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 a229128e7b8..8ce0eca23b3 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -9,16 +9,17 @@
#define PCHRONO_H_
#include "pconfig.h"
+#include "ptypes.h"
-#include <cstdint>
#include <chrono>
+#include <cstdint>
namespace plib {
namespace chrono {
template <typename T>
struct sys_ticks
{
- typedef typename T::rep type;
+ using type = typename T::rep;
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; }
@@ -145,7 +146,7 @@ namespace chrono {
struct counter
{
counter() : m_count(0) { }
- typedef uint_least64_t type;
+ using type = uint_least64_t;
type operator()() const { return m_count; }
void inc() { ++m_count; }
void reset() { m_count = 0; }
@@ -157,7 +158,7 @@ namespace chrono {
template<>
struct counter<false>
{
- typedef uint_least64_t type;
+ using type = uint_least64_t;
constexpr type operator()() const { return 0; }
void inc() const { }
void reset() const { }
@@ -168,15 +169,28 @@ namespace chrono {
template< typename T, bool enabled_ = true>
struct timer
{
- typedef typename T::type type;
- typedef uint_least64_t ctype;
+ 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;
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; }
@@ -185,7 +199,7 @@ namespace chrono {
double as_seconds() const { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
- constexpr static bool enabled = enabled_;
+ guard_t guard() { return guard_t(*this); }
private:
type m_time;
ctype m_count;
@@ -194,19 +208,31 @@ namespace chrono {
template<typename T>
struct timer<T, false>
{
- typedef typename T::type type;
- typedef uint_least64_t ctype;
+ 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() { }
+ };
+
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 0200c305ecd..d66b342f815 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -21,18 +21,46 @@
* if PHAS_RDTSCP == 1
*/
#ifndef PUSE_ACCURATE_STATS
-#define PUSE_ACCURATE_STATS (1)
+#define PUSE_ACCURATE_STATS (0)
#endif
/*
* Set this to one if you want to use 128 bit int for ptime.
- * This is for tests only.
+ * This is about 5% slower on a kaby lake processor.
*/
#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
*
@@ -47,6 +75,13 @@
*
*============================================================*/
+#ifndef NVCCBUILD
+#define NVCCBUILD (0)
+#endif
+
+#if NVCCBUILD
+#define C14CONSTEXPR
+#else
#if __cplusplus == 201103L
#define C14CONSTEXPR
#elif __cplusplus == 201402L
@@ -58,6 +93,7 @@
#else
#error "C++ version not supported"
#endif
+#endif
#ifndef PHAS_INT128
#define PHAS_INT128 (0)
@@ -68,17 +104,6 @@ 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 13827eaf24c..0d32bead51d 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 = palloc_array<CHAR>(char_count);
+ result = new 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 = palloc_array<WCHAR>(char_count);
+ result = new 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());
- pfree_array(buffer);
+ delete [] buffer;
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -88,9 +88,11 @@ 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());
@@ -104,7 +106,7 @@ dynlib::dynlib(const pstring path, const pstring libname)
{
//printf("win: library <%s> not found!\n", libname.c_str());
}
- pfree_array(buffer);
+ delete [] buffer;
#elif defined(EMSCRIPTEN)
//no-op
#else
@@ -139,7 +141,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());
@@ -148,4 +150,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 7c9412593c9..1454c053298 100644
--- a/src/lib/netlist/plib/pdynlib.h
+++ b/src/lib/netlist/plib/pdynlib.h
@@ -8,28 +8,31 @@
#define PDYNLIB_H_
#include "pstring.h"
+#include "ptypes.h"
namespace plib {
// ----------------------------------------------------------------------------------------
// pdynlib: dynamic loading of libraries ...
// ----------------------------------------------------------------------------------------
-class dynlib
+class dynlib : public nocopyassignmove
{
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;
@@ -64,6 +67,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 a4ed8f367e0..8d6907d66f2 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -9,6 +9,7 @@
#include "pfmtlog.h"
#include <cfenv>
+#include <iostream>
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
#define HAS_FEENABLE_EXCEPT (1)
@@ -17,127 +18,113 @@
#endif
namespace plib {
-//============================================================
-// 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)
+
+ //============================================================
+ // terminate
+ //============================================================
+
+ void terminate(const pstring &msg) noexcept
{
- 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);
+ std::cerr << msg.c_str() << "\n";
+ std::terminate();
}
-#else
- m_last_enabled = 0;
-#endif
-}
-fpsignalenabler::~fpsignalenabler()
-{
-#if HAS_FEENABLE_EXCEPT
- if (m_enable)
+ //============================================================
+ // 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)
{
- 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::global_enable(bool enable)
-{
- bool old = m_enable;
- m_enable = enable;
- return old;
-}
+ file_write_e::file_write_e(const pstring &filename)
+ : file_e("File write failed: {}", filename)
+ {
+ }
+
+
+ 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()
+ {
+ #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
+ }
+
+ bool fpsignalenabler::supported()
+ {
+ return true;
+ }
+
+ 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 4827081b754..28a3ac1adf1 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -9,118 +9,116 @@
#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 b8b5fcb3b91..af87251fbdf 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -8,83 +8,96 @@
#include "pfmtlog.h"
#include "palloc.h"
-#include <cstring>
-#include <cstdlib>
-#include <cstdarg>
#include <algorithm>
-#include <locale>
+#include <array>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <iostream>
+#include <locale>
namespace plib {
pfmt &pfmt::format_element(const char *l, const unsigned cfmt_spec, ...)
{
va_list ap;
- va_start(ap, cfmt_spec);
- pstring fmt("%");
- char buf[2048]; // FIXME
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
+ std::array<char, 2048> buf;
std::size_t sl;
+ bool found_abs = false;
m_arg++;
- pstring search("{");
- search += plib::to_string(m_arg);
- sl = search.length();
+ 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();
- 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
- {
- sl = 2;
- p = m_str.find("{}");
- }
- if (p == pstring::npos)
+ auto p = m_str.find(search + ":");
+ sl++; // ":"
+ if (p == pstring::npos) // no further specifiers
{
- sl=1;
- p = m_str.find("{");
- if (p != pstring:: npos)
+ p = m_str.find(search + "}");
+ if (p == pstring::npos) // not found try default
{
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
+ 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)
{
- sl = p1 - p + 1;
- fmt += m_str.substr(p+1, p1 - p - 1);
+ auto p1 = m_str.find("}", p);
+ if (p1 != pstring::npos)
+ {
+ sl = p1 - p + 1;
+ fmt += m_str.substr(p+1, p1 - p - 1);
+ }
}
}
}
- }
- else
- {
- auto p1 = m_str.find("}", p);
- if (p1 != pstring::npos)
+ else
+ {
+ // found absolute positional place holder
+ auto p1 = m_str.find("}", p);
+ if (p1 != 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;
+ }
+ }
+ pstring::value_type pend = fmt.at(fmt.size() - 1);
+ if (pstring("duxo").find(cfmt_spec) != 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));
+ 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;
}
- }
- 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;
- }
- 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);
+ 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);
return *this;
}
-}
+} // namespace plib
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index 9b7a85d8d8d..cb9b59c01ce 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -9,6 +9,7 @@
#include "pstring.h"
#include "ptypes.h"
+#include "putil.h"
#include <limits>
@@ -34,7 +35,6 @@ 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,7 +136,6 @@ struct ptype_traits<double> : ptype_traits_base<double>
static char32_t fmt_spec() { return 'f'; }
};
-
template<>
struct ptype_traits<char *> : ptype_traits_base<char *>
{
@@ -144,6 +143,13 @@ 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:
@@ -151,44 +157,57 @@ public:
: m_str(fmt), m_arg(0)
{
}
+ COPYASSIGNMOVE(pfmt, default)
- pfmt(const pfmt &rhs) : m_str(rhs.m_str), m_arg(rhs.m_arg) { }
-
- ~pfmt()
- {
- }
+ ~pfmt() noexcept = default;
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);
}
@@ -203,11 +222,13 @@ private:
};
template <class T, bool build_enabled = true>
-class pfmt_writer_t : plib::nocopyassignmove
+class pfmt_writer_t
{
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
@@ -237,7 +258,7 @@ public:
bool is_enabled() const { return m_enabled; }
protected:
- ~pfmt_writer_t() { }
+ ~pfmt_writer_t() noexcept = default;
private:
pfmt &xlog(pfmt &fmt) const { return fmt; }
@@ -258,7 +279,10 @@ 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) { }
- ~plog_channel() { }
+
+ COPYASSIGNMOVE(plog_channel, delete)
+
+ ~plog_channel() noexcept = default;
protected:
void vdowrite(const pstring &ls) const
@@ -283,7 +307,9 @@ public:
error(proxy),
fatal(proxy)
{}
- virtual ~plog_base() {}
+
+ COPYASSIGNMOVE(plog_base, default)
+ virtual ~plog_base() noexcept = default;
plog_channel<T, plog_level::DEBUG, debug_enabled> debug;
plog_channel<T, plog_level::INFO> info;
@@ -293,7 +319,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 79f09cb4a46..6a2179e0e6f 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 (expr.startsWith("rpn:"))
+ if (plib::startsWith(expr, "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 (unsigned i = 0; i < inputs.size(); i++)
+ for (std::size_t 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;
- rc.m_param = cmd.as_double(&err);
+ bool err;
+ rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, 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(pstring v)
+static int get_prio(const pstring &v)
{
if (v == "(" || v == ")")
return 1;
- else if (v.left(1) >= "a" && v.left(1) <= "z")
+ else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z")
return 0;
else if (v == "*" || v == "/")
return 20;
@@ -113,12 +113,11 @@ 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(expr.replace_all(" ",""), sep));
+ std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, pstring(" "), pstring("")), sep));
std::stack<pstring> opstk;
std::vector<pstring> postfix;
- //printf("dbg: %s\n", expr.c_str());
- for (unsigned i = 0; i < sexpr.size(); i++)
+ for (std::size_t i = 0; i < sexpr.size(); i++)
{
pstring &s = sexpr[i];
if (s=="(")
@@ -182,14 +181,15 @@ 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)
{
- double stack[20];
+ std::array<double, 20> stack = { 0 };
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 7d5984f9d15..fbb6c508333 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 "pstring.h"
#include "pstate.h"
+#include "pstring.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 5fefa658b83..c2fee9c2f8e 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -12,6 +12,8 @@
#include "pstring.h"
+#include <array>
+#include <type_traits>
#include <vector>
namespace plib {
@@ -29,14 +31,13 @@ class uninitialised_array_t
{
public:
- typedef C* iterator;
- typedef const C* const_iterator;
+ using iterator = C *;