mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
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.
This commit is contained in:
parent
3b55bb501f
commit
636894b02f
@ -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<bool> 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();
|
||||
|
@ -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
|
||||
|
@ -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; i<groupspre.size() - 1; i++)
|
||||
if (plib::container::contains(groupspre[i], &n))
|
||||
{
|
||||
// copy all nets
|
||||
for (auto & cn : groupspre[i])
|
||||
if (!plib::container::contains(groupspre.back(), cn))
|
||||
groupspre.back().push_back(cn);
|
||||
// clear
|
||||
groupspre[i].clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// if it's already processed - no need to continue
|
||||
for (auto & grp : groups)
|
||||
if (plib::container::contains(grp, &n))
|
||||
return true;
|
||||
if (!groupspre.empty() && plib::container::contains(groupspre.back(), &n))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void process_net(netlist_state_t &netlist, analog_net_t &n)
|
||||
{
|
||||
// ignore empty nets. FIXME: print a warning message
|
||||
netlist.log().verbose("Net {}", n.name());
|
||||
if (n.num_cons() == 0)
|
||||
return;
|
||||
// add the net
|
||||
groups.back().push_back(&n);
|
||||
groupspre.back().push_back(&n);
|
||||
// process all terminals connected to this net
|
||||
for (auto &term : n.core_terms())
|
||||
{
|
||||
netlist.log().verbose("Term {} {}", term->name(), (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<analog_net_t *>(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<analog_net_t::list_t> groups;
|
||||
private:
|
||||
std::vector<analog_net_t::list_t> groupspre;
|
||||
};
|
||||
|
||||
void NETLIB_NAME(solver)::post_start()
|
||||
|
Loading…
Reference in New Issue
Block a user