From 636894b02f9e920cc122b150a5356188da60edd7 Mon Sep 17 00:00:00 2001 From: couriersud Date: Sun, 26 Jan 2020 21:22:13 +0100 Subject: [PATCH] netlist: MAJOR bug fix. Expect other bugs to surface. [Couriersud] This commit fixes an issue with parsing netlists. To cut a long story short: The separation of nets into independant groups of nets failed under some circumstances for four terminal devices (controlled voltage/current devices). Everything worked as long as an external feedback loop existed. Without external feedback loop, the separation would either fail or create "false" separated nets. This fix also highlighted an issue with cmos switches (4066/4016). There is a slight chance that other bugs may surface due to this change. --- src/lib/netlist/devices/nld_4066.cpp | 9 ++++-- src/lib/netlist/nl_config.h | 2 +- src/lib/netlist/solver/nld_solver.cpp | 41 +++++++++++++++++++++------ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp index bd9b7bfe004..a45b2ab9e22 100644 --- a/src/lib/netlist/devices/nld_4066.cpp +++ b/src/lib/netlist/devices/nld_4066.cpp @@ -23,6 +23,7 @@ namespace netlist , m_R(*this, "R") , m_control(*this, "CTL") , m_base_r(*this, "BASER", nlconst::magic(270.0)) + , m_last(*this, "m_last", false) { } @@ -34,7 +35,8 @@ namespace netlist analog::NETLIB_SUB(R_base) m_R; analog_input_t m_control; - param_fp_t m_base_r; + param_fp_t m_base_r; + state_var m_last; }; NETLIB_RESET(CD4066_GATE) @@ -53,6 +55,7 @@ namespace netlist nl_fptype in = m_control() - m_supply.GND().Q_Analog(); nl_fptype rON = m_base_r() * nlconst::magic(5.0) / sup; nl_fptype R = -nlconst::one(); + bool new_state(false); if (in < low) { @@ -61,10 +64,12 @@ namespace netlist else if (in > high) { R = rON; + new_state = true; } //printf("%s %f %f %g\n", name().c_str(), sup, in, R); - if (R > nlconst::zero()) + if (R > nlconst::zero() && (m_last != new_state)) { + m_last = new_state; m_R.update(); m_R.set_R(R); m_R.solve_later(); diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 3d50da284c4..f6b594af977 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -17,7 +17,7 @@ /// /// \brief Version - Minor. /// -#define NL_VERSION_MINOR 9 +#define NL_VERSION_MINOR 10 /// \brief Version - Patch level. /// #define NL_VERSION_PATCHLEVEL 0 diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 09920dfd73c..a4eedc38ed7 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -253,28 +253,45 @@ namespace devices struct net_splitter { - bool already_processed(const analog_net_t &n) const + bool already_processed(const analog_net_t &n) { // no need to process rail nets - these are known variables if (n.isRailNet()) return true; + // First check if it is in a previous group. + // In this case we need to merge this group into the current group + if (groupspre.size() > 1) + { + for (std::size_t i = 0; iname(), (int) term->type()); // only process analog terminals if (term->is_type(detail::terminal_type::TERMINAL)) { @@ -282,6 +299,7 @@ namespace devices // check the connected terminal // analog_net_t &connected_net = pt->connected_terminal()->net(); analog_net_t &connected_net = netlist.setup().get_connected_terminal(*pt)->net(); + netlist.log().verbose(" Connected net {}", connected_net.name()); if (!already_processed(connected_net)) process_net(netlist, connected_net); } @@ -292,22 +310,29 @@ namespace devices { for (auto & net : netlist.nets()) { - netlist.log().debug("processing {1}\n", net->name()); + netlist.log().debug("processing {1}", net->name()); + netlist.log().verbose("processing {1}", net->name()); if (!net->isRailNet() && net->num_cons() > 0) { - netlist.log().debug(" ==> not a rail net\n"); + netlist.log().debug(" ==> not a rail net"); + netlist.log().verbose(" ==> not a rail net"); // Must be an analog net auto &n = *static_cast(net.get()); if (!already_processed(n)) { - groups.emplace_back(analog_net_t::list_t()); + groupspre.emplace_back(analog_net_t::list_t()); process_net(netlist, n); } } } + for (auto &g : groupspre) + if (!g.empty()) + groups.push_back(g); } std::vector groups; + private: + std::vector groupspre; }; void NETLIB_NAME(solver)::post_start()