diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index 6c3d88c0387..aa3d40ae795 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -81,6 +81,7 @@ project "netlist" MAME_DIR .. "src/lib/netlist/analog/nld_opamps.h", MAME_DIR .. "src/lib/netlist/solver/nld_solver.cpp", MAME_DIR .. "src/lib/netlist/solver/nld_solver.h", + MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.cpp", MAME_DIR .. "src/lib/netlist/solver/nld_matrix_solver.h", MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct.h", MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct1.h", diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index cddb4751146..81883053776 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -167,9 +167,9 @@ maketree: $(sort $(OBJDIRS)) .PHONY: clang mingw doc clang: - $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-cast-align -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-format-nonliteral -Wno-weak-template-vtables" + $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-Weverything -Werror -Wno-padded -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-cast-align -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-format-nonliteral -Wno-weak-template-vtables" -# +#-Wno-weak-vtables # FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors # diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index 080f9a27a4b..6b6da2176cf 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -17,10 +17,82 @@ namespace netlist namespace devices { + // ----------------------------------------------------------------------------- + // nld_base_proxy + // ----------------------------------------------------------------------------- + + nld_base_proxy::nld_base_proxy(netlist_t &anetlist, const pstring &name, + logic_t *inout_proxied, detail::core_terminal_t *proxy_inout) + : device_t(anetlist, name) + { + m_logic_family = inout_proxied->logic_family(); + m_term_proxied = inout_proxied; + 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, + 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_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) + { + } + + NETLIB_UPDATE(a_to_d_proxy) + { + nl_assert(m_logic_family != nullptr); + // FIXME: Variable supply voltage! + double supply_V = logic_family().fixed_V(); + if (supply_V == 0.0) supply_V = 5.0; + + if (m_I.Q_Analog() > logic_family().high_thresh_V(0.0, supply_V)) + out().push(1, NLTIME_FROM_NS(1)); + else if (m_I.Q_Analog() < logic_family().low_thresh_V(0.0, supply_V)) + out().push(0, NLTIME_FROM_NS(1)); + else + { + // do nothing + } + } + // ---------------------------------------------------------------------------------------- // nld_d_to_a_proxy // ---------------------------------------------------------------------------------------- + nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name, + logic_output_t *out_proxied, detail::core_terminal_t &proxy_out) + : nld_base_proxy(anetlist, name, out_proxied, &proxy_out) + , m_I(*this, "I") + { + } + + nld_base_d_to_a_proxy::~nld_base_d_to_a_proxy() + { + } + nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied) : nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P) , m_GNDHack(*this, "_Q") diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h index 50920c5cf80..eced07f8356 100644 --- a/src/lib/netlist/devices/nlid_proxy.h +++ b/src/lib/netlist/devices/nlid_proxy.h @@ -31,15 +31,9 @@ namespace netlist { public: nld_base_proxy(netlist_t &anetlist, const pstring &name, - logic_t *inout_proxied, detail::core_terminal_t *proxy_inout) - : device_t(anetlist, name) - { - m_logic_family = inout_proxied->logic_family(); - m_term_proxied = inout_proxied; - m_proxy_term = proxy_inout; - } + logic_t *inout_proxied, detail::core_terminal_t *proxy_inout); - virtual ~nld_base_proxy() {} + virtual ~nld_base_proxy(); logic_t &term_proxied() const { return *m_term_proxied; } detail::core_terminal_t &proxy_term() const { return *m_proxy_term; } @@ -65,18 +59,14 @@ namespace netlist { public: - virtual ~nld_base_a_to_d_proxy() {} + 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, - logic_input_t *in_proxied, detail::core_terminal_t *in_proxy) - : nld_base_proxy(anetlist, name, in_proxied, in_proxy) - , m_Q(*this, "Q") - { - } + logic_input_t *in_proxied, detail::core_terminal_t *in_proxy); private: @@ -87,36 +77,17 @@ 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) - : nld_base_a_to_d_proxy(anetlist, name, in_proxied, &m_I) - , m_I(*this, "I") - { - } + nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied); - virtual ~nld_a_to_d_proxy() {} + virtual ~nld_a_to_d_proxy(); analog_input_t m_I; protected: - NETLIB_RESETI() { } + NETLIB_RESETI(); + NETLIB_UPDATEI(); - NETLIB_UPDATEI() - { - nl_assert(m_logic_family != nullptr); - // FIXME: Variable supply voltage! - double supply_V = logic_family().fixed_V(); - if (supply_V == 0.0) supply_V = 5.0; - - if (m_I.Q_Analog() > logic_family().high_thresh_V(0.0, supply_V)) - out().push(1, NLTIME_FROM_NS(1)); - else if (m_I.Q_Analog() < logic_family().low_thresh_V(0.0, supply_V)) - out().push(0, NLTIME_FROM_NS(1)); - else - { - // do nothing - } - } private: }; @@ -127,17 +98,13 @@ namespace netlist NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy) { public: - virtual ~nld_base_d_to_a_proxy() {} + 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, - logic_output_t *out_proxied, detail::core_terminal_t &proxy_out) - : nld_base_proxy(anetlist, name, out_proxied, &proxy_out) - , m_I(*this, "I") - { - } + logic_output_t *out_proxied, detail::core_terminal_t &proxy_out); logic_input_t m_I; diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index aa6cfc5b340..ab643f1ee87 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -49,10 +49,24 @@ void object_t::operator delete (void * mem) } +nl_exception::~nl_exception() +{ +} + + // ---------------------------------------------------------------------------------------- // logic_family_ttl_t // ---------------------------------------------------------------------------------------- +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: @@ -761,6 +775,9 @@ logic_net_t::logic_net_t(netlist_t &nl, const pstring &aname, detail::core_termi { } +logic_net_t::~logic_net_t() +{ +} // ---------------------------------------------------------------------------------------- // analog_net_t @@ -772,6 +789,10 @@ analog_net_t::analog_net_t(netlist_t &nl, const pstring &aname, detail::core_ter { } +analog_net_t::~analog_net_t() +{ +} + // ---------------------------------------------------------------------------------------- // core_terminal_t // ---------------------------------------------------------------------------------------- @@ -785,6 +806,10 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam { } +detail::core_terminal_t::~core_terminal_t() +{ +} + void detail::core_terminal_t::reset() { if (is_type(OUTPUT)) @@ -803,6 +828,13 @@ void detail::core_terminal_t::set_net(net_t *anet) m_net = nullptr; } +analog_t::~analog_t() +{ +} + +logic_t::~logic_t() +{ +} // ---------------------------------------------------------------------------------------- // terminal_t @@ -854,6 +886,11 @@ logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname) netlist().setup().register_term(*this); } +logic_output_t::~logic_output_t() +{ +} + + void logic_output_t::initial(const netlist_sig_t val) { net().initial(val); @@ -883,6 +920,10 @@ analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname) netlist().setup().register_term(*this); } +analog_output_t::~analog_output_t() +{ +} + void analog_output_t::initial(const nl_double val) { net().m_cur_Analog = val; @@ -899,6 +940,10 @@ logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname) netlist().setup().register_term(*this); } +logic_input_t::~logic_input_t() +{ +} + // ---------------------------------------------------------------------------------------- // Parameters ... // ---------------------------------------------------------------------------------------- @@ -910,6 +955,10 @@ param_t::param_t(const param_type_t atype, device_t &device, const pstring &name device.setup().register_param(this->name(), *this); } +param_t::~param_t() +{ +} + void param_t::update_param() { device().update_param(); @@ -958,6 +1007,15 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val) //netlist().save(*this, m_param, "m_param"); } +void param_str_t::changed() +{ +} + +void param_model_t::changed() +{ + m_map.clear(); +} + const pstring param_model_t::model_value_str(const pstring &entity) { if (m_map.size() == 0) @@ -972,6 +1030,10 @@ nl_double param_model_t::model_value(const pstring &entity) return netlist().setup().model_value(m_map, entity); } +void param_data_t::changed() +{ +} + std::unique_ptr param_data_t::stream() { return device().netlist().setup().get_data_stream(Value()); diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index cfefc32bc41..e85a891aaaf 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -209,7 +209,7 @@ namespace netlist : plib::pexception(text) { } /*! Copy constructor. */ nl_exception(const nl_exception &e) : plib::pexception(e) { } - virtual ~nl_exception() {} + virtual ~nl_exception(); }; class logic_output_t; @@ -234,8 +234,8 @@ namespace netlist class logic_family_desc_t { public: - logic_family_desc_t() {} - virtual ~logic_family_desc_t() {} + logic_family_desc_t(); + virtual ~logic_family_desc_t(); virtual plib::owned_ptr create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const = 0; @@ -496,7 +496,7 @@ namespace netlist core_terminal_t(core_device_t &dev, const pstring &aname, const type_t type, const state_e state); - virtual ~core_terminal_t() { } + virtual ~core_terminal_t(); void set_net(net_t *anet); void clear_net(); @@ -532,6 +532,7 @@ namespace netlist : core_terminal_t(dev, aname, type, state) { } + virtual ~analog_t(); const analog_net_t & net() const NL_NOEXCEPT; analog_net_t & net() NL_NOEXCEPT; @@ -613,6 +614,7 @@ namespace netlist , m_proxy(nullptr) { } + virtual ~logic_t(); bool has_proxy() const { return (m_proxy != nullptr); } devices::nld_base_proxy *get_proxy() const { return m_proxy; } @@ -635,6 +637,7 @@ namespace netlist { public: logic_input_t(core_device_t &dev, const pstring &aname); + virtual ~logic_input_t(); netlist_sig_t Q() const NL_NOEXCEPT; @@ -750,7 +753,7 @@ namespace netlist public: logic_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr); - virtual ~logic_net_t() { } + virtual ~logic_net_t(); netlist_sig_t Q() const { return m_cur_Q; } netlist_sig_t new_Q() const { return m_new_Q; } @@ -794,7 +797,7 @@ namespace netlist analog_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr); - virtual ~analog_net_t() { } + virtual ~analog_net_t(); nl_double Q_Analog() const { return m_cur_Analog; } nl_double &Q_Analog_state_ptr() { return m_cur_Analog; } @@ -817,6 +820,7 @@ namespace netlist public: logic_output_t(core_device_t &dev, const pstring &aname); + virtual ~logic_output_t(); void initial(const netlist_sig_t val); @@ -834,6 +838,7 @@ namespace netlist P_PREVENT_COPYING(analog_output_t) 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); @@ -861,7 +866,7 @@ namespace netlist }; param_t(const param_type_t atype, device_t &device, const pstring &name); - virtual ~param_t() {} + virtual ~param_t(); param_type_t param_type() const { return m_param_type; } @@ -937,7 +942,7 @@ namespace netlist } } protected: - virtual void changed() { } + virtual void changed(); pstring Value() const { return m_param; } private: pstring m_param; @@ -954,7 +959,7 @@ namespace netlist const pstring model_value_str(const pstring &entity); const pstring model_type(); protected: - virtual void changed() override { m_map.clear(); } + virtual void changed() override; private: model_map_t m_map; }; @@ -966,7 +971,7 @@ namespace netlist : param_str_t(device, name, "") { } std::unique_ptr stream(); protected: - virtual void changed() override { } + virtual void changed() override; }; // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp index 1e5a8e11b44..33fc532331b 100644 --- a/src/lib/netlist/nl_factory.cpp +++ b/src/lib/netlist/nl_factory.cpp @@ -14,6 +14,18 @@ namespace netlist { namespace factory { + +element_t::element_t(const pstring &name, const pstring &classname, + const pstring &def_param) + : m_name(name), m_classname(classname), m_def_param(def_param) +{ +} + +element_t::~element_t() +{ +} + + // ---------------------------------------------------------------------------------------- // net_device_t_base_factory // ---------------------------------------------------------------------------------------- @@ -51,7 +63,7 @@ factory::element_t * list_t::factory_by_name(const pstring &devname) plib::owned_ptr library_element_t::Create(netlist_t &anetlist, const pstring &name) { - return plib::owned_ptr::Create(anetlist, name); + return plib::owned_ptr::Create(anetlist, name); } void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name) @@ -61,5 +73,13 @@ void library_element_t::macro_actions(netlist_t &anetlist, const pstring &name) anetlist.setup().namespace_pop(); } +NETLIB_RESET(wrapper) +{ +} + +NETLIB_UPDATE(wrapper) +{ +} + } } diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index a14ff71d5e1..0f4a1344e38 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -30,11 +30,8 @@ namespace netlist { namespace factory P_PREVENT_COPYING(element_t) public: element_t(const pstring &name, const pstring &classname, - const pstring &def_param) - : m_name(name), m_classname(classname), m_def_param(def_param) - {} - - virtual ~element_t() {} + const pstring &def_param); + virtual ~element_t(); virtual plib::owned_ptr Create(netlist_t &anetlist, const pstring &name) = 0; virtual void macro_actions(netlist_t &anetlist, const pstring &name) {} @@ -117,6 +114,18 @@ namespace netlist { namespace factory // factory_lib_entry_t: factory class to wrap macro based chips/elements // ----------------------------------------------------------------------------- + class NETLIB_NAME(wrapper) : public device_t + { + public: + NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name) + : device_t(anetlist, name) + { + } + protected: + NETLIB_RESETI(); + NETLIB_UPDATEI(); + }; + class library_element_t : public element_t { P_PREVENT_COPYING(library_element_t) @@ -126,18 +135,6 @@ namespace netlist { namespace factory const pstring &def_param) : element_t(name, classname, def_param), m_setup(setup) { } - class wrapper : public device_t - { - public: - wrapper(netlist_t &anetlist, const pstring &name) - : device_t(anetlist, name) - { - } - protected: - NETLIB_RESETI() { } - NETLIB_UPDATEI() { } - }; - plib::owned_ptr Create(netlist_t &anetlist, const pstring &name) override; void macro_actions(netlist_t &anetlist, const pstring &name) override; diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 038fd7ed978..39d85e5be1d 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -1080,4 +1080,22 @@ std::unique_ptr source_file_t::stream(const pstring &name) return plib::make_unique_base(m_filename); } +bool source_proc_t::parse(const pstring &name) +{ + if (name == m_setup_func_name) + { + m_setup_func(setup()); + return true; + } + else + return false; } + +std::unique_ptr source_proc_t::stream(const pstring &name) +{ + std::unique_ptr p(nullptr); + return p; +} + +} + diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 1edc3b50781..66745504c74 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -373,22 +373,9 @@ namespace netlist { } - virtual bool parse(const pstring &name) override - { - if (name == m_setup_func_name) - { - m_setup_func(setup()); - return true; - } - else - return false; - } + virtual bool parse(const pstring &name) override; + virtual std::unique_ptr stream(const pstring &name) override; - virtual std::unique_ptr stream(const pstring &name) override - { - std::unique_ptr p(nullptr); - return p; - } private: void (*m_setup_func)(setup_t &); pstring m_setup_func_name; diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp index 7d0adca22c5..2eedd6f9d16 100644 --- a/src/lib/netlist/plib/pexception.cpp +++ b/src/lib/netlist/plib/pexception.cpp @@ -26,41 +26,75 @@ 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)) { } -fpexception::fpexception(const pstring &text) +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) diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h index d3bccbd54ad..a4d3b3c498f 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -21,10 +21,10 @@ namespace plib { class pexception : public std::exception { public: - pexception(const pstring text); + explicit pexception(const pstring text); pexception(const pexception &e) : std::exception(e) { m_text = e.m_text; } - virtual ~pexception() noexcept {} + virtual ~pexception() noexcept; const pstring &text() { return m_text; } @@ -36,46 +36,60 @@ class file_e : public plib::pexception { public: explicit 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 : public pexception +class fpexception_e : public pexception { public: - fpexception(const pstring &text); + fpexception_e(const pstring &text); + fpexception_e(const fpexception_e &e) : pexception(e) { } + virtual ~fpexception_e() noexcept; }; static const unsigned FP_INEXACT = 0x0001; diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp index 73da6822d20..48b0f1544c1 100644 --- a/src/lib/netlist/plib/pfmtlog.cpp +++ b/src/lib/netlist/plib/pfmtlog.cpp @@ -17,6 +17,11 @@ #include "palloc.h" namespace plib { + +plog_dispatch_intf::~plog_dispatch_intf() +{ +} + pfmt::pfmt(const pstring &fmt) : m_str(m_str_buf), m_allocated(0), m_arg(0) { diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index 49f8ae62b44..c5369109b81 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -263,7 +263,7 @@ class plog_dispatch_intf template friend class plog_channel; public: - virtual ~plog_dispatch_intf() { } + virtual ~plog_dispatch_intf(); protected: virtual void vlog(const plog_level &l, const pstring &ls) const = 0; }; diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp index 2060e8ec46c..a14d4ae93e7 100644 --- a/src/lib/netlist/plib/poptions.cpp +++ b/src/lib/netlist/plib/poptions.cpp @@ -22,11 +22,23 @@ namespace plib { { } + option_group::~option_group() + { + } + + option_example::~option_example() + { + } + option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument) : option_base(parent, help), m_short(ashort), m_long(along), m_has_argument(has_argument) { } + option::~option() + { + } + int option_str::parse(pstring argument) { m_val = argument; diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index 3fac79b58ef..aa5ce07cbc8 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -39,6 +39,7 @@ class option_group : public option_base public: option_group(options &parent, pstring group, pstring help) : option_base(parent, help), m_group(group) { } + ~option_group(); pstring group() { return m_group; } private: @@ -50,6 +51,7 @@ class option_example : public option_base public: option_example(options &parent, pstring group, pstring help) : option_base(parent, help), m_example(group) { } + ~option_example(); pstring example() { return m_example; } private: @@ -61,6 +63,7 @@ class option : public option_base { public: option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument); + ~option(); /* no_argument options will be called with "" argument */ diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp index 0a19685316d..35629aacdee 100644 --- a/src/lib/netlist/plib/pparser.cpp +++ b/src/lib/netlist/plib/pparser.cpp @@ -15,6 +15,16 @@ namespace plib { // A simple tokenizer // ---------------------------------------------------------------------------------------- +ptokenizer::ptokenizer(pistream &strm) +: m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"') +{ +} + +ptokenizer::~ptokenizer() +{ +} + + pstring ptokenizer::currentline_str() { return m_cur_line; diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h index 301a4fc30a2..db88299d85c 100644 --- a/src/lib/netlist/plib/pparser.h +++ b/src/lib/netlist/plib/pparser.h @@ -22,11 +22,9 @@ class ptokenizer { P_PREVENT_COPYING(ptokenizer) public: - virtual ~ptokenizer() {} + explicit ptokenizer(pistream &strm); - explicit ptokenizer(pistream &strm) - : m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"') - {} + virtual ~ptokenizer(); enum token_type { diff --git a/src/lib/netlist/plib/pstate.cpp b/src/lib/netlist/plib/pstate.cpp index ddfe0a37bc8..91869c26ba7 100644 --- a/src/lib/netlist/plib/pstate.cpp +++ b/src/lib/netlist/plib/pstate.cpp @@ -60,4 +60,9 @@ template<> void state_manager_t::save_item(const void *owner, callback_t &state, state.register_state(*this, stname); } +state_manager_t::callback_t::~callback_t() +{ +} + + } diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h index cd6c8efe38b..48420825164 100644 --- a/src/lib/netlist/plib/pstate.h +++ b/src/lib/netlist/plib/pstate.h @@ -62,7 +62,7 @@ public: public: using list_t = std::vector; - virtual ~callback_t() { } + virtual ~callback_t(); virtual void register_state(state_manager_t &manager, const pstring &module) = 0; virtual void on_pre_save() = 0; diff --git a/src/lib/netlist/plib/pstream.cpp b/src/lib/netlist/plib/pstream.cpp index b9895036a12..b05d86d7bc5 100644 --- a/src/lib/netlist/plib/pstream.cpp +++ b/src/lib/netlist/plib/pstream.cpp @@ -14,10 +14,19 @@ #include "palloc.h" namespace plib { + +pstream::~pstream() +{ +} + // ----------------------------------------------------------------------------- // pistream: input stream // ----------------------------------------------------------------------------- +pistream::~pistream() +{ +} + bool pistream::readline(pstring &line) { char c = 0; @@ -44,6 +53,10 @@ bool pistream::readline(pstring &line) // postream: output stream // ----------------------------------------------------------------------------- +postream::~postream() +{ +} + void postream::write(pistream &strm) { char buf[1024]; @@ -142,6 +155,10 @@ pstdin::pstdin() /* nothing to do */ } +pstdin::~pstdin() +{ +} + // ----------------------------------------------------------------------------- // Output file stream // ----------------------------------------------------------------------------- @@ -209,6 +226,11 @@ pstream::pos_type pofilestream::vtell() return static_cast(ret); } +postringstream::~postringstream() +{ +} + + // ----------------------------------------------------------------------------- // pstderr: write to stderr // ----------------------------------------------------------------------------- @@ -218,6 +240,10 @@ pstderr::pstderr() { } +pstderr::~pstderr() +{ +} + // ----------------------------------------------------------------------------- // pstdout: write to stdout // ----------------------------------------------------------------------------- @@ -227,6 +253,10 @@ pstdout::pstdout() { } +pstdout::~pstdout() +{ +} + // ----------------------------------------------------------------------------- // Memory stream // ----------------------------------------------------------------------------- @@ -273,6 +303,10 @@ pimemstream::pos_type pimemstream::vtell() return m_pos; } +pistringstream::~pistringstream() +{ +} + // ----------------------------------------------------------------------------- // Output memory stream // ----------------------------------------------------------------------------- @@ -333,4 +367,9 @@ pstream::pos_type pomemstream::vtell() return m_pos; } +pstream_fmt_writer_t::~pstream_fmt_writer_t() +{ +} + + } diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index 11bf0fb12cf..6d02c4d1551 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -32,9 +32,7 @@ public: explicit pstream(const unsigned flags) : m_flags(flags) { } - virtual ~pstream() - { - } + virtual ~pstream(); bool seekable() const { return ((m_flags & FLAG_SEEKABLE) != 0); } @@ -79,7 +77,7 @@ class pistream : public pstream public: explicit pistream(const unsigned flags) : pstream(flags) {} - virtual ~pistream() {} + virtual ~pistream(); bool eof() const { return ((flags() & FLAG_EOF) != 0); } @@ -115,7 +113,7 @@ class postream : public pstream public: explicit postream(unsigned flags) : pstream(flags) {} - virtual ~postream() {} + virtual ~postream(); /* this digests linux & dos/windows text files */ @@ -184,7 +182,7 @@ class postringstream : public postream public: postringstream() : postream(0) { } - virtual ~postringstream() { } + virtual ~postringstream(); const pstringbuffer &str() { return m_buf; } @@ -238,6 +236,7 @@ class pstderr : public pofilestream P_PREVENT_COPYING(pstderr) public: pstderr(); + virtual ~pstderr(); }; // ----------------------------------------------------------------------------- @@ -249,6 +248,7 @@ class pstdout : public pofilestream P_PREVENT_COPYING(pstdout) public: pstdout(); + virtual ~pstdout(); }; // ----------------------------------------------------------------------------- @@ -290,6 +290,7 @@ class pstdin : public pifilestream public: pstdin(); + virtual ~pstdin(); }; // ----------------------------------------------------------------------------- @@ -325,8 +326,8 @@ class pistringstream : public pimemstream { P_PREVENT_COPYING(pistringstream) public: - pistringstream(const pstring &str) : pimemstream(str.c_str(), str.len()), m_str(str) { } + virtual ~pistringstream(); private: /* only needed for a reference till destruction */ @@ -343,7 +344,7 @@ class pstream_fmt_writer_t : public plib::pfmt_writer_t<> public: explicit pstream_fmt_writer_t(postream &strm) : m_strm(strm) {} - virtual ~pstream_fmt_writer_t() { } + virtual ~pstream_fmt_writer_t(); protected: virtual void vdowrite(const pstring &ls) const override diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 60189bfb0cc..f96fd423530 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -102,25 +102,26 @@ public: { } - virtual std::unique_ptr stream(const pstring &file) override - { - pstring name = m_folder + "/" + file; - try - { - auto strm = plib::make_unique_base(name); - return strm; - } - catch (plib::pexception e) - { - - } - return std::unique_ptr(nullptr); - } + virtual std::unique_ptr stream(const pstring &file) override; private: pstring m_folder; }; +std::unique_ptr netlist_data_folder_t::stream(const pstring &file) +{ + pstring name = m_folder + "/" + file; + try + { + auto strm = plib::make_unique_base(name); + return strm; + } + catch (plib::pexception e) + { + + } + return std::unique_ptr(nullptr); +} class netlist_tool_t : public netlist::netlist_t { @@ -182,18 +183,20 @@ public: protected: - void vlog(const plib::plog_level &l, const pstring &ls) const override - { - pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str()); - pout("{}", err); - if (l == plib::plog_level::FATAL) - throw netlist::nl_exception(err); - } + void vlog(const plib::plog_level &l, const pstring &ls) const override; private: netlist::setup_t *m_setup; }; +void netlist_tool_t::vlog(const plib::plog_level &l, const pstring &ls) const +{ + pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str()); + pout("{}", err); + if (l == plib::plog_level::FATAL) + throw netlist::nl_exception(err); +} + // FIXME: usage should go elsewhere void usage(tool_options_t &opts); diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp new file mode 100644 index 00000000000..d6032e65912 --- /dev/null +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -0,0 +1,562 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nld_matrix_solver.cpp + * + */ + +#include "nld_matrix_solver.h" +#include "plib/putil.h" + +namespace netlist +{ + namespace devices + { + +proxied_analog_output_t::~proxied_analog_output_t() +{ +} + +terms_t::terms_t() + : m_railstart(0) + , m_last_V(0.0) + , m_DD_n_m_1(0.0) + , m_h_n_m_1(1e-9) +{ +} + +void terms_t::clear() +{ + m_term.clear(); + m_net_other.clear(); + m_gt.clear(); + m_go.clear(); + m_Idr.clear(); + m_other_curanalog.clear(); +} + +void terms_t::add(terminal_t *term, int net_other, bool sorted) +{ + if (sorted) + for (unsigned i=0; i < m_net_other.size(); i++) + { + if (m_net_other[i] > net_other) + { + plib::container::insert_at(m_term, i, term); + plib::container::insert_at(m_net_other, i, net_other); + plib::container::insert_at(m_gt, i, 0.0); + plib::container::insert_at(m_go, i, 0.0); + plib::container::insert_at(m_Idr, i, 0.0); + plib::container::insert_at(m_other_curanalog, i, nullptr); + return; + } + } + m_term.push_back(term); + m_net_other.push_back(net_other); + m_gt.push_back(0.0); + m_go.push_back(0.0); + m_Idr.push_back(0.0); + m_other_curanalog.push_back(nullptr); +} + +void terms_t::set_pointers() +{ + for (unsigned i = 0; i < count(); i++) + { + m_term[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]); + m_other_curanalog[i] = m_term[i]->m_otherterm->net().m_cur_Analog.ptr(); + } +} + +// ---------------------------------------------------------------------------------------- +// matrix_solver +// ---------------------------------------------------------------------------------------- + +matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name, + const eSortType sort, const solver_parameters_t *params) + : device_t(anetlist, name) + , m_params(*params) + , m_stat_calculations(*this, "m_stat_calculations", 0) + , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0) + , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0) + , m_iterative_fail(*this, "m_iterative_fail", 0) + , m_iterative_total(*this, "m_iterative_total", 0) + , m_last_step(*this, "m_last_step", netlist_time::zero()) + , m_fb_sync(*this, "FB_sync") + , m_Q_sync(*this, "Q_sync") + , m_sort(sort) +{ + connect_post_start(m_fb_sync, m_Q_sync); +} + +matrix_solver_t::~matrix_solver_t() +{ + for (unsigned k = 0; k < m_terms.size(); k++) + { + plib::pfree(m_terms[k]); + } + +} + +void matrix_solver_t::setup_base(analog_net_t::list_t &nets) +{ + log().debug("New solver setup\n"); + + m_nets.clear(); + m_terms.clear(); + + for (auto & net : nets) + { + m_nets.push_back(net); + m_terms.push_back(plib::palloc()); + m_rails_temp.push_back(plib::palloc()); + } + + for (std::size_t k = 0; k < nets.size(); k++) + { + analog_net_t *net = nets[k]; + + log().debug("setting up net\n"); + + net->set_solver(this); + + for (auto &p : net->m_core_terms) + { + log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet()); + switch (p->type()) + { + case terminal_t::TERMINAL: + if (p->device().is_timestep()) + if (!plib::container::contains(m_step_devices, &p->device())) + m_step_devices.push_back(&p->device()); + if (p->device().is_dynamic()) + if (!plib::container::contains(m_dynamic_devices, &p->device())) + m_dynamic_devices.push_back(&p->device()); + { + terminal_t *pterm = dynamic_cast(p); + add_term(k, pterm); + } + log().debug("Added terminal {1}\n", p->name()); + break; + case terminal_t::INPUT: + { + proxied_analog_output_t *net_proxy_output = nullptr; + for (auto & input : m_inps) + if (input->m_proxied_net == &p->net()) + { + net_proxy_output = input.get(); + break; + } + + if (net_proxy_output == nullptr) + { + auto net_proxy_output_u = plib::make_unique(*this, this->name() + "." + plib::pfmt("m{1}")(m_inps.size())); + net_proxy_output = net_proxy_output_u.get(); + m_inps.push_back(std::move(net_proxy_output_u)); + nl_assert(p->net().is_analog()); + net_proxy_output->m_proxied_net = static_cast(&p->net()); + } + net_proxy_output->net().add_terminal(*p); + // FIXME: repeated + net_proxy_output->net().rebuild_list(); + log().debug("Added input\n"); + } + break; + case terminal_t::OUTPUT: + case terminal_t::PARAM: + log().fatal("unhandled element found\n"); + break; + } + } + log().debug("added net with {1} populated connections\n", net->m_core_terms.size()); + } + + /* now setup the matrix */ + setup_matrix(); +} + +void matrix_solver_t::setup_matrix() +{ + const std::size_t iN = m_nets.size(); + + for (std::size_t k = 0; k < iN; k++) + { + m_terms[k]->m_railstart = m_terms[k]->count(); + for (std::size_t i = 0; i < m_rails_temp[k]->count(); i++) + this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false); + + m_rails_temp[k]->clear(); // no longer needed + m_terms[k]->set_pointers(); + } + + for (unsigned k = 0; k < iN; k++) + plib::pfree(m_rails_temp[k]); // no longer needed + + m_rails_temp.clear(); + + /* Sort in descending order by number of connected matrix voltages. + * The idea is, that for Gauss-Seidel algo the first voltage computed + * depends on the greatest number of previous voltages thus taking into + * account the maximum amout of information. + * + * This actually improves performance on popeye slightly. Average + * GS computations reduce from 2.509 to 2.370 + * + * Smallest to largest : 2.613 + * Unsorted : 2.509 + * Largest to smallest : 2.370 + * + * Sorting as a general matrix pre-conditioning is mentioned in + * literature but I have found no articles about Gauss Seidel. + * + * For Gaussian Elimination however increasing order is better suited. + * FIXME: Even better would be to sort on elements right of the matrix diagonal. + * + */ + + if (m_sort != NOSORT) + { + int sort_order = (m_sort == DESCENDING ? 1 : -1); + + for (unsigned k = 0; k < iN - 1; k++) + for (unsigned i = k+1; i < iN; i++) + { + if ((static_cast(m_terms[k]->m_railstart) - static_cast(m_terms[i]->m_railstart)) * sort_order < 0) + { + std::swap(m_terms[i], m_terms[k]); + std::swap(m_nets[i], m_nets[k]); + } + } + + for (unsigned k = 0; k < iN; k++) + { + int *other = m_terms[k]->net_other(); + for (unsigned i = 0; i < m_terms[k]->count(); i++) + if (other[i] != -1) + other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net()); + } + } + + /* create a list of non zero elements. */ + for (unsigned k = 0; k < iN; k++) + { + terms_t * t = m_terms[k]; + /* pretty brutal */ + int *other = t->net_other(); + + t->m_nz.clear(); + + for (unsigned i = 0; i < t->m_railstart; i++) + if (!plib::container::contains(t->m_nz, static_cast(other[i]))) + t->m_nz.push_back(static_cast(other[i])); + + t->m_nz.push_back(k); // add diagonal + + /* and sort */ + std::sort(t->m_nz.begin(), t->m_nz.end()); + } + + /* create a list of non zero elements right of the diagonal + * These list anticipate the population of array elements by + * Gaussian elimination. + */ + for (unsigned k = 0; k < iN; k++) + { + terms_t * t = m_terms[k]; + /* pretty brutal */ + int *other = t->net_other(); + + if (k==0) + t->m_nzrd.clear(); + else + { + t->m_nzrd = m_terms[k-1]->m_nzrd; + for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); ) + { + if (*j < k + 1) + j = t->m_nzrd.erase(j); + else + ++j; + } + } + + for (unsigned i = 0; i < t->m_railstart; i++) + if (!plib::container::contains(t->m_nzrd, static_cast(other[i])) && other[i] >= static_cast(k + 1)) + t->m_nzrd.push_back(static_cast(other[i])); + + /* and sort */ + std::sort(t->m_nzrd.begin(), t->m_nzrd.end()); + } + + /* create a list of non zero elements below diagonal k + * This should reduce cache misses ... + */ + + bool **touched = new bool*[iN]; + for (unsigned k=0; km_nz.size(); j++) + touched[k][m_terms[k]->m_nz[j]] = true; + } + + unsigned ops = 0; + for (unsigned k = 0; k < iN; k++) + { + ops++; // 1/A(k,k) + for (unsigned row = k + 1; row < iN; row++) + { + if (touched[row][k]) + { + ops++; + if (!plib::container::contains(m_terms[k]->m_nzbd, row)) + m_terms[k]->m_nzbd.push_back(row); + for (unsigned col = k + 1; col < iN; col++) + if (touched[k][col]) + { + touched[row][col] = true; + ops += 2; + } + } + } + } + log().verbose("Number of mults/adds for {1}: {2}", name(), ops); + + if ((0)) + for (unsigned k = 0; k < iN; k++) + { + pstring line = plib::pfmt("{1}")(k, "3"); + for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++) + line += plib::pfmt(" {1}")(m_terms[k]->m_nzrd[j], "3"); + log().verbose("{1}", line); + } + + /* + * save states + */ + for (unsigned k = 0; k < iN; k++) + { + pstring num = plib::pfmt("{1}")(k); + + netlist().save(*this, m_terms[k]->m_last_V, "lastV." + num); + netlist().save(*this, m_terms[k]->m_DD_n_m_1, "m_DD_n_m_1." + num); + netlist().save(*this, m_terms[k]->m_h_n_m_1, "m_h_n_m_1." + num); + + netlist().save(*this, m_terms[k]->go(),"GO" + num, m_terms[k]->count()); + netlist().save(*this, m_terms[k]->gt(),"GT" + num, m_terms[k]->count()); + netlist().save(*this, m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count()); + } + + for (unsigned k=0; kpush(inp->m_proxied_net->Q_Analog()); +} + +void matrix_solver_t::update_dynamic() +{ + /* update all non-linear devices */ + for (auto &dyn : m_dynamic_devices) + dyn->update_terminals(); +} + +void matrix_solver_t::reset() +{ + m_last_step = netlist_time::zero(); +} + +void matrix_solver_t::update() NL_NOEXCEPT +{ + const netlist_time new_timestep = solve(); + + if (m_params.m_dynamic && has_timestep_devices() && new_timestep > netlist_time::zero()) + { + m_Q_sync.net().force_queue_execution(); + m_Q_sync.net().reschedule_in_queue(new_timestep); + } +} + +void matrix_solver_t::update_forced() +{ + ATTR_UNUSED const netlist_time new_timestep = solve(); + + if (m_params.m_dynamic && has_timestep_devices()) + { + m_Q_sync.net().force_queue_execution(); + m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep)); + } +} + +void matrix_solver_t::step(const netlist_time &delta) +{ + const nl_double dd = delta.as_double(); + for (std::size_t k=0; k < m_step_devices.size(); k++) + m_step_devices[k]->timestep(dd); +} + +void matrix_solver_t::solve_base() +{ + m_stat_vsolver_calls++; + if (has_dynamic_devices()) + { + unsigned this_resched; + unsigned newton_loops = 0; + do + { + update_dynamic(); + // Gauss-Seidel will revert to Gaussian elemination if steps exceeded. + this_resched = this->vsolve_non_dynamic(true); + newton_loops++; + } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); + + m_stat_newton_raphson += newton_loops; + // reschedule .... + if (this_resched > 1 && !m_Q_sync.net().is_queued()) + { + log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name()); + m_Q_sync.net().toggle_new_Q(); + m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay); + } + } + else + { + this->vsolve_non_dynamic(false); + } +} + +const netlist_time matrix_solver_t::solve() +{ + const netlist_time now = netlist().time(); + const netlist_time delta = now - m_last_step; + + // We are already up to date. Avoid oscillations. + // FIXME: Make this a parameter! + if (delta < netlist_time::quantum()) + return netlist_time::zero(); + + /* update all terminals for new time step */ + m_last_step = now; + step(delta); + solve_base(); + const netlist_time next_time_step = compute_next_timestep(delta.as_double()); + + update_inputs(); + + return next_time_step; +} + +int matrix_solver_t::get_net_idx(detail::net_t *net) +{ + for (std::size_t k = 0; k < m_nets.size(); k++) + if (m_nets[k] == net) + return static_cast(k); + return -1; +} + +void matrix_solver_t::add_term(std::size_t k, terminal_t *term) +{ + if (term->m_otherterm->net().isRailNet()) + { + m_rails_temp[k]->add(term, -1, false); + } + else + { + int ot = get_net_idx(&term->m_otherterm->net()); + if (ot>=0) + { + m_terms[k]->add(term, ot, true); + } + /* Should this be allowed ? */ + else // if (ot<0) + { + m_rails_temp[k]->add(term, ot, true); + log().fatal("found term with missing othernet {1}\n", term->name()); + } + } +} + +netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts) +{ + nl_double new_solver_timestep = m_params.m_max_timestep; + + if (m_params.m_dynamic) + { + /* + * FIXME: We should extend the logic to use either all nets or + * only output nets. + */ + for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++) + { + analog_net_t *n = m_nets[k]; + terms_t *t = m_terms[k]; + + const nl_double DD_n = (n->Q_Analog() - t->m_last_V); + const nl_double hn = cur_ts; + + //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1); + nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1); + nl_double new_net_timestep; + + t->m_h_n_m_1 = hn; + t->m_DD_n_m_1 = DD_n; + if (std::fabs(DD2) > NL_FCONST(1e-60)) // avoid div-by-zero + new_net_timestep = std::sqrt(m_params.m_lte / std::fabs(NL_FCONST(0.5)*DD2)); + else + new_net_timestep = m_params.m_max_timestep; + + if (new_net_timestep < new_solver_timestep) + new_solver_timestep = new_net_timestep; + + t->m_last_V = n->Q_Analog(); + } + if (new_solver_timestep < m_params.m_min_timestep) + { + //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6); + new_solver_timestep = m_params.m_min_timestep; + } + } + //if (new_solver_timestep > 10.0 * hn) + // new_solver_timestep = 10.0 * hn; + /* + * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere. + */ + return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2); +} + + + +void matrix_solver_t::log_stats() +{ + if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats) + { + log().verbose("=============================================="); + log().verbose("Solver {1}", this->name()); + log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name()); + log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic"); + log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep"); + log().verbose(" {1:6.3} average newton raphson loops", + static_cast(this->m_stat_newton_raphson) / static_cast(this->m_stat_vsolver_calls)); + log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average", + this->m_stat_calculations(), + static_cast(this->m_stat_calculations()) / this->netlist().time().as_double(), + this->m_iterative_fail(), + 100.0 * static_cast(this->m_iterative_fail()) + / static_cast(this->m_stat_calculations()), + static_cast(this->m_iterative_total()) / static_cast(this->m_stat_calculations())); + } +} + + + } //namespace devices +} // namespace netlist + diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index f1473ce5931..aa3f7e86bfa 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -41,22 +41,9 @@ class terms_t P_PREVENT_COPYING(terms_t) public: - terms_t() - : m_railstart(0) - , m_last_V(0.0) - , m_DD_n_m_1(0.0) - , m_h_n_m_1(1e-9) - {} + terms_t(); - void clear() - { - m_term.clear(); - m_net_other.clear(); - m_gt.clear(); - m_go.clear(); - m_Idr.clear(); - m_other_curanalog.clear(); - } + void clear(); void add(terminal_t *term, int net_other, bool sorted); @@ -100,6 +87,7 @@ public: : analog_output_t(dev, aname) , m_proxied_net(nullptr) { } + virtual ~proxied_analog_output_t(); analog_net_t *m_proxied_net; // only for proxy nets in analog input logic }; @@ -118,21 +106,7 @@ public: }; matrix_solver_t(netlist_t &anetlist, const pstring &name, - const eSortType sort, const solver_parameters_t *params) - : device_t(anetlist, name) - , m_params(*params) - , m_stat_calculations(*this, "m_stat_calculations", 0) - , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0) - , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0) - , m_iterative_fail(*this, "m_iterative_fail", 0) - , m_iterative_total(*this, "m_iterative_total", 0) - , m_last_step(*this, "m_last_step", netlist_time::zero()) - , m_fb_sync(*this, "FB_sync") - , m_Q_sync(*this, "Q_sync") - , m_sort(sort) - { - connect_post_start(m_fb_sync, m_Q_sync); - } + const eSortType sort, const solver_parameters_t *params); virtual ~matrix_solver_t(); diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index b0c70ebbde4..25b32401620 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -59,509 +59,7 @@ namespace netlist { namespace devices { -void terms_t::add(terminal_t *term, int net_other, bool sorted) -{ - if (sorted) - for (unsigned i=0; i < m_net_other.size(); i++) - { - if (m_net_other[i] > net_other) - { - plib::container::insert_at(m_term, i, term); - plib::container::insert_at(m_net_other, i, net_other); - plib::container::insert_at(m_gt, i, 0.0); - plib::container::insert_at(m_go, i, 0.0); - plib::container::insert_at(m_Idr, i, 0.0); - plib::container::insert_at(m_other_curanalog, i, nullptr); - return; - } - } - m_term.push_back(term); - m_net_other.push_back(net_other); - m_gt.push_back(0.0); - m_go.push_back(0.0); - m_Idr.push_back(0.0); - m_other_curanalog.push_back(nullptr); -} -void terms_t::set_pointers() -{ - for (unsigned i = 0; i < count(); i++) - { - m_term[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]); - m_other_curanalog[i] = m_term[i]->m_otherterm->net().m_cur_Analog.ptr(); - } -} - -// ---------------------------------------------------------------------------------------- -// matrix_solver -// ---------------------------------------------------------------------------------------- - -matrix_solver_t::~matrix_solver_t() -{ - for (unsigned k = 0; k < m_terms.size(); k++) - { - plib::pfree(m_terms[k]); - } - -} - -void matrix_solver_t::setup_base(analog_net_t::list_t &nets) -{ - log().debug("New solver setup\n"); - - m_nets.clear(); - m_terms.clear(); - - for (auto & net : nets) - { - m_nets.push_back(net); - m_terms.push_back(plib::palloc()); - m_rails_temp.push_back(plib::palloc()); - } - - for (std::size_t k = 0; k < nets.size(); k++) - { - analog_net_t *net = nets[k]; - - log().debug("setting up net\n"); - - net->set_solver(this); - - for (auto &p : net->m_core_terms) - { - log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet()); - switch (p->type()) - { - case terminal_t::TERMINAL: - if (p->device().is_timestep()) - if (!plib::container::contains(m_step_devices, &p->device())) - m_step_devices.push_back(&p->device()); - if (p->device().is_dynamic()) - if (!plib::container::contains(m_dynamic_devices, &p->device())) - m_dynamic_devices.push_back(&p->device()); - { - terminal_t *pterm = dynamic_cast(p); - add_term(k, pterm); - } - log().debug("Added terminal {1}\n", p->name()); - break; - case terminal_t::INPUT: - { - proxied_analog_output_t *net_proxy_output = nullptr; - for (auto & input : m_inps) - if (input->m_proxied_net == &p->net()) - { - net_proxy_output = input.get(); - break; - } - - if (net_proxy_output == nullptr) - { - auto net_proxy_output_u = plib::make_unique(*this, this->name() + "." + plib::pfmt("m{1}")(m_inps.size())); - net_proxy_output = net_proxy_output_u.get(); - m_inps.push_back(std::move(net_proxy_output_u)); - nl_assert(p->net().is_analog()); - net_proxy_output->m_proxied_net = static_cast(&p->net()); - } - net_proxy_output->net().add_terminal(*p); - // FIXME: repeated - net_proxy_output->net().rebuild_list(); - log().debug("Added input\n"); - } - break; - case terminal_t::OUTPUT: - case terminal_t::PARAM: - log().fatal("unhandled element found\n"); - break; - } - } - log().debug("added net with {1} populated connections\n", net->m_core_terms.size()); - } - - /* now setup the matrix */ - setup_matrix(); -} - -void matrix_solver_t::setup_matrix() -{ - const std::size_t iN = m_nets.size(); - - for (std::size_t k = 0; k < iN; k++) - { - m_terms[k]->m_railstart = m_terms[k]->count(); - for (std::size_t i = 0; i < m_rails_temp[k]->count(); i++) - this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false); - - m_rails_temp[k]->clear(); // no longer needed - m_terms[k]->set_pointers(); - } - - for (unsigned k = 0; k < iN; k++) - plib::pfree(m_rails_temp[k]); // no longer needed - - m_rails_temp.clear(); - - /* Sort in descending order by number of connected matrix voltages. - * The idea is, that for Gauss-Seidel algo the first voltage computed - * depends on the greatest number of previous voltages thus taking into - * account the maximum amout of information. - * - * This actually improves performance on popeye slightly. Average - * GS computations reduce from 2.509 to 2.370 - * - * Smallest to largest : 2.613 - * Unsorted : 2.509 - * Largest to smallest : 2.370 - * - * Sorting as a general matrix pre-conditioning is mentioned in - * literature but I have found no articles about Gauss Seidel. - * - * For Gaussian Elimination however increasing order is better suited. - * FIXME: Even better would be to sort on elements right of the matrix diagonal. - * - */ - - if (m_sort != NOSORT) - { - int sort_order = (m_sort == DESCENDING ? 1 : -1); - - for (unsigned k = 0; k < iN - 1; k++) - for (unsigned i = k+1; i < iN; i++) - { - if ((static_cast(m_terms[k]->m_railstart) - static_cast(m_terms[i]->m_railstart)) * sort_order < 0) - { - std::swap(m_terms[i], m_terms[k]); - std::swap(m_nets[i], m_nets[k]); - } - } - - for (unsigned k = 0; k < iN; k++) - { - int *other = m_terms[k]->net_other(); - for (unsigned i = 0; i < m_terms[k]->count(); i++) - if (other[i] != -1) - other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net()); - } - } - - /* create a list of non zero elements. */ - for (unsigned k = 0; k < iN; k++) - { - terms_t * t = m_terms[k]; - /* pretty brutal */ - int *other = t->net_other(); - - t->m_nz.clear(); - - for (unsigned i = 0; i < t->m_railstart; i++) - if (!plib::container::contains(t->m_nz, static_cast(other[i]))) - t->m_nz.push_back(static_cast(other[i])); - - t->m_nz.push_back(k); // add diagonal - - /* and sort */ - std::sort(t->m_nz.begin(), t->m_nz.end()); - } - - /* create a list of non zero elements right of the diagonal - * These list anticipate the population of array elements by - * Gaussian elimination. - */ - for (unsigned k = 0; k < iN; k++) - { - terms_t * t = m_terms[k]; - /* pretty brutal */ - int *other = t->net_other(); - - if (k==0) - t->m_nzrd.clear(); - else - { - t->m_nzrd = m_terms[k-1]->m_nzrd; - for (auto j = t->m_nzrd.begin(); j != t->m_nzrd.end(); ) - { - if (*j < k + 1) - j = t->m_nzrd.erase(j); - else - ++j; - } - } - - for (unsigned i = 0; i < t->m_railstart; i++) - if (!plib::container::contains(t->m_nzrd, static_cast(other[i])) && other[i] >= static_cast(k + 1)) - t->m_nzrd.push_back(static_cast(other[i])); - - /* and sort */ - std::sort(t->m_nzrd.begin(), t->m_nzrd.end()); - } - - /* create a list of non zero elements below diagonal k - * This should reduce cache misses ... - */ - - bool **touched = new bool*[iN]; - for (unsigned k=0; km_nz.size(); j++) - touched[k][m_terms[k]->m_nz[j]] = true; - } - - unsigned ops = 0; - for (unsigned k = 0; k < iN; k++) - { - ops++; // 1/A(k,k) - for (unsigned row = k + 1; row < iN; row++) - { - if (touched[row][k]) - { - ops++; - if (!plib::container::contains(m_terms[k]->m_nzbd, row)) - m_terms[k]->m_nzbd.push_back(row); - for (unsigned col = k + 1; col < iN; col++) - if (touched[k][col]) - { - touched[row][col] = true; - ops += 2; - } - } - } - } - log().verbose("Number of mults/adds for {1}: {2}", name(), ops); - - if ((0)) - for (unsigned k = 0; k < iN; k++) - { - pstring line = plib::pfmt("{1}")(k, "3"); - for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++) - line += plib::pfmt(" {1}")(m_terms[k]->m_nzrd[j], "3"); - log().verbose("{1}", line); - } - - /* - * save states - */ - for (unsigned k = 0; k < iN; k++) - { - pstring num = plib::pfmt("{1}")(k); - - netlist().save(*this, m_terms[k]->m_last_V, "lastV." + num); - netlist().save(*this, m_terms[k]->m_DD_n_m_1, "m_DD_n_m_1." + num); - netlist().save(*this, m_terms[k]->m_h_n_m_1, "m_h_n_m_1." + num); - - netlist().save(*this, m_terms[k]->go(),"GO" + num, m_terms[k]->count()); - netlist().save(*this, m_terms[k]->gt(),"GT" + num, m_terms[k]->count()); - netlist().save(*this, m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count()); - } - - for (unsigned k=0; kpush(inp->m_proxied_net->Q_Analog()); -} - -void matrix_solver_t::update_dynamic() -{ - /* update all non-linear devices */ - for (auto &dyn : m_dynamic_devices) - dyn->update_terminals(); -} - -void matrix_solver_t::reset() -{ - m_last_step = netlist_time::zero(); -} - -void matrix_solver_t::update() NL_NOEXCEPT -{ - const netlist_time new_timestep = solve(); - - if (m_params.m_dynamic && has_timestep_devices() && new_timestep > netlist_time::zero()) - { - m_Q_sync.net().force_queue_execution(); - m_Q_sync.net().reschedule_in_queue(new_timestep); - } -} - -void matrix_solver_t::update_forced() -{ - ATTR_UNUSED const netlist_time new_timestep = solve(); - - if (m_params.m_dynamic && has_timestep_devices()) - { - m_Q_sync.net().force_queue_execution(); - m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep)); - } -} - -void matrix_solver_t::step(const netlist_time &delta) -{ - const nl_double dd = delta.as_double(); - for (std::size_t k=0; k < m_step_devices.size(); k++) - m_step_devices[k]->timestep(dd); -} - -void matrix_solver_t::solve_base() -{ - m_stat_vsolver_calls++; - if (has_dynamic_devices()) - { - unsigned this_resched; - unsigned newton_loops = 0; - do - { - update_dynamic(); - // Gauss-Seidel will revert to Gaussian elemination if steps exceeded. - this_resched = this->vsolve_non_dynamic(true); - newton_loops++; - } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); - - m_stat_newton_raphson += newton_loops; - // reschedule .... - if (this_resched > 1 && !m_Q_sync.net().is_queued()) - { - log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name()); - m_Q_sync.net().toggle_new_Q(); - m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay); - } - } - else - { - this->vsolve_non_dynamic(false); - } -} - -const netlist_time matrix_solver_t::solve() -{ - const netlist_time now = netlist().time(); - const netlist_time delta = now - m_last_step; - - // We are already up to date. Avoid oscillations. - // FIXME: Make this a parameter! - if (delta < netlist_time::quantum()) - return netlist_time::zero(); - - /* update all terminals for new time step */ - m_last_step = now; - step(delta); - solve_base(); - const netlist_time next_time_step = compute_next_timestep(delta.as_double()); - - update_inputs(); - - return next_time_step; -} - -int matrix_solver_t::get_net_idx(detail::net_t *net) -{ - for (std::size_t k = 0; k < m_nets.size(); k++) - if (m_nets[k] == net) - return static_cast(k); - return -1; -} - -void matrix_solver_t::add_term(std::size_t k, terminal_t *term) -{ - if (term->m_otherterm->net().isRailNet()) - { - m_rails_temp[k]->add(term, -1, false); - } - else - { - int ot = get_net_idx(&term->m_otherterm->net()); - if (ot>=0) - { - m_terms[k]->add(term, ot, true); - } - /* Should this be allowed ? */ - else // if (ot<0) - { - m_rails_temp[k]->add(term, ot, true); - log().fatal("found term with missing othernet {1}\n", term->name()); - } - } -} - -netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts) -{ - nl_double new_solver_timestep = m_params.m_max_timestep; - - if (m_params.m_dynamic) - { - /* - * FIXME: We should extend the logic to use either all nets or - * only output nets. - */ - for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++) - { - analog_net_t *n = m_nets[k]; - terms_t *t = m_terms[k]; - - const nl_double DD_n = (n->Q_Analog() - t->m_last_V); - const nl_double hn = cur_ts; - - //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1); - nl_double DD2 = (DD_n / hn - t->m_DD_n_m_1 / t->m_h_n_m_1) / (hn + t->m_h_n_m_1); - nl_double new_net_timestep; - - t->m_h_n_m_1 = hn; - t->m_DD_n_m_1 = DD_n; - if (std::fabs(DD2) > NL_FCONST(1e-60)) // avoid div-by-zero - new_net_timestep = std::sqrt(m_params.m_lte / std::fabs(NL_FCONST(0.5)*DD2)); - else - new_net_timestep = m_params.m_max_timestep; - - if (new_net_timestep < new_solver_timestep) - new_solver_timestep = new_net_timestep; - - t->m_last_V = n->Q_Analog(); - } - if (new_solver_timestep < m_params.m_min_timestep) - { - //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6); - new_solver_timestep = m_params.m_min_timestep; - } - } - //if (new_solver_timestep > 10.0 * hn) - // new_solver_timestep = 10.0 * hn; - /* - * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere. - */ - return std::max(netlist_time::from_double(new_solver_timestep), netlist_time::quantum() * 2); -} - - - -void matrix_solver_t::log_stats() -{ - if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats) - { - log().verbose("=============================================="); - log().verbose("Solver {1}", this->name()); - log().verbose(" ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name()); - log().verbose(" has {1} elements", this->has_dynamic_devices() ? "dynamic" : "no dynamic"); - log().verbose(" has {1} elements", this->has_timestep_devices() ? "timestep" : "no timestep"); - log().verbose(" {1:6.3} average newton raphson loops", - static_cast(this->m_stat_newton_raphson) / static_cast(this->m_stat_vsolver_calls)); - log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average", - this->m_stat_calculations(), - static_cast(this->m_stat_calculations()) / this->netlist().time().as_double(), - this->m_iterative_fail(), - 100.0 * static_cast(this->m_iterative_fail()) - / static_cast(this->m_stat_calculations()), - static_cast(this->m_iterative_total()) / static_cast(this->m_stat_calculations())); - } -} // ---------------------------------------------------------------------------------------- diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp index 3dc021cce64..9523febf06a 100644 --- a/src/lib/netlist/tools/nl_convert.cpp +++ b/src/lib/netlist/tools/nl_convert.cpp @@ -58,6 +58,19 @@ static lib_map_t read_lib_map(const pstring lm) convert - convert a spice netlist -------------------------------------------------*/ +nl_convert_base_t::nl_convert_base_t() + : out(m_buf) + , m_numberchars("0123456789-+e.") +{ +} + +nl_convert_base_t::~nl_convert_base_t() +{ + m_nets.clear(); + m_devs.clear(); + m_pins.clear(); +} + void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias) { pstring pname = devname + "." + name; @@ -384,19 +397,53 @@ void nl_convert_spice_t::process_line(const pstring &line) } } +/*------------------------------------------------- + Eagle converter +-------------------------------------------------*/ + +nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm) + : plib::ptokenizer(strm) + , m_convert(convert) +{ + set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-"); + set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers + char ws[5]; + ws[0] = ' '; + ws[1] = 9; + ws[2] = 10; + ws[3] = 13; + ws[4] = 0; + set_whitespace(ws); + /* FIXME: gnetlist doesn't print comments */ + set_comment("/*", "*/", "//"); + set_string_char('\''); + m_tok_ADD = register_token("ADD"); + m_tok_VALUE = register_token("VALUE"); + m_tok_SIGNAL = register_token("SIGNAL"); + m_tok_SEMICOLON = register_token(";"); + /* currently not used, but required for parsing */ + register_token(")"); + register_token("("); +} + +void nl_convert_eagle_t::tokenizer::verror(const pstring &msg, int line_num, const pstring &line) +{ + m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str()); +} + //FIXME: should accept a stream as well void nl_convert_eagle_t::convert(const pstring &contents) { plib::pistringstream istrm(contents); - eagle_tokenizer tok(*this, istrm); + tokenizer tok(*this, istrm); out("NETLIST_START(dummy)\n"); add_term("GND", "GND"); add_term("VCC", "VCC"); - eagle_tokenizer::token_t token = tok.get_token(); + tokenizer::token_t token = tok.get_token(); while (true) { - if (token.is_type(eagle_tokenizer::ENDOFFILE)) + if (token.is_type(tokenizer::ENDOFFILE)) { dump_nl(); // FIXME: Parameter @@ -492,6 +539,42 @@ void nl_convert_eagle_t::convert(const pstring &contents) } +/*------------------------------------------------- + RINF converter +-------------------------------------------------*/ + +nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm) + : plib::ptokenizer(strm) + , m_convert(convert) +{ + set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-"); + set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers + char ws[5]; + ws[0] = ' '; + ws[1] = 9; + ws[2] = 10; + ws[3] = 13; + ws[4] = 0; + set_whitespace(ws); + /* FIXME: gnetlist doesn't print comments */ + set_comment("","","//"); // FIXME:needs to be confirmed + set_string_char('"'); + m_tok_HEA = register_token(".HEA"); + m_tok_APP = register_token(".APP"); + m_tok_TIM = register_token(".TIM"); + m_tok_TYP = register_token(".TYP"); + m_tok_ADDC = register_token(".ADD_COM"); + m_tok_ATTC = register_token(".ATT_COM"); + m_tok_NET = register_token(".ADD_TER"); + m_tok_TER = register_token(".TER"); + m_tok_END = register_token(".END"); +} + +void nl_convert_rinf_t::tokenizer::verror(const pstring &msg, int line_num, const pstring &line) +{ + m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str()); +} + /* token_id_t m_tok_HFA; token_id_t m_tok_APP; token_id_t m_tok_TIM; @@ -502,6 +585,7 @@ void nl_convert_eagle_t::convert(const pstring &contents) token_id_t m_tok_TER; * */ + void nl_convert_rinf_t::convert(const pstring &contents) { plib::pistringstream istrm(contents); diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index 859c5ea1e9c..3536488c766 100644 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -23,13 +23,8 @@ class nl_convert_base_t { public: - nl_convert_base_t() : out(m_buf), m_numberchars("0123456789-+e.") {} - virtual ~nl_convert_base_t() - { - m_nets.clear(); - m_devs.clear(); - m_pins.clear(); - } + nl_convert_base_t(); + virtual ~nl_convert_base_t(); const pstringbuffer &result() { return m_buf.str(); } @@ -168,32 +163,10 @@ public: { } - class eagle_tokenizer : public plib::ptokenizer + class tokenizer : public plib::ptokenizer { public: - eagle_tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm) - : plib::ptokenizer(strm), m_convert(convert) - { - set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-"); - set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers - char ws[5]; - ws[0] = ' '; - ws[1] = 9; - ws[2] = 10; - ws[3] = 13; - ws[4] = 0; - set_whitespace(ws); - /* FIXME: gnetlist doesn't print comments */ - set_comment("/*", "*/", "//"); - set_string_char('\''); - m_tok_ADD = register_token("ADD"); - m_tok_VALUE = register_token("VALUE"); - m_tok_SIGNAL = register_token("SIGNAL"); - m_tok_SEMICOLON = register_token(";"); - /* currently not used, but required for parsing */ - register_token(")"); - register_token("("); - } + tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm); token_id_t m_tok_ADD; token_id_t m_tok_VALUE; @@ -202,11 +175,7 @@ public: protected: - void verror(const pstring &msg, int line_num, const pstring &line) override - { - m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str()); - } - + virtual void verror(const pstring &msg, int line_num, const pstring &line) override; private: nl_convert_eagle_t &m_convert; @@ -233,31 +202,7 @@ public: class tokenizer : public plib::ptokenizer { public: - tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm) - : plib::ptokenizer(strm), m_convert(convert) - { - set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-"); - set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers - char ws[5]; - ws[0] = ' '; - ws[1] = 9; - ws[2] = 10; - ws[3] = 13; - ws[4] = 0; - set_whitespace(ws); - /* FIXME: gnetlist doesn't print comments */ - set_comment("","","//"); // FIXME:needs to be confirmed - set_string_char('"'); - m_tok_HEA = register_token(".HEA"); - m_tok_APP = register_token(".APP"); - m_tok_TIM = register_token(".TIM"); - m_tok_TYP = register_token(".TYP"); - m_tok_ADDC = register_token(".ADD_COM"); - m_tok_ATTC = register_token(".ATT_COM"); - m_tok_NET = register_token(".ADD_TER"); - m_tok_TER = register_token(".TER"); - m_tok_END = register_token(".END"); - } + tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm); token_id_t m_tok_HEA; token_id_t m_tok_APP; @@ -271,11 +216,7 @@ public: protected: - void verror(const pstring &msg, int line_num, const pstring &line) override - { - m_convert.out("{} (line {}): {}\n", msg.c_str(), line_num, line.c_str()); - } - + virtual void verror(const pstring &msg, int line_num, const pstring &line) override; private: nl_convert_rinf_t &m_convert;