From 737093be1e3c32c49759ace207d6f46649aee260 Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Mon, 7 Jan 2019 22:33:15 +0300 Subject: netlist wip: 7474, 7497, test driver --- scripts/src/netlist.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/src/netlist.lua') diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 29eb931f916..f986ead5f31 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -140,6 +140,8 @@ project "netlist" MAME_DIR .. "src/lib/netlist/devices/nld_7490.h", MAME_DIR .. "src/lib/netlist/devices/nld_7493.cpp", MAME_DIR .. "src/lib/netlist/devices/nld_7493.h", + MAME_DIR .. "src/lib/netlist/devices/nld_7497.cpp", + MAME_DIR .. "src/lib/netlist/devices/nld_7497.h", MAME_DIR .. "src/lib/netlist/devices/nld_74107.cpp", MAME_DIR .. "src/lib/netlist/devices/nld_74107.h", MAME_DIR .. "src/lib/netlist/devices/nld_74123.cpp", -- cgit v1.2.3-70-g09d2 From fb685c05b9f100c46c2ae5df6532f298e45ab4f7 Mon Sep 17 00:00:00 2001 From: couriersud Date: Wed, 13 Feb 2019 21:19:59 +0100 Subject: netlist: memory allocation clean-up. (nw) --- scripts/src/netlist.lua | 2 +- src/lib/netlist/build/makefile | 1 - src/lib/netlist/devices/nld_7448.cpp | 4 +- src/lib/netlist/devices/nlid_system.h | 2 +- src/lib/netlist/nl_base.cpp | 7 +- src/lib/netlist/nl_setup.h | 14 ++-- src/lib/netlist/plib/mat_cr.h | 16 ++-- src/lib/netlist/plib/palloc.cpp | 105 ----------------------- src/lib/netlist/plib/palloc.h | 38 --------- src/lib/netlist/plib/pmain.h | 3 +- src/lib/netlist/plib/pmempool.h | 153 ++++++++++++++++++++++++++++++++++ src/lib/netlist/plib/pstream.h | 4 +- src/lib/netlist/solver/nld_ms_gmres.h | 2 +- src/lib/netlist/solver/nld_solver.cpp | 4 +- src/lib/netlist/tools/nl_convert.h | 2 +- 15 files changed, 184 insertions(+), 173 deletions(-) delete mode 100644 src/lib/netlist/plib/palloc.cpp create mode 100644 src/lib/netlist/plib/pmempool.h (limited to 'scripts/src/netlist.lua') diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index f986ead5f31..1e0a8b8c70f 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -49,7 +49,6 @@ project "netlist" MAME_DIR .. "src/lib/netlist/nl_setup.h", MAME_DIR .. "src/lib/netlist/nl_time.h", MAME_DIR .. "src/lib/netlist/plib/pconfig.h", - MAME_DIR .. "src/lib/netlist/plib/palloc.cpp", MAME_DIR .. "src/lib/netlist/plib/palloc.h", MAME_DIR .. "src/lib/netlist/plib/pchrono.cpp", MAME_DIR .. "src/lib/netlist/plib/pchrono.h", @@ -64,6 +63,7 @@ project "netlist" MAME_DIR .. "src/lib/netlist/plib/pdynlib.h", MAME_DIR .. "src/lib/netlist/plib/pmain.cpp", MAME_DIR .. "src/lib/netlist/plib/pmain.h", + MAME_DIR .. "src/lib/netlist/plib/pmempool.h", MAME_DIR .. "src/lib/netlist/plib/pomp.h", MAME_DIR .. "src/lib/netlist/plib/poptions.cpp", MAME_DIR .. "src/lib/netlist/plib/poptions.h", diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 75aaed13889..c382d2fe2ab 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -80,7 +80,6 @@ OBJS = $(POBJS) $(NLOBJS) POBJS := \ $(POBJ)/pstring.o \ - $(POBJ)/palloc.o \ $(POBJ)/pchrono.o \ $(POBJ)/pdynlib.o \ $(POBJ)/pexception.o \ diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp index 14a1f12bfcc..c95af08778f 100644 --- a/src/lib/netlist/devices/nld_7448.cpp +++ b/src/lib/netlist/devices/nld_7448.cpp @@ -7,8 +7,8 @@ #include -#include "nlid_truthtable.h" -#include "nld_7448.h" +#include "nld_7448.h" +#include "nlid_truthtable.h" namespace netlist { diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index 1c2c166dff4..2a1e4b3e66c 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -28,7 +28,7 @@ namespace netlist { NETLIB_CONSTRUCTOR(netlistparams) , m_use_deactivate(*this, "USE_DEACTIVATE", false) - , m_startup_strategy(*this, "STARTUP_STRATEGY", 0) + , m_startup_strategy(*this, "STARTUP_STRATEGY", 1) { } NETLIB_UPDATEI() { } diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 53ee4e83a8a..8ef16e58bcb 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -9,6 +9,7 @@ #include "solver/nld_solver.h" #include "plib/palloc.h" +#include "plib/pmempool.h" #include "plib/putil.h" #include "devices/nlid_proxy.h" @@ -29,10 +30,8 @@ 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 s_pool(655360, 32); + return &s_pool; } void * object_t::operator new (size_t size) diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 07dbdb887e6..55e335234d2 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -8,21 +8,22 @@ #ifndef NLSETUP_H_ #define NLSETUP_H_ +#include +#include +#include +#include + #include "plib/pparser.h" -#include "plib/pstate.h" +//#include "plib/pstate.h" #include "plib/pstream.h" #include "plib/pstring.h" #include "plib/putil.h" #include "netlist_types.h" #include "nl_config.h" -#include "nl_errstr.h" +//#include "nl_errstr.h" #include "nl_factory.h" -#include -#include -#include - //============================================================ // MACROS / inline netlist definitions //============================================================ @@ -112,7 +113,6 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \ setup.tt_factory_create(desc, __FILE__); \ } - namespace netlist { diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h index 827f9a6c270..be2d730b215 100644 --- a/src/lib/netlist/plib/mat_cr.h +++ b/src/lib/netlist/plib/mat_cr.h @@ -28,6 +28,9 @@ namespace plib { + // FIXME: causes a crash with GMRES handler + // template + template struct matrix_compressed_rows_t { @@ -69,7 +72,7 @@ namespace plib ~matrix_compressed_rows_t() = default; - index_type size() const { return m_size; } + constexpr index_type size() const { return (N>0) ? N : m_size; } void set_scalar(const T scalar) { @@ -382,7 +385,7 @@ namespace plib * */ - for (std::size_t i = 1; i < m_size; i++) // row i + 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 @@ -398,8 +401,8 @@ namespace plib 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 auto c_i_j = col_idx[i_j]; // row i, column j - const auto c_k_j = col_idx[k_j]; // row i, column j + 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) @@ -435,7 +438,7 @@ namespace plib * This can be solved for x using backwards elimination in U. * */ - for (std::size_t i = 1; i < m_size; ++i ) + for (std::size_t i = 1; i < size(); ++i ) { T tmp = 0.0; const std::size_t j1 = row_idx[i]; @@ -443,11 +446,10 @@ namespace plib 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 = m_size; i-- > 0; ) + for (std::size_t i = size(); i-- > 0; ) { T tmp = 0.0; const std::size_t di = diag[i]; diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp deleted file mode 100644 index 4115a450a40..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 "pexception.h" -#include "pfmtlog.h" -#include "pstream.h" - -#include - -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) - { - perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); - } - ::operator delete(b->data); - } - m_blocks.clear(); -} - -mempool::block * mempool::new_block() -{ - auto *b = new block(); - b->data = static_cast(::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 b; -} - -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 (auto &b : m_blocks) - { - if (b->m_free > rs) - { - b->m_free -= rs; - b->m_num_alloc++; - auto i = reinterpret_cast(b->cur_ptr); - i->m_block = b; - auto ret = reinterpret_cast(b->cur_ptr + mininfosize()); - b->cur_ptr += rs; - return ret; - } - } - { - block *b = new_block(); - b->m_num_alloc = 1; - b->m_free = m_min_alloc - rs; - auto i = reinterpret_cast(b->cur_ptr); - i->m_block = b; - auto ret = reinterpret_cast(b->cur_ptr + mininfosize()); - b->cur_ptr += rs; - return ret; - } -} - -void mempool::free(void *ptr) -{ - auto p = reinterpret_cast(ptr); - - auto i = reinterpret_cast(p - mininfosize()); - block *b = i->m_block; - if (b->m_num_alloc == 0) - throw plib::pexception("mempool::free - double free was called\n"); - else - { - //b->m_free = m_min_alloc; - //b->cur_ptr = b->data; - } - b->m_num_alloc--; -} - -} // namespace plib diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index b837455095c..72a10d54dc2 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -151,44 +151,6 @@ private: bool m_is_owned; }; -class mempool -{ -private: - struct block - { - 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; - }; - - block * new_block(); - size_t mininfosize(); - - struct info - { - info() : m_block(nullptr) { } - block * m_block; - }; - - size_t m_min_alloc; - size_t m_min_align; - - std::vector m_blocks; - -public: - mempool(size_t min_alloc, size_t min_align); - - COPYASSIGNMOVE(mempool, delete) - - ~mempool(); - - void *alloc(size_t size); - void free(void *ptr); - -}; - } // namespace plib #endif /* PALLOC_H_ */ diff --git a/src/lib/netlist/plib/pmain.h b/src/lib/netlist/plib/pmain.h index e6fb0bd60d5..4f4be779251 100644 --- a/src/lib/netlist/plib/pmain.h +++ b/src/lib/netlist/plib/pmain.h @@ -10,6 +10,7 @@ #ifndef PMAIN_H_ #define PMAIN_H_ +#include "palloc.h" #include "poptions.h" #include "pstream.h" #include "pstring.h" @@ -53,7 +54,7 @@ namespace plib { template static int mainrun(int argc, T **argv) { - auto a = std::unique_ptr(new C); + auto a = plib::make_unique(); return a->main_utfX(argc, argv); } diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h new file mode 100644 index 00000000000..2e15076b477 --- /dev/null +++ b/src/lib/netlist/plib/pmempool.h @@ -0,0 +1,153 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * palloc.h + * + */ + +#ifndef PMEMPOOL_H_ +#define PMEMPOOL_H_ + +#include "palloc.h" +#include "pstream.h" +#include "pstring.h" +#include "ptypes.h" +#include "putil.h" + +#include +#include +#include +#include +#include +#include + +namespace plib { + + //============================================================ + // Memory pool + //============================================================ + + class mempool + { + private: + struct block + { + block(mempool *mp) + : m_num_alloc(0) + , m_free(mp->m_min_alloc) + , m_cur(0) + , m_data(nullptr) + , m_mempool(mp) + { + std::size_t alloc_bytes = (mp->m_min_alloc + mp->m_min_align - 1) & ~(mp->m_min_align - 1); + m_data_allocated = static_cast(::operator new(alloc_bytes)); + void *r = m_data_allocated; + std::align(mp->m_min_align, mp->m_min_alloc, r, alloc_bytes); + m_data = reinterpret_cast(r); + } + std::size_t m_num_alloc; + std::size_t m_free; + std::size_t m_cur; + char *m_data; + char *m_data_allocated; + mempool *m_mempool; + }; + + struct info + { + info(block *b, std::size_t p) : m_block(b), m_pos(p) { } + info(const info &) = default; + info(info &&) = default; + block * m_block; + std::size_t m_pos; + }; + + + block * new_block() + { + auto *b = new block(this); + m_blocks.push_back(b); + return b; + } + + + static std::unordered_map &sinfo() + { + static std::unordered_map spinfo; + return spinfo; + } + + size_t m_min_alloc; + size_t m_min_align; + + std::vector m_blocks; + + public: + + mempool(size_t min_alloc, size_t min_align) + : m_min_alloc(min_alloc), m_min_align(min_align) + { + } + + + COPYASSIGNMOVE(mempool, delete) + + ~mempool() + { + for (auto & b : m_blocks) + { + if (b->m_num_alloc != 0) + { + plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); + } + ::operator delete(b->m_data); + } + } + + + void *alloc(size_t size) + { + size_t rs = (size + m_min_align - 1) & ~(m_min_align - 1); + for (auto &b : m_blocks) + { + if (b->m_free > rs) + { + b->m_free -= rs; + b->m_num_alloc++; + auto ret = reinterpret_cast(b->m_data + b->m_cur); + sinfo().insert({ ret, info(b, b->m_cur)}); + b->m_cur += rs; + return ret; + } + } + { + block *b = new_block(); + b->m_num_alloc = 1; + b->m_free = m_min_alloc - rs; + auto ret = reinterpret_cast(b->m_data + b->m_cur); + sinfo().insert({ ret, info(b, b->m_cur)}); + b->m_cur += rs; + return ret; + } + } + + void free(void *ptr) + { + info i = sinfo().find(ptr)->second; + block *b = i.m_block; + if (b->m_num_alloc == 0) + throw plib::pexception("mempool::free - double free was called\n"); + else + { + //b->m_free = m_min_alloc; + //b->cur_ptr = b->data; + } + b->m_num_alloc--; + } + + + }; + +} // namespace plib + +#endif /* PMEMPOOL_H_ */ diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index 17a5f2702a4..80619137c51 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -626,11 +626,11 @@ public: { std::size_t sz = 0; read(sz); - auto buf = new plib::string_info::mem_t[sz+1]; + auto buf = plib::palloc_array::mem_t>(sz+1); m_strm.read(reinterpret_cast(buf), sz); buf[sz] = 0; s = pstring(buf); - delete [] buf; + plib::pfree_array(buf); } template diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index 3cd88dea429..16dec115934 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -105,7 +105,7 @@ namespace devices { const std::size_t iN = this->size(); - plib::parray RHS(iN); + alignas(128) plib::parray RHS(iN); //float_type new_V[storage_N]; m_ops.m_mat.set_scalar(0.0); diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 5d17056637a..3982f88b4c0 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -343,8 +343,8 @@ void NETLIB_NAME(solver)::post_start() break; #endif #if 0 - case 87: - ms = create_solver<87,87>(87, sname); + case 86: + ms = create_solver(86, sname); break; #endif #endif diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index 2c7393bc82e..7dd0e56c5ee 100644 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -10,10 +10,10 @@ #ifndef NL_CONVERT_H_ #define NL_CONVERT_H_ -#include "../plib/ptypes.h" #include "../plib/plists.h" #include "../plib/pparser.h" #include "../plib/pstring.h" +#include "../plib/ptypes.h" #include /*------------------------------------------------- -- cgit v1.2.3-70-g09d2 From 9e495a17ebc5cb70c114c08b96bcc819e8f2feab Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 14 Feb 2019 06:48:56 +0900 Subject: scripts/src/netlist.lua : Fix spacing --- scripts/src/netlist.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/src/netlist.lua') diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 1e0a8b8c70f..5e6d239373e 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -63,7 +63,7 @@ project "netlist" MAME_DIR .. "src/lib/netlist/plib/pdynlib.h", MAME_DIR .. "src/lib/netlist/plib/pmain.cpp", MAME_DIR .. "src/lib/netlist/plib/pmain.h", - MAME_DIR .. "src/lib/netlist/plib/pmempool.h", + MAME_DIR .. "src/lib/netlist/plib/pmempool.h", MAME_DIR .. "src/lib/netlist/plib/pomp.h", MAME_DIR .. "src/lib/netlist/plib/poptions.cpp", MAME_DIR .. "src/lib/netlist/plib/poptions.h", -- cgit v1.2.3-70-g09d2 From 672f9b092a0a93048e8db600a9dce86f29f465d3 Mon Sep 17 00:00:00 2001 From: couriersud Date: Sat, 23 Feb 2019 17:45:08 +0100 Subject: Move ptime struct into plib namespace and fix relative includes. (nw) --- scripts/src/netlist.lua | 6 +- scripts/src/tools.lua | 2 + src/devices/machine/netlist.h | 3 +- src/lib/netlist/analog/nlid_fourterm.h | 2 +- src/lib/netlist/analog/nlid_twoterm.h | 2 +- src/lib/netlist/build/makefile | 2 +- src/lib/netlist/devices/nld_log.cpp | 4 +- src/lib/netlist/devices/nlid_system.h | 2 +- src/lib/netlist/devices/nlid_truthtable.cpp | 4 +- src/lib/netlist/devices/nlid_truthtable.h | 2 +- src/lib/netlist/netlist_types.h | 114 ------------------- src/lib/netlist/nl_base.h | 4 +- src/lib/netlist/nl_factory.h | 2 +- src/lib/netlist/nl_lists.h | 2 +- src/lib/netlist/nl_setup.h | 2 +- src/lib/netlist/nl_time.h | 159 --------------------------- src/lib/netlist/nl_types.h | 140 +++++++++++++++++++++++ src/lib/netlist/plib/ptime.h | 136 +++++++++++++++++++++++ src/lib/netlist/prg/nlwav.cpp | 10 +- src/lib/netlist/solver/nld_matrix_solver.cpp | 2 +- src/lib/netlist/solver/nld_ms_direct.h | 4 +- src/lib/netlist/solver/nld_ms_gcr.h | 11 +- src/lib/netlist/solver/nld_ms_gmres.h | 8 +- src/lib/netlist/solver/nld_ms_sm.h | 2 +- src/lib/netlist/solver/nld_ms_w.h | 2 +- src/lib/netlist/solver/nld_solver.cpp | 2 +- src/lib/netlist/solver/nld_solver.h | 2 +- src/lib/netlist/tools/nl_convert.cpp | 4 +- src/lib/netlist/tools/nl_convert.h | 8 +- 29 files changed, 324 insertions(+), 319 deletions(-) delete mode 100644 src/lib/netlist/netlist_types.h delete mode 100644 src/lib/netlist/nl_time.h create mode 100644 src/lib/netlist/nl_types.h create mode 100644 src/lib/netlist/plib/ptime.h (limited to 'scripts/src/netlist.lua') diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 5e6d239373e..09575cacffc 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -32,6 +32,7 @@ project "netlist" includedirs { MAME_DIR .. "src/lib", + MAME_DIR .. "src/lib/netlist", } files { @@ -47,7 +48,7 @@ project "netlist" MAME_DIR .. "src/lib/netlist/nl_parser.h", MAME_DIR .. "src/lib/netlist/nl_setup.cpp", MAME_DIR .. "src/lib/netlist/nl_setup.h", - MAME_DIR .. "src/lib/netlist/nl_time.h", + MAME_DIR .. "src/lib/netlist/nl_types.h", MAME_DIR .. "src/lib/netlist/plib/pconfig.h", MAME_DIR .. "src/lib/netlist/plib/palloc.h", MAME_DIR .. "src/lib/netlist/plib/pchrono.cpp", @@ -74,10 +75,9 @@ project "netlist" MAME_DIR .. "src/lib/netlist/plib/pstate.h", MAME_DIR .. "src/lib/netlist/plib/pstring.cpp", MAME_DIR .. "src/lib/netlist/plib/pstring.h", - MAME_DIR .. "src/lib/netlist/plib/pstring.cpp", - MAME_DIR .. "src/lib/netlist/plib/pstring.h", MAME_DIR .. "src/lib/netlist/plib/pstream.cpp", MAME_DIR .. "src/lib/netlist/plib/pstream.h", + MAME_DIR .. "src/lib/netlist/plib/ptime.h", MAME_DIR .. "src/lib/netlist/plib/ptypes.h", MAME_DIR .. "src/lib/netlist/plib/putil.cpp", MAME_DIR .. "src/lib/netlist/plib/putil.h", diff --git a/scripts/src/tools.lua b/scripts/src/tools.lua index f991c16bbea..564653f5a4a 100644 --- a/scripts/src/tools.lua +++ b/scripts/src/tools.lua @@ -499,6 +499,7 @@ links { includedirs { MAME_DIR .. "src/lib", + MAME_DIR .. "src/lib/netlist", } files { @@ -543,6 +544,7 @@ links { includedirs { MAME_DIR .. "src/lib", + MAME_DIR .. "src/lib/netlist", } files { diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index 182c77ece2c..58a8c065b14 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -13,8 +13,7 @@ #include -#include "netlist/nl_time.h" -#include "netlist/netlist_types.h" +#include "../../lib/netlist/nl_types.h" class nld_sound_out; class nld_sound_in; diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h index 2d0d1ec174f..9eb2fbc5f36 100644 --- a/src/lib/netlist/analog/nlid_fourterm.h +++ b/src/lib/netlist/analog/nlid_fourterm.h @@ -9,7 +9,7 @@ #define NLID_FOURTERM_H_ #include "../nl_base.h" -#include "../plib/putil.h" +#include "plib/putil.h" namespace netlist { namespace analog { diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index 546e8193734..131504d86e4 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -33,7 +33,7 @@ #ifndef NLID_TWOTERM_H_ #define NLID_TWOTERM_H_ -#include "../plib/pfunction.h" +#include "plib/pfunction.h" #include "netlist/nl_base.h" #include "netlist/nl_setup.h" diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index d4296c1b007..f628e9eaed6 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -49,7 +49,7 @@ endif # LTO = -flto=4 -fuse-linker-plugin -flto-partition=balanced -Wodr -CFLAGS = $(LTO) -g -O3 -std=c++11 -I../.. $(CEXTRAFLAGS) +CFLAGS = $(LTO) -g -O3 -std=c++11 -I$(CURDIR)/.. -I$(CURDIR)/../.. $(CEXTRAFLAGS) LDFLAGS = $(LTO) -g -O3 -std=c++11 $(LDEXTRAFLAGS) LIBS = -lpthread -ldl diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp index c99fcb5a9bc..8cbcf0c81ca 100644 --- a/src/lib/netlist/devices/nld_log.cpp +++ b/src/lib/netlist/devices/nld_log.cpp @@ -6,8 +6,8 @@ */ #include "../nl_base.h" -#include "../plib/pfmtlog.h" -#include "../plib/pstream.h" +#include "plib/pfmtlog.h" +#include "plib/pstream.h" #include "nld_log.h" //#include "sound/wavwrite.h" diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index 10cbc498a6b..e744ee11dc6 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -14,7 +14,7 @@ #include "../analog/nlid_twoterm.h" #include "../nl_base.h" #include "../nl_setup.h" -#include "../plib/putil.h" +#include "plib/putil.h" namespace netlist { diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 78fd076b560..e1a6f5e9046 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -7,8 +7,8 @@ #include "nlid_truthtable.h" #include "../nl_setup.h" -#include "../plib/palloc.h" -#include "../plib/plists.h" +#include "plib/palloc.h" +#include "plib/plists.h" #include diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h index a4b9e1e238e..c995b1c766e 100644 --- a/src/lib/netlist/devices/nlid_truthtable.h +++ b/src/lib/netlist/devices/nlid_truthtable.h @@ -12,7 +12,7 @@ #include "../nl_base.h" #include "../nl_setup.h" -#include "../plib/putil.h" +#include "plib/putil.h" #define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \ class NETLIB_NAME(cname) : public nld_truthtable_t \ diff --git a/src/lib/netlist/netlist_types.h b/src/lib/netlist/netlist_types.h deleted file mode 100644 index b2a507fe0fe..00000000000 --- a/src/lib/netlist/netlist_types.h +++ /dev/null @@ -1,114 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/*! - * - * \file netlist_types.h - * - */ - -#ifndef NETLIST_TYPES_H_ -#define NETLIST_TYPES_H_ - -#include -#include - -#include "nl_config.h" -#include "plib/pchrono.h" -#include "plib/pfmtlog.h" -#include "plib/pmempool.h" -#include "plib/pstring.h" - - -namespace netlist -{ - /*! @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; - - - //============================================================ - // Performance tracking - //============================================================ - - template - using nperftime_t = plib::chrono::timer; - - template - using nperfcount_t = plib::chrono::counter; - - //============================================================ - // 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::mempool_default; -#endif - - /*! Owned pointer type for pooled allocations. - * - */ - template - using poolptr = nlmempool::poolptr; - - inline nlmempool &pool() - { - static nlmempool static_pool(655360, 16); - 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 */ - }; - - /*! Type of the model map used. - * This is used to hold all #Models in an unordered map - */ - using model_map_t = std::unordered_map; - - } // namespace detail -} // namespace netlist - -#endif /* NETLIST_TYPES_H_ */ diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index dccfb32f896..adbda1d679d 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -24,10 +24,10 @@ #include "plib/pstate.h" #include "plib/pstream.h" -#include "netlist_types.h" +#include "nl_types.h" #include "nl_errstr.h" #include "nl_lists.h" -#include "nl_time.h" +#include "plib/ptime.h" //============================================================ // MACROS / New Syntax diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index cd7e74944eb..abf41ef9f93 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -11,7 +11,7 @@ #include -#include "netlist_types.h" +#include "nl_types.h" #include "plib/palloc.h" #include "plib/ptypes.h" diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h index 5443cd86c86..32e31998b7a 100644 --- a/src/lib/netlist/nl_lists.h +++ b/src/lib/netlist/nl_lists.h @@ -10,7 +10,6 @@ #ifndef NLLISTS_H_ #define NLLISTS_H_ -#include "netlist_types.h" #include "nl_config.h" #include "plib/pchrono.h" #include "plib/plists.h" @@ -21,6 +20,7 @@ #include #include #include +#include "nl_types.h" // ---------------------------------------------------------------------------------------- // timed queue diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 50536d9da3b..dd4f9b381ac 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -18,9 +18,9 @@ #include "plib/pstring.h" #include "plib/putil.h" -#include "netlist_types.h" #include "nl_config.h" #include "nl_factory.h" +#include "nl_types.h" //============================================================ // MACROS / inline netlist definitions diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h deleted file mode 100644 index 1db22241d64..00000000000 --- a/src/lib/netlist/nl_time.h +++ /dev/null @@ -1,159 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nltime.h - */ - -#ifndef NLTIME_H_ -#define NLTIME_H_ - -#include "nl_config.h" -#include "plib/pstate.h" -#include "plib/ptypes.h" - -#include - -// ---------------------------------------------------------------------------------------- -// netlist_time -// ---------------------------------------------------------------------------------------- - -namespace netlist -{ - - template - struct ptime final - { - public: - - using internal_type = TYPE; - using mult_type = TYPE; - - constexpr ptime() noexcept : m_time(0) {} - - ~ptime() noexcept = default; - - constexpr ptime(const ptime &rhs) noexcept = default; - constexpr ptime(ptime &&rhs) noexcept = default; - constexpr explicit ptime(const internal_type &time) noexcept : m_time(time) {} - constexpr explicit ptime(internal_type &&time) noexcept : m_time(time) {} - C14CONSTEXPR ptime &operator=(const ptime &rhs) noexcept = default; - C14CONSTEXPR ptime &operator=(ptime &&rhs) noexcept = default; - - constexpr explicit ptime(const double t) = delete; - //: m_time((internal_type) ( t * (double) resolution)) { } - constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept - : m_time(nom * (RES / den)) { } - - C14CONSTEXPR ptime &operator+=(const ptime rhs) noexcept { m_time += rhs.m_time; return *this; } - C14CONSTEXPR ptime &operator-=(const ptime rhs) noexcept { m_time -= rhs.m_time; return *this; } - C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast(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(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(m_time) * inv_res; - } - - // for save states .... - C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; } - - static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); } - static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C( 1000000)); } - static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C( 1000)); } - static constexpr ptime from_sec(const internal_type s) noexcept { return ptime(s, UINT64_C( 1)); } - static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); } - static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); } - static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast( t * static_cast(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::max(), RES); } - static constexpr internal_type resolution() noexcept { return RES; } - - constexpr internal_type in_nsec() const noexcept { return m_time / (RES / UINT64_C(1000000000)); } - constexpr internal_type in_usec() const noexcept { return m_time / (RES / UINT64_C( 1000000)); } - constexpr internal_type in_msec() const noexcept { return m_time / (RES / UINT64_C( 1000)); } - constexpr internal_type in_sec() const noexcept { return m_time / (RES / UINT64_C( 1)); } - - private: - static constexpr const double inv_res = 1.0 / static_cast(RES); - internal_type m_time; - }; - -#if (PHAS_INT128) - using netlist_time = ptime; -#else - using netlist_time = ptime; - static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr"); -#endif - - //============================================================ - // MACROS - //============================================================ - - template inline constexpr netlist_time NLTIME_FROM_NS(T &&t) noexcept { return netlist_time::from_nsec(t); } - template inline constexpr netlist_time NLTIME_FROM_US(T &&t) noexcept { return netlist_time::from_usec(t); } - template inline constexpr 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 /* NLTIME_H_ */ diff --git a/src/lib/netlist/nl_types.h b/src/lib/netlist/nl_types.h new file mode 100644 index 00000000000..8b229e85bf5 --- /dev/null +++ b/src/lib/netlist/nl_types.h @@ -0,0 +1,140 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/*! + * + * \file nl_types.h + * + */ + +#ifndef NL_TYPES_H_ +#define NL_TYPES_H_ + +#include "nl_config.h" +#include "plib/ptime.h" +#include "plib/pchrono.h" +#include "plib/pfmtlog.h" +#include "plib/pmempool.h" +#include "plib/pstring.h" +#include "plib/pstate.h" + +#include +#include + +namespace netlist +{ + /*! @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; + + + //============================================================ + // Performance tracking + //============================================================ + + template + using nperftime_t = plib::chrono::timer; + + template + using nperfcount_t = plib::chrono::counter; + + //============================================================ + // 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::mempool_default; +#endif + + /*! Owned pointer type for pooled allocations. + * + */ + template + using poolptr = nlmempool::poolptr; + + inline nlmempool &pool() + { + static nlmempool static_pool(655360, 16); + 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 */ + }; + + /*! Type of the model map used. + * This is used to hold all #Models in an unordered map + */ + using model_map_t = std::unordered_map; + + } // namespace detail + +#if (PHAS_INT128) + using netlist_time = ptime; +#else + using netlist_time = plib::ptime; + static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr"); +#endif + + //============================================================ + // MACROS + //============================================================ + + template inline constexpr netlist_time NLTIME_FROM_NS(T &&t) noexcept { return netlist_time::from_nsec(t); } + template inline constexpr netlist_time NLTIME_FROM_US(T &&t) noexcept { return netlist_time::from_usec(t); } + template inline constexpr 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 /* NL_TYPES_H_ */ diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h new file mode 100644 index 00000000000..4767a197342 --- /dev/null +++ b/src/lib/netlist/plib/ptime.h @@ -0,0 +1,136 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * ptime.h + */ + +#ifndef PTIME_H_ +#define PTIME_H_ + +#include "pconfig.h" +#include "ptypes.h" + +#include + +// ---------------------------------------------------------------------------------------- +// netlist_time +// ---------------------------------------------------------------------------------------- + +namespace plib +{ + + template + struct ptime final + { + public: + + using internal_type = TYPE; + using mult_type = TYPE; + + constexpr ptime() noexcept : m_time(0) {} + + ~ptime() noexcept = default; + + constexpr ptime(const ptime &rhs) noexcept = default; + constexpr ptime(ptime &&rhs) noexcept = default; + constexpr explicit ptime(const internal_type &time) noexcept : m_time(time) {} + constexpr explicit ptime(internal_type &&time) noexcept : m_time(time) {} + C14CONSTEXPR ptime &operator=(const ptime &rhs) noexcept = default; + C14CONSTEXPR ptime &operator=(ptime &&rhs) noexcept = default; + + constexpr explicit ptime(const double t) = delete; + //: m_time((internal_type) ( t * (double) resolution)) { } + constexpr explicit ptime(const internal_type nom, const internal_type den) noexcept + : m_time(nom * (RES / den)) { } + + C14CONSTEXPR ptime &operator+=(const ptime rhs) noexcept { m_time += rhs.m_time; return *this; } + C14CONSTEXPR ptime &operator-=(const ptime rhs) noexcept { m_time -= rhs.m_time; return *this; } + C14CONSTEXPR ptime &operator*=(const mult_type factor) noexcept { m_time *= static_cast(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(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(m_time) * inv_res; + } + + // for save states .... + C14CONSTEXPR internal_type *get_internaltype_ptr() noexcept { return &m_time; } + + static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); } + static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C( 1000000)); } + static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C( 1000)); } + static constexpr ptime from_sec(const internal_type s) noexcept { return ptime(s, UINT64_C( 1)); } + static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); } + static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); } + static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast( t * static_cast(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::max(), RES); } + static constexpr internal_type resolution() noexcept { return RES; } + + constexpr internal_type in_nsec() const noexcept { return m_time / (RES / UINT64_C(1000000000)); } + constexpr internal_type in_usec() const noexcept { return m_time / (RES / UINT64_C( 1000000)); } + constexpr internal_type in_msec() const noexcept { return m_time / (RES / UINT64_C( 1000)); } + constexpr internal_type in_sec() const noexcept { return m_time / (RES / UINT64_C( 1)); } + + private: + static constexpr const double inv_res = 1.0 / static_cast(RES); + internal_type m_time; + }; + + +} // namespace plib + + +#endif /* PTIME_H_ */ diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index bd30e93d7e6..384d11f5781 100644 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -1,11 +1,11 @@ // license:GPL-2.0+ // copyright-holders:Couriersud -#include "../plib/pstring.h" +#include "plib/pstring.h" #include "../nl_setup.h" -#include "../plib/plists.h" -#include "../plib/pmain.h" -#include "../plib/ppmf.h" -#include "../plib/pstream.h" +#include "plib/plists.h" +#include "plib/pmain.h" +#include "plib/ppmf.h" +#include "plib/pstream.h" #include diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 6494ca6eaee..68cad1422ea 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -6,7 +6,7 @@ */ #include "nld_matrix_solver.h" -#include "../plib/putil.h" +#include "plib/putil.h" #include // <<= needed by windows build diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h index 13f187f41b5..c0995d99e54 100644 --- a/src/lib/netlist/solver/nld_ms_direct.h +++ b/src/lib/netlist/solver/nld_ms_direct.h @@ -10,8 +10,8 @@ #include #include -#include -#include +#include "plib/mat_cr.h" +#include "plib/vector_ops.h" #include "nld_matrix_solver.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index d2caa944434..0a9f720f104 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -10,15 +10,16 @@ #ifndef NLD_MS_GCR_H_ #define NLD_MS_GCR_H_ -#include -#include +#include "plib/mat_cr.h" -#include "../plib/pdynlib.h" -#include "../plib/pstream.h" -#include "../plib/vector_ops.h" +#include "plib/pdynlib.h" +#include "plib/pstream.h" +#include "plib/vector_ops.h" #include "nld_ms_direct.h" #include "nld_solver.h" +#include + namespace netlist { namespace devices diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index e8963578452..bee5c25e3d5 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -8,10 +8,10 @@ #ifndef NLD_MS_GMRES_H_ #define NLD_MS_GMRES_H_ -#include "../plib/gmres.h" -#include "../plib/mat_cr.h" -#include "../plib/parray.h" -#include "../plib/vector_ops.h" +#include "plib/gmres.h" +#include "plib/mat_cr.h" +#include "plib/parray.h" +#include "plib/vector_ops.h" #include "nld_ms_direct.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h index c473b6131e7..6c0f610e3f2 100644 --- a/src/lib/netlist/solver/nld_ms_sm.h +++ b/src/lib/netlist/solver/nld_ms_sm.h @@ -35,7 +35,7 @@ #include -#include "../plib/vector_ops.h" +#include "plib/vector_ops.h" #include "nld_matrix_solver.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h index e5935462f03..584d50fdb15 100644 --- a/src/lib/netlist/solver/nld_ms_w.h +++ b/src/lib/netlist/solver/nld_ms_w.h @@ -42,7 +42,7 @@ #include -#include "../plib/vector_ops.h" +#include "plib/vector_ops.h" #include "nld_matrix_solver.h" #include "nld_solver.h" diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index be008a21706..ab75b7d7dc4 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -33,7 +33,7 @@ #include "../nl_lists.h" -#include "../plib/pomp.h" +#include "plib/pomp.h" #include "../nl_factory.h" diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index 646271e0ebd..87e02d215ec 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -9,7 +9,7 @@ #define NLD_SOLVER_H_ #include "../nl_base.h" -#include "../plib/pstream.h" +#include "plib/pstream.h" #include "nld_matrix_solver.h" #include diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp index 16a3cfd6960..a9e17d56120 100644 --- a/src/lib/netlist/tools/nl_convert.cpp +++ b/src/lib/netlist/tools/nl_convert.cpp @@ -5,8 +5,8 @@ * */ -#include "../plib/palloc.h" -#include "../plib/putil.h" +#include "plib/palloc.h" +#include "plib/putil.h" #include "nl_convert.h" #include #include diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index b031ef72618..367546092be 100644 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -10,10 +10,10 @@ #ifndef NL_CONVERT_H_ #define NL_CONVERT_H_ -#include "../plib/plists.h" -#include "../plib/pparser.h" -#include "../plib/pstring.h" -#include "../plib/ptypes.h" +#include "plib/plists.h" +#include "plib/pparser.h" +#include "plib/pstring.h" +#include "plib/ptypes.h" #include /*------------------------------------------------- -- cgit v1.2.3-70-g09d2 From 39a7c420b1a956cfb680481077ed19f6315c6d37 Mon Sep 17 00:00:00 2001 From: couriersud Date: Mon, 25 Mar 2019 21:34:24 +0100 Subject: netlist: add MOSFET model. [Couriersud] - added MOSFET model. Currently capacitances are not modelled. This is a 3-pin model (Bulk connected to Source) with provisions to extend it to 4-pin at a later stage. - Add a capacitor generic model which is charge conserving. Switch netlist to use this model instead of constant capacity model. - Start putting constants into a central place. Please expect minor timing differences due to a different numerical path. The cmos inverter example illustrates the analog implementation of a cmos inverter gate. These were used a lot back in the 70s/80s to generate sinus waves. The model should also be able to better emulate 4066 analog switches. The addition of a relatively simple capacitor model is planned at a later stage. Expect everything from the MOSFET model at the current stage. Wrong results as well as convergence issues and crashes. --- nl_examples/cmos_inverter.cpp | 42 +++ nl_examples/nmos_fet.cpp | 52 ++++ scripts/src/netlist.lua | 2 + src/lib/netlist/analog/nld_bjt.cpp | 10 +- src/lib/netlist/analog/nld_mosfet.cpp | 488 ++++++++++++++++++++++++++++++++ src/lib/netlist/analog/nld_mosfet.h | 21 ++ src/lib/netlist/analog/nlid_twoterm.cpp | 98 +------ src/lib/netlist/analog/nlid_twoterm.h | 196 ++++++++++++- src/lib/netlist/build/makefile | 3 +- src/lib/netlist/devices/net_lib.cpp | 1 + src/lib/netlist/devices/net_lib.h | 1 + src/lib/netlist/macro/nlm_base.cpp | 10 + src/lib/netlist/nl_base.h | 7 +- src/lib/netlist/nltypes.h | 8 + src/lib/netlist/plib/palloc.h | 2 +- src/lib/netlist/plib/putil.h | 29 ++ src/lib/netlist/solver/nld_ms_direct2.h | 1 + 17 files changed, 855 insertions(+), 116 deletions(-) create mode 100644 nl_examples/cmos_inverter.cpp create mode 100644 nl_examples/nmos_fet.cpp create mode 100644 src/lib/netlist/analog/nld_mosfet.cpp create mode 100644 src/lib/netlist/analog/nld_mosfet.h (limited to 'scripts/src/netlist.lua') diff --git a/nl_examples/cmos_inverter.cpp b/nl_examples/cmos_inverter.cpp new file mode 100644 index 00000000000..e0936bfd3bc --- /dev/null +++ b/nl_examples/cmos_inverter.cpp @@ -0,0 +1,42 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * bjt.c + * + */ + + +#include "netlist/devices/net_lib.h" +#include "netlist/analog/nld_twoterm.h" + +NETLIST_START(cmos_inverter) + /* Standard stuff */ + + SOLVER(Solver, 48000) + PARAM(Solver.ACCURACY, 1e-7) + PARAM(Solver.NR_LOOPS, 5000) + PARAM(Solver.METHOD, "MAT_CR") + ANALOG_INPUT(V5, 5) + + VS(IN, 5) + PARAM(IN.FUNC, "T 5 *") + + MOSFET(P, "PMOS(VTO=-1.0 KP=2e-3 LAMBDA=2E-2)") + MOSFET(M, "NMOS(VTO=1.0 KP=2e-3 LAMBDA=2E-2)") + + NET_C(P.S, V5) + NET_C(P.D, M.D) + NET_C(GND, M.S, IN.N) + + NET_C(IN.P, M.G, P.G) + + // capacitance over D - S +#if 0 + CAP(C, CAP_N(1)) + NET_C(M.D, C.1) + NET_C(M.S, C.2) +#endif + LOG(log_G, M.G) + LOG(log_D, M.D) + +NETLIST_END() diff --git a/nl_examples/nmos_fet.cpp b/nl_examples/nmos_fet.cpp new file mode 100644 index 00000000000..ffa67c1bf00 --- /dev/null +++ b/nl_examples/nmos_fet.cpp @@ -0,0 +1,52 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * bjt.c + * + */ + + +#include "netlist/devices/net_lib.h" +#include "netlist/analog/nld_twoterm.h" + +NETLIST_START(bjt) + /* Standard stuff */ + + CLOCK(clk, 100) // 100 Hz + SOLVER(Solver, 48000) + PARAM(Solver.ACCURACY, 1e-7) + PARAM(Solver.NR_LOOPS, 5000) + ANALOG_INPUT(V5, 5) + ANALOG_INPUT(V3, 3.5) + + /* NMOS - example */ + + NET_MODEL("MM NMOS(VTO=1.0 KP=2e-3 LAMBDA=2E-2)") + MOSFET(M, "MM") + + RES(RB, 1000) + RES(RC, 10000) + + NET_C(RC.1, V5) + NET_C(RC.2, M.D) + NET_C(RB.1, clk) + //NET_C(RB.1, V3) + NET_C(RB.2, M.G) + NET_C(M.S, GND) + + // put some load on M.D + + RES(RCE, 150000) + NET_C(RCE.1, M.D) + NET_C(RCE.2, GND) + + // capacitance over D - S + + CAP(C, CAP_N(1)) + NET_C(M.D, C.1) + NET_C(M.S, C.2) + + LOG(log_G, M.G) + LOG(log_D, M.D) + +NETLIST_END() diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 09575cacffc..e24eb2d26ef 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -85,6 +85,8 @@ project "netlist" MAME_DIR .. "src/lib/netlist/tools/nl_convert.h", MAME_DIR .. "src/lib/netlist/analog/nld_bjt.cpp", MAME_DIR .. "src/lib/netlist/analog/nld_bjt.h", + MAME_DIR .. "src/lib/netlist/analog/nld_mosfet.cpp", + MAME_DIR .. "src/lib/netlist/analog/nld_mosfet.h", MAME_DIR .. "src/lib/netlist/analog/nlid_fourterm.cpp", MAME_DIR .. "src/lib/netlist/analog/nlid_fourterm.h", MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.h", diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp index 6050bdb6f37..aef920635fe 100644 --- a/src/lib/netlist/analog/nld_bjt.cpp +++ b/src/lib/netlist/analog/nld_bjt.cpp @@ -9,12 +9,14 @@ #include "netlist/nl_setup.h" #include "nlid_twoterm.h" + #include namespace netlist { namespace analog { + using constants = plib::constants; class diode { @@ -279,8 +281,8 @@ namespace analog NETLIB_UPDATE_TERMINALSI(); private: - generic_diode m_gD_BC; - generic_diode m_gD_BE; + generic_diode m_gD_BC; + generic_diode 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 @@ -449,8 +451,8 @@ namespace analog m_alpha_f = BF / (1.0 + BF); m_alpha_r = BR / (1.0 + BR); - m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin()); - m_gD_BC.set_param(IS / m_alpha_r, NR, exec().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 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 + +#define BODY_CONNECTED_TO_SOURCE (1) + +namespace netlist +{ +namespace analog +{ + + using constants = plib::constants; + + // ----------------------------------------------------------------------------- + // 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 m_D_BD; +#if (!BODY_CONNECTED_TO_SOURCE) + generic_diode 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/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp index f945100c652..5019c98c0e4 100644 --- a/src/lib/netlist/analog/nlid_twoterm.cpp +++ b/src/lib/netlist/analog/nlid_twoterm.cpp @@ -16,68 +16,6 @@ namespace netlist { namespace analog { -// ---------------------------------------------------------------------------------------- -// generic_diode -// ---------------------------------------------------------------------------------------- - -generic_diode::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) - , 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) -{ - static constexpr double csqrt2 = 1.414213562373095048801688724209; //std::sqrt(2.0); - m_Is = Is; - m_logIs = std::log(Is); - m_n = n; - m_gmin = gmin; - - m_Vt = 0.0258 * m_n; - m_Vmin = -5.0 * m_Vt; - - m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2); - m_VtInv = 1.0 / m_Vt; -} - -void generic_diode::update_diode(const nl_double nVd) -{ - if (nVd < m_Vmin) - { - m_Vd = nVd; - m_G = m_gmin; - m_Id = - m_Is; - } - else if (nVd < m_Vcrit) - { - m_Vd = nVd; - //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt); - //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv); - const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv); - m_Id = IseVDVt - m_Is; - m_G = IseVDVt * m_VtInv + m_gmin; - } - else - { - const double a = std::max((nVd - m_Vd) * m_VtInv, plib::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; - } -} // ---------------------------------------------------------------------------------------- // nld_twoterm @@ -192,41 +130,15 @@ NETLIB_UPDATE_PARAM(POT2) m_R1.set_R(std::max(m_R() * v, exec().gmin())); } -// ---------------------------------------------------------------------------------------- -// nld_C -// ---------------------------------------------------------------------------------------- - -NETLIB_RESET(C) -{ - // FIXME: Startup conditions - set_G_V_I(exec().gmin(), 0.0, -5.0 / exec().gmin()); - //set(exec().gmin(), 0.0, 0.0); -} - -NETLIB_UPDATE_PARAM(C) -{ - m_GParallel = exec().gmin(); -} - -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); -} - // ---------------------------------------------------------------------------------------- // nld_L // ---------------------------------------------------------------------------------------- NETLIB_RESET(L) { - m_GParallel = exec().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); @@ -240,7 +152,7 @@ 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); @@ -255,7 +167,7 @@ NETLIB_RESET(D) nl_double Is = m_model.m_IS; nl_double n = m_model.m_N; - m_D.set_param(Is, n, exec().gmin()); + m_D.set_param(Is, n, exec().gmin(), constants::T0()); set_G_V_I(m_D.G(), 0.0, m_D.Ieq()); } @@ -264,7 +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, exec().gmin()); + m_D.set_param(Is, n, exec().gmin(), constants::T0()); } NETLIB_UPDATE_TERMINALS(D) diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index 08c7235caf1..470fb35c96e 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -35,8 +35,11 @@ #include "netlist/nl_base.h" #include "netlist/nl_setup.h" +#include "netlist/solver/nld_solver.h" #include "plib/pfunction.h" +#include + // ----------------------------------------------------------------------------- // Implementation // ----------------------------------------------------------------------------- @@ -217,6 +220,83 @@ private: param_logic_t m_Reverse; }; +// ----------------------------------------------------------------------------- +// A generic capacitor model +// ----------------------------------------------------------------------------- + +enum class capacitor_e +{ + CHARGE_CONSERVING, + CONSTANT_CAPACITY +}; + +template +class generic_capacitor +{ +}; + + +template <> +class generic_capacitor +{ +public: + generic_capacitor(device_t &dev, const pstring &name) + : m_h(dev, name + ".m_h", 0.0) + , m_charge(dev, name + ".m_charge", 0.0) + , m_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 m_h; + state_var m_charge; + nl_double m_gmin; +}; + +template <> +class generic_capacitor +{ +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 m_h; + nl_double m_gmin; +}; // ----------------------------------------------------------------------------- // nld_C @@ -227,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(); + NETLIB_RESETI() + { + m_cap.setparams(exec().gmin()); + } protected: //NETLIB_UPDATEI(); - NETLIB_UPDATE_PARAMI(); + NETLIB_UPDATE_PARAMI() { } private: - nl_double m_GParallel; - + generic_capacitor m_cap; + //generic_capacitor m_cap; }; // ----------------------------------------------------------------------------- @@ -257,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) { @@ -276,7 +376,7 @@ protected: private: param_double_t m_L; - nl_double m_GParallel; + nl_double m_gmin; nl_double m_G; nl_double m_I; }; @@ -285,14 +385,82 @@ private: // A generic diode model to be used in other devices (Diode, BJT ...) // ----------------------------------------------------------------------------- +enum class diode_e +{ + BIPOLAR, + MOS +}; + +template class generic_diode { public: - generic_diode(device_t &dev, const 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); + 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; + + 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; } @@ -391,7 +559,7 @@ protected: private: diode_model_t m_model; - generic_diode m_D; + generic_diode m_D; }; diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index ea034440b5e..647c7df6f12 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -28,7 +28,7 @@ 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,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 @@ -94,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 \ diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp index 06778d49ec5..c0353f2489a 100644 --- a/src/lib/netlist/devices/net_lib.cpp +++ b/src/lib/netlist/devices/net_lib.cpp @@ -45,6 +45,7 @@ namespace devices 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) diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h index 6cc6749eee6..abf58ccee16 100644 --- a/src/lib/netlist/devices/net_lib.h +++ b/src/lib/netlist/devices/net_lib.h @@ -92,6 +92,7 @@ #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" diff --git a/src/lib/netlist/macro/nlm_base.cpp b/src/lib/netlist/macro/nlm_base.cpp index 6d4d3c252b4..86f2450d301 100644 --- a/src/lib/netlist/macro/nlm_base.cpp +++ b/src/lib/netlist/macro/nlm_base.cpp @@ -31,6 +31,13 @@ NETLIST_END() * BJT Models * ---------------------------------------------------------------------------*/ +static NETLIST_START(mosfet_models) + //NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") + //NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") + NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") + NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)") +NETLIST_END() + static NETLIST_START(bjt_models) NET_MODEL("NPN _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)") NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)") @@ -81,7 +88,9 @@ 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) @@ -89,6 +98,7 @@ NETLIST_START(base) INCLUDE(diode_models) INCLUDE(bjt_models) + INCLUDE(mosfet_models) INCLUDE(family_models) INCLUDE(TTL74XX_lib) INCLUDE(CD4XXX_lib) diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 368ce54e345..9d0eed869e0 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -1024,6 +1024,7 @@ namespace netlist virtual void changed(); const pstring &value() const NL_NOEXCEPT { return m_param; } private: + PALIGNAS_CACHELINE() pstring m_param; }; @@ -1042,8 +1043,8 @@ namespace netlist : m_value(param.model_value(name)) { } - const double &operator()() const noexcept { return m_value; } - operator const double&() const noexcept { return m_value; } + double operator()() const noexcept { return m_value; } + operator double() const noexcept { return m_value; } private: const double m_value; }; @@ -1091,7 +1092,7 @@ 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: void changed() override { diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index f6980af5fcf..7d7582774b1 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -20,12 +20,20 @@ #include "plib/pstate.h" #include "plib/pstring.h" #include "plib/ptime.h" +#include "plib/putil.h" #include #include 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; + /*! @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. diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index ef1ed18de30..15fede3a99b 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) #include diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index 0db2ae28ffb..e8145361d9d 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -66,6 +66,35 @@ namespace plib static constexpr T one() noexcept { return static_cast(1); } static constexpr T two() noexcept { return static_cast(2); } + /*! + * \brief Electric constant of vacuum + */ + static constexpr T eps_0() noexcept { return static_cast(8.854187817e-12); } + /*! + * \brief Relative permittivity of Silicon dioxide + */ + static constexpr T eps_SiO2() noexcept { return static_cast(3.9); } + /*! + * \brief Relative permittivity of Silicon + */ + static constexpr T eps_Si() noexcept { return static_cast(11.7); } + /*! + * \brief Boltzmann constant + */ + static constexpr T k_b() noexcept { return static_cast(1.38064852e-23); } + /*! + * \brief room temperature (gives VT = 0.02585 at T=300) + */ + static constexpr T T0() noexcept { return static_cast(300); } + /*! + * \brief Elementary charge + */ + static constexpr T Q_e() noexcept { return static_cast(1.6021765314e-19); } + /*! + * \brief Intrinsic carrier concentration in 1/m^3 of Silicon + */ + static constexpr T NiSi() noexcept { return static_cast(1.45e16); } + template static constexpr const T cast(V &&v) noexcept { return static_cast(v); } }; diff --git a/src/lib/netlist/solver/nld_ms_direct2.h b/src/lib/netlist/solver/nld_ms_direct2.h index 1e7103f8672..01f77c3bc3c 100644 --- a/src/lib/netlist/solver/nld_ms_direct2.h +++ b/src/lib/netlist/solver/nld_ms_direct2.h @@ -44,6 +44,7 @@ namespace devices const float_type v0 = (this->RHS(0) - b * v1) / a; std::array new_V = {v0, v1}; + this->m_stat_calculations++; const float_type err = (newton_raphson ? this->delta(new_V) : 0.0); this->store(new_V); return (err > this->m_params.m_accuracy) ? 2 : 1; -- cgit v1.2.3-70-g09d2