mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
netlist: Nice performance increase by removing logic terminals from net if they are inactive. Introduced a linked-list class to abstract linked-lists. Fixed deactivating devices. You have to enable this because it is not guaranteed to be timing-exact. [Couriersud]
This commit is contained in:
parent
72292ef70a
commit
61300bfcb8
@ -32,7 +32,7 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLI
|
||||
|
||||
(*pn)->m_solver = this;
|
||||
|
||||
for (netlist_core_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_core_terminal_t *p = (*pn)->m_list.first(); p != NULL; p = (*pn)->m_list.next(p))
|
||||
{
|
||||
NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet()));
|
||||
switch (p->type())
|
||||
@ -627,12 +627,12 @@ ATTR_COLD static bool already_processed(net_groups_t groups, int &cur_group, net
|
||||
|
||||
ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
|
||||
{
|
||||
if (net->m_head == NULL)
|
||||
if (net->m_list.is_empty())
|
||||
return;
|
||||
/* add the net */
|
||||
SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr()));
|
||||
groups[cur_group].add(net);
|
||||
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_core_terminal_t *p = net->m_list.first(); p != NULL; p = net->m_list.next(p))
|
||||
{
|
||||
SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr()));
|
||||
if (p->isType(netlist_terminal_t::TERMINAL))
|
||||
@ -855,7 +855,7 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start()
|
||||
{
|
||||
SOLVER_VERBOSE_OUT(("Net %d: %s\n", j, groups[i][j]->name().cstr()));
|
||||
netlist_net_t *n = groups[i][j];
|
||||
for (netlist_core_terminal_t *p = n->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_core_terminal_t *p = n->m_list.first(); p != NULL; p = n->m_list.next(p))
|
||||
{
|
||||
SOLVER_VERBOSE_OUT((" %s\n", p->name().cstr()));
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
NETLIB_START(9316)
|
||||
{
|
||||
register_sub(subABCD, "subABCD");
|
||||
sub.m_ABCD = &subABCD;
|
||||
register_sub(sub, "sub");
|
||||
|
||||
register_subalias("CLK", sub.m_CLK);
|
||||
@ -16,10 +18,10 @@ NETLIB_START(9316)
|
||||
register_input("CLRQ", m_CLRQ);
|
||||
register_input("LOADQ", m_LOADQ);
|
||||
|
||||
register_subalias("A", sub.m_A);
|
||||
register_subalias("B", sub.m_B);
|
||||
register_subalias("C", sub.m_C);
|
||||
register_subalias("D", sub.m_D);
|
||||
register_subalias("A", subABCD.m_A);
|
||||
register_subalias("B", subABCD.m_B);
|
||||
register_subalias("C", subABCD.m_C);
|
||||
register_subalias("D", subABCD.m_D);
|
||||
|
||||
register_subalias("QA", sub.m_QA);
|
||||
register_subalias("QB", sub.m_QB);
|
||||
@ -32,17 +34,45 @@ NETLIB_START(9316)
|
||||
NETLIB_RESET(9316)
|
||||
{
|
||||
sub.do_reset();
|
||||
subABCD.do_reset();
|
||||
}
|
||||
|
||||
NETLIB_START(9316_subABCD)
|
||||
{
|
||||
register_input("A", m_A);
|
||||
register_input("B", m_B);
|
||||
register_input("C", m_C);
|
||||
register_input("D", m_D);
|
||||
|
||||
}
|
||||
|
||||
NETLIB_RESET(9316_subABCD)
|
||||
{
|
||||
if (1 || !USE_ADD_REMOVE_LIST)
|
||||
{
|
||||
m_A.inactivate();
|
||||
m_B.inactivate();
|
||||
m_C.inactivate();
|
||||
m_D.inactivate();
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline UINT8 NETLIB_NAME(9316_subABCD::read_ABCD)()
|
||||
{
|
||||
if (1 || !USE_ADD_REMOVE_LIST)
|
||||
return (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
|
||||
else
|
||||
return (INPLOGIC(m_D) << 3) | (INPLOGIC(m_C) << 2) | (INPLOGIC(m_B) << 1) | (INPLOGIC(m_A) << 0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(9316_subABCD)
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_START(9316_sub)
|
||||
{
|
||||
register_input("CLK", m_CLK);
|
||||
|
||||
register_input("A", m_A);
|
||||
register_input("B", m_B);
|
||||
register_input("C", m_C);
|
||||
register_input("D", m_D);
|
||||
|
||||
register_output("QA", m_QA);
|
||||
register_output("QB", m_QB);
|
||||
register_output("QC", m_QC);
|
||||
@ -57,11 +87,6 @@ NETLIB_START(9316_sub)
|
||||
NETLIB_RESET(9316_sub)
|
||||
{
|
||||
m_CLK.set_state(netlist_input_t::STATE_INP_LH);
|
||||
m_A.set_state(netlist_input_t::STATE_INP_PASSIVE);
|
||||
m_B.set_state(netlist_input_t::STATE_INP_PASSIVE);
|
||||
m_C.set_state(netlist_input_t::STATE_INP_PASSIVE);
|
||||
m_D.set_state(netlist_input_t::STATE_INP_PASSIVE);
|
||||
|
||||
m_cnt = 0;
|
||||
m_loadq = 1;
|
||||
m_ent = 1;
|
||||
@ -84,7 +109,7 @@ NETLIB_UPDATE(9316_sub)
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt = (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
|
||||
cnt = m_ABCD->read_ABCD();
|
||||
update_outputs_all(cnt);
|
||||
OUTLOGIC(m_RC, m_ent & (cnt == 0x0f), NLTIME_FROM_NS(20));
|
||||
}
|
||||
@ -109,9 +134,9 @@ NETLIB_UPDATE(9316)
|
||||
{
|
||||
cnt = 0;
|
||||
sub.update_outputs(cnt);
|
||||
OUTLOGIC(sub.m_RC, 0, NLTIME_FROM_NS(20));
|
||||
//OUTLOGIC(sub.m_RC, 0, NLTIME_FROM_NS(20));
|
||||
sub.m_cnt = cnt;
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
}
|
||||
OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
|
||||
@ -177,10 +202,10 @@ NETLIB_START(9316_dip)
|
||||
|
||||
register_subalias("1", m_CLRQ);
|
||||
register_subalias("2", sub.m_CLK);
|
||||
register_subalias("3", sub.m_A);
|
||||
register_subalias("4", sub.m_B);
|
||||
register_subalias("5", sub.m_C);
|
||||
register_subalias("6", sub.m_D);
|
||||
register_subalias("3", subABCD.m_A);
|
||||
register_subalias("4", subABCD.m_B);
|
||||
register_subalias("5", subABCD.m_C);
|
||||
register_subalias("6", subABCD.m_D);
|
||||
register_subalias("7", m_ENP);
|
||||
// register_subalias("8", ); --> GND
|
||||
|
||||
|
@ -66,18 +66,23 @@
|
||||
#define TTL_9316_DIP(_name) \
|
||||
NET_REGISTER_DEV(9316_dip, _name)
|
||||
|
||||
NETLIB_SUBDEVICE(9316_subABCD,
|
||||
netlist_ttl_input_t m_A;
|
||||
netlist_ttl_input_t m_B;
|
||||
netlist_ttl_input_t m_C;
|
||||
netlist_ttl_input_t m_D;
|
||||
|
||||
ATTR_HOT inline UINT8 read_ABCD();
|
||||
);
|
||||
|
||||
NETLIB_SUBDEVICE(9316_sub,
|
||||
ATTR_HOT void update_outputs_all(const UINT8 cnt);
|
||||
ATTR_HOT void update_outputs(const UINT8 cnt);
|
||||
|
||||
netlist_ttl_input_t m_CLK;
|
||||
|
||||
netlist_ttl_input_t m_A;
|
||||
netlist_ttl_input_t m_B;
|
||||
netlist_ttl_input_t m_C;
|
||||
netlist_ttl_input_t m_D;
|
||||
|
||||
UINT8 m_cnt;
|
||||
NETLIB_NAME(9316_subABCD) *m_ABCD;
|
||||
netlist_sig_t m_loadq;
|
||||
netlist_sig_t m_ent;
|
||||
|
||||
@ -90,6 +95,7 @@ NETLIB_SUBDEVICE(9316_sub,
|
||||
|
||||
NETLIB_DEVICE(9316,
|
||||
NETLIB_NAME(9316_sub) sub;
|
||||
NETLIB_NAME(9316_subABCD) subABCD;
|
||||
netlist_ttl_input_t m_ENP;
|
||||
netlist_ttl_input_t m_ENT;
|
||||
netlist_ttl_input_t m_CLRQ;
|
||||
|
@ -104,29 +104,33 @@ public:
|
||||
m_active = 1;
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT void inc_active()
|
||||
{
|
||||
if (++m_active == 1)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT void inc_active()
|
||||
{
|
||||
if (++m_active == 1)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT void dec_active()
|
||||
{
|
||||
if (--m_active == 0)
|
||||
{
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
m_i[i].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ATTR_HOT void dec_active()
|
||||
{
|
||||
if (--m_active == 0)
|
||||
{
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
m_i[i].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
|
||||
|
||||
// FIXME: this check is needed because update is called during startup as well
|
||||
if (UNEXPECTED(USE_DEACTIVE_DEVICE && m_active == 0))
|
||||
return;
|
||||
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
{
|
||||
this->m_i[i].activate();
|
||||
@ -174,29 +178,33 @@ public:
|
||||
m_active = 1;
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT virtual void inc_active()
|
||||
{
|
||||
if (++m_active == 1)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT virtual void inc_active()
|
||||
{
|
||||
if (++m_active == 1)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT virtual void dec_active()
|
||||
{
|
||||
if (--m_active == 0)
|
||||
{
|
||||
m_i[0].inactivate();
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ATTR_HOT virtual void dec_active()
|
||||
{
|
||||
if (--m_active == 0)
|
||||
{
|
||||
m_i[0].inactivate();
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void update()
|
||||
{
|
||||
const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)};
|
||||
|
||||
// FIXME: this check is needed because update is called during startup as well
|
||||
if (UNEXPECTED(USE_DEACTIVE_DEVICE && m_active == 0))
|
||||
return;
|
||||
|
||||
m_i[0].activate();
|
||||
m_i[1].activate();
|
||||
#if 0
|
||||
|
@ -465,7 +465,6 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil
|
||||
: netlist_object_t(atype, afamily)
|
||||
, m_solver(NULL)
|
||||
, m_railterminal(NULL)
|
||||
, m_head(NULL)
|
||||
, m_num_cons(0)
|
||||
, m_time(netlist_time::zero)
|
||||
, m_active(0)
|
||||
@ -484,10 +483,16 @@ ATTR_COLD netlist_net_t::~netlist_net_t()
|
||||
netlist().remove_save_items(this);
|
||||
}
|
||||
|
||||
ATTR_HOT void netlist_net_t::inc_active()
|
||||
ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term)
|
||||
{
|
||||
m_active++;
|
||||
|
||||
if (USE_ADD_REMOVE_LIST)
|
||||
{
|
||||
m_list.insert(term);
|
||||
//m_list.add(term);
|
||||
}
|
||||
|
||||
if (USE_DEACTIVE_DEVICE)
|
||||
{
|
||||
if (m_active == 1 && m_in_queue > 0)
|
||||
@ -516,9 +521,15 @@ ATTR_HOT void netlist_net_t::inc_active()
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT void netlist_net_t::dec_active()
|
||||
ATTR_HOT void netlist_net_t::dec_active(netlist_core_terminal_t &term)
|
||||
{
|
||||
m_active--;
|
||||
|
||||
if (USE_ADD_REMOVE_LIST)
|
||||
{
|
||||
m_list.remove(term);
|
||||
}
|
||||
|
||||
if (USE_DEACTIVE_DEVICE)
|
||||
{
|
||||
if (m_active == 0)
|
||||
@ -539,9 +550,12 @@ ATTR_COLD void netlist_net_t::reset()
|
||||
m_active = 0;
|
||||
m_in_queue = 2;
|
||||
|
||||
for (netlist_core_terminal_t *t = m_head; t != NULL; t = t->m_update_list_next)
|
||||
for (netlist_core_terminal_t *t = m_list.first(); t != NULL; t = m_list.next(t))
|
||||
{
|
||||
t->do_reset();
|
||||
}
|
||||
for (netlist_core_terminal_t *t = m_list.first(); t != NULL; t = m_list.next(t))
|
||||
{
|
||||
if (t->state() != netlist_input_t::STATE_INP_PASSIVE)
|
||||
m_active++;
|
||||
}
|
||||
@ -589,15 +603,15 @@ ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet)
|
||||
}
|
||||
else
|
||||
{
|
||||
netlist_core_terminal_t *p = othernet->m_head;
|
||||
netlist_core_terminal_t *p = othernet->m_list.first();
|
||||
while (p != NULL)
|
||||
{
|
||||
netlist_core_terminal_t *pn = p->m_update_list_next;
|
||||
netlist_core_terminal_t *pn = othernet->m_list.next(p);
|
||||
register_con(*p);
|
||||
p = pn;
|
||||
}
|
||||
|
||||
othernet->m_head = NULL; // FIXME: othernet needs to be free'd from memory
|
||||
othernet->m_list.clear(); // FIXME: othernet needs to be free'd from memory
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,8 +619,7 @@ ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal)
|
||||
{
|
||||
terminal.set_net(*this);
|
||||
|
||||
terminal.m_update_list_next = m_head;
|
||||
m_head = &terminal;
|
||||
m_list.insert(terminal);
|
||||
m_num_cons++;
|
||||
|
||||
if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE)
|
||||
@ -632,38 +645,52 @@ ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs()
|
||||
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ];
|
||||
netlist_core_terminal_t *p = m_head;
|
||||
netlist_core_terminal_t *p = m_list.first();
|
||||
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
m_cur_Q = m_new_Q;
|
||||
|
||||
m_cur_Analog = m_new_Analog;
|
||||
|
||||
#if 1
|
||||
switch (m_num_cons)
|
||||
if (USE_ADD_REMOVE_LIST)
|
||||
{
|
||||
case 2:
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
case 1:
|
||||
update_dev(p, mask);
|
||||
break;
|
||||
default:
|
||||
do
|
||||
switch (m_active)
|
||||
{
|
||||
case 2:
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
} while (p != NULL);
|
||||
break;
|
||||
p = m_list.next(p);
|
||||
if (p == NULL) break;
|
||||
case 1:
|
||||
update_dev(p, mask);
|
||||
break;
|
||||
default:
|
||||
while (p != NULL)
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p = m_list.next(p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
do
|
||||
else
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p = p->m_update_list_next;
|
||||
} while (p != NULL);
|
||||
#endif
|
||||
switch (m_num_cons)
|
||||
{
|
||||
case 2:
|
||||
update_dev(p, mask);
|
||||
p = m_list.next(p);
|
||||
case 1:
|
||||
update_dev(p, mask);
|
||||
break;
|
||||
default:
|
||||
do
|
||||
{
|
||||
update_dev(p, mask);
|
||||
p = m_list.next(p);
|
||||
} while (p != NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_last_Q = m_cur_Q;
|
||||
m_last_Analog = m_cur_Analog;
|
||||
}
|
||||
@ -680,8 +707,8 @@ ATTR_HOT void netlist_net_t::solve()
|
||||
|
||||
ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, const family_t afamily)
|
||||
: netlist_owned_object_t(atype, afamily)
|
||||
, plinked_list_element<netlist_core_terminal_t>()
|
||||
, m_family_desc(NULL)
|
||||
, m_update_list_next(NULL)
|
||||
, m_net(NULL)
|
||||
, m_state(STATE_NONEX)
|
||||
{
|
||||
|
@ -364,7 +364,7 @@ private:
|
||||
// netlist_core_terminal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_core_terminal_t : public netlist_owned_object_t
|
||||
class netlist_core_terminal_t : public netlist_owned_object_t, public plinked_list_element<netlist_core_terminal_t>
|
||||
{
|
||||
NETLIST_PREVENT_COPYING(netlist_core_terminal_t)
|
||||
public:
|
||||
@ -403,8 +403,6 @@ public:
|
||||
|
||||
const netlist_logic_family_desc_t *m_family_desc;
|
||||
|
||||
netlist_core_terminal_t *m_update_list_next;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
@ -568,8 +566,8 @@ public:
|
||||
ATTR_HOT inline const netlist_core_terminal_t & RESTRICT railterminal() const { return *m_railterminal; }
|
||||
|
||||
/* Everything below is used by the logic subsystem */
|
||||
ATTR_HOT void inc_active();
|
||||
ATTR_HOT void dec_active();
|
||||
ATTR_HOT void inc_active(netlist_core_terminal_t &term);
|
||||
ATTR_HOT void dec_active(netlist_core_terminal_t &term);
|
||||
|
||||
ATTR_HOT inline const netlist_sig_t Q() const
|
||||
{
|
||||
@ -627,7 +625,7 @@ public:
|
||||
|
||||
ATTR_HOT void solve();
|
||||
|
||||
netlist_core_terminal_t *m_head;
|
||||
plinked_list<netlist_core_terminal_t> m_list;
|
||||
|
||||
protected: //FIXME: needed by current solver code
|
||||
|
||||
@ -1159,15 +1157,15 @@ ATTR_HOT inline void netlist_input_t::inactivate()
|
||||
if (EXPECTED(!is_state(STATE_INP_PASSIVE)))
|
||||
{
|
||||
set_state(STATE_INP_PASSIVE);
|
||||
net().dec_active();
|
||||
net().dec_active(*this);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void netlist_input_t::activate()
|
||||
{
|
||||
if (EXPECTED(is_state(STATE_INP_PASSIVE)))
|
||||
if (is_state(STATE_INP_PASSIVE))
|
||||
{
|
||||
net().inc_active();
|
||||
net().inc_active(*this);
|
||||
set_state(STATE_INP_ACTIVE);
|
||||
}
|
||||
}
|
||||
@ -1176,7 +1174,7 @@ ATTR_HOT inline void netlist_input_t::activate_hl()
|
||||
{
|
||||
if (is_state(STATE_INP_PASSIVE))
|
||||
{
|
||||
net().inc_active();
|
||||
net().inc_active(*this);
|
||||
set_state(STATE_INP_HL);
|
||||
}
|
||||
}
|
||||
@ -1185,7 +1183,7 @@ ATTR_HOT inline void netlist_input_t::activate_lh()
|
||||
{
|
||||
if (is_state(STATE_INP_PASSIVE))
|
||||
{
|
||||
net().inc_active();
|
||||
net().inc_active(*this);
|
||||
set_state(STATE_INP_LH);
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,15 @@
|
||||
*/
|
||||
#define USE_PMFDELEGATES (0)
|
||||
|
||||
// This used to add 20% performance ... but is not guaranteed to be absolutely timing correct.
|
||||
// Update 01.01.2014: Currently, enabling this has no observable impact on performance.
|
||||
// This increases performance in circuits with a lot of gates
|
||||
// but is not guaranteed to be absolutely timing correct.
|
||||
|
||||
#define USE_DEACTIVE_DEVICE (0)
|
||||
|
||||
// The following adds about 10% performance ...
|
||||
|
||||
#define USE_ADD_REMOVE_LIST (1)
|
||||
|
||||
#define USE_OPENMP (0)
|
||||
|
||||
// Use nano-second resolution - Sufficient for now
|
||||
|
@ -293,5 +293,82 @@ private:
|
||||
netlist_list_t<_StackClass, _NumElem> m_list;
|
||||
};
|
||||
|
||||
template <class _ListClass>
|
||||
struct plinked_list_element
|
||||
{
|
||||
plinked_list_element() : m_next(NULL) {}
|
||||
_ListClass * m_next;
|
||||
|
||||
};
|
||||
|
||||
template <class _ListClass>
|
||||
class plinked_list
|
||||
{
|
||||
public:
|
||||
|
||||
plinked_list() : m_head(NULL) {}
|
||||
|
||||
ATTR_HOT inline void insert(const _ListClass &before, _ListClass &elem)
|
||||
{
|
||||
if (m_head == &before)
|
||||
{
|
||||
elem.m_next = m_head;
|
||||
m_head = elem;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ListClass *p = m_head;
|
||||
while (p != NULL)
|
||||
{
|
||||
if (p->m_next == &before)
|
||||
{
|
||||
elem->m_next = &before;
|
||||
p->m_next = &elem;
|
||||
return;
|
||||
}
|
||||
p = p->m_next;
|
||||
}
|
||||
assert_always(false, "element not found");
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void insert(_ListClass &elem)
|
||||
{
|
||||
elem.m_next = m_head;
|
||||
m_head = &elem;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void add(_ListClass &elem)
|
||||
{
|
||||
_ListClass **p = &m_head;
|
||||
while (*p != NULL)
|
||||
{
|
||||
p = &((*p)->m_next);
|
||||
}
|
||||
*p = &elem;
|
||||
elem.m_next = NULL;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void remove(const _ListClass &elem)
|
||||
{
|
||||
_ListClass **p = &m_head;
|
||||
while (*p != &elem)
|
||||
{
|
||||
assert(*p != NULL);
|
||||
p = &((*p)->m_next);
|
||||
}
|
||||
(*p) = elem.m_next;
|
||||
}
|
||||
|
||||
|
||||
ATTR_HOT static inline _ListClass *next(const _ListClass &elem) { return elem.m_next; }
|
||||
ATTR_HOT static inline _ListClass *next(const _ListClass *elem) { return elem->m_next; }
|
||||
ATTR_HOT inline _ListClass *first() const { return m_head; }
|
||||
ATTR_HOT inline void clear() { m_head = NULL; }
|
||||
ATTR_HOT inline bool is_empty() const { return (m_head == NULL); }
|
||||
|
||||
private:
|
||||
_ListClass *m_head;
|
||||
};
|
||||
|
||||
#endif /* NLLISTS_H_ */
|
||||
|
@ -402,15 +402,15 @@ nld_base_d_to_a_proxy *netlist_setup_t::get_d_a_proxy(netlist_output_t &out)
|
||||
#if 1
|
||||
/* connect all existing terminals to new net */
|
||||
|
||||
netlist_core_terminal_t *p = out.net().m_head;
|
||||
netlist_core_terminal_t *p = out.net().m_list.first();
|
||||
while (p != NULL)
|
||||
{
|
||||
netlist_core_terminal_t *np = p->m_update_list_next;
|
||||
netlist_core_terminal_t *np = out.net().m_list.next(p);
|
||||
p->clear_net(); // de-link from all nets ...
|
||||
connect(proxy->out(), *p);
|
||||
p = np;
|
||||
}
|
||||
out.net().m_head = NULL; // clear the list
|
||||
out.net().m_list.clear(); // clear the list
|
||||
out.net().m_num_cons = 0;
|
||||
#endif
|
||||
out.net().register_con(proxy->m_I);
|
||||
@ -620,7 +620,7 @@ void netlist_setup_t::resolve_inputs()
|
||||
|
||||
for (netlist_net_t *const *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
|
||||
{
|
||||
if ((*pn)->m_head == NULL)
|
||||
if ((*pn)->m_list.is_empty())
|
||||
{
|
||||
todelete.add(*pn);
|
||||
}
|
||||
|
@ -57,6 +57,13 @@ void free_file_line( void *memory, const char *file, int line )
|
||||
osd_free( memory );
|
||||
}
|
||||
|
||||
void CLIB_DECL logerror(const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vprintf(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
struct options_entry oplist[] =
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user