Optimized netlist proxies. Small but measurable performance increase for pongf and Pong Doubles. In addition, moved some code between classes and sorted code in nl_base.c

This commit is contained in:
Couriersud 2014-06-15 17:38:18 +00:00
parent 9e57e262c6
commit b94047212b
8 changed files with 233 additions and 182 deletions

View File

@ -116,11 +116,11 @@ NETLIB_START(QBJT_switch)
NETLIB_UPDATE(QBJT_switch)
{
if (!m_RB.m_P.net().isRailNet())
m_RB.m_P.net().as_analog().schedule_solve(); // Basis
m_RB.m_P.schedule_solve(); // Basis
else if (!m_RB.m_N.net().isRailNet())
m_RB.m_N.net().as_analog().schedule_solve(); // Emitter
m_RB.m_N.schedule_solve(); // Emitter
else if (!m_RC.m_P.net().isRailNet())
m_RC.m_P.net().as_analog().schedule_solve(); // Collector
m_RC.m_P.schedule_solve(); // Collector
}
@ -176,11 +176,11 @@ NETLIB_START(QBJT_EB)
NETLIB_UPDATE(QBJT_EB)
{
if (!m_D_EB.m_P.net().isRailNet())
m_D_EB.m_P.net().as_analog().schedule_solve(); // Basis
m_D_EB.m_P.schedule_solve(); // Basis
else if (!m_D_EB.m_N.net().isRailNet())
m_D_EB.m_N.net().as_analog().schedule_solve(); // Emitter
m_D_EB.m_N.schedule_solve(); // Emitter
else
m_D_CB.m_N.net().as_analog().schedule_solve(); // Collector
m_D_CB.m_N.schedule_solve(); // Collector
}
NETLIB_RESET(QBJT_EB)

View File

@ -63,13 +63,13 @@ NETLIB_UPDATE(VCCS)
/* only called if connected to a rail net ==> notify the solver to recalculate */
/* Big FIXME ... */
if (!m_IP.net().isRailNet())
m_IP.net().as_analog().schedule_solve();
m_IP.schedule_solve();
else if (!m_IN.net().isRailNet())
m_IN.net().as_analog().schedule_solve();
m_IN.schedule_solve();
else if (!m_OP.net().isRailNet())
m_OP.net().as_analog().schedule_solve();
m_OP.schedule_solve();
else if (!m_ON.net().isRailNet())
m_ON.net().as_analog().schedule_solve();
m_ON.schedule_solve();
}
// ----------------------------------------------------------------------------------------

View File

@ -205,6 +205,10 @@ public:
ATTR_HOT inline bool is_timestep() { return m_step_devices.count() > 0; }
ATTR_HOT void update_forced();
ATTR_HOT inline void update_after(const netlist_time after)
{
m_Q_sync.net().reschedule_in_queue(after);
}
/* netdevice functions */
ATTR_HOT virtual void update();

View File

@ -60,9 +60,9 @@ NETLIB_UPDATE(twoterm)
/* only called if connected to a rail net ==> notify the solver to recalculate */
/* we only need to call the non-rail terminal */
if (!m_P.net().isRailNet())
m_P.net().as_analog().schedule_solve();
m_P.schedule_solve();
else
m_N.net().as_analog().schedule_solve();
m_N.schedule_solve();
}
// ----------------------------------------------------------------------------------------

View File

@ -87,12 +87,51 @@ NETLIB_UPDATE_PARAM(analog_input)
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
ATTR_COLD void nld_d_to_a_proxy::start()
{
nld_base_d_to_a_proxy::start();
register_sub(m_RV, "RV");
register_terminal("1", m_RV.m_P);
register_terminal("2", m_RV.m_N);
register_output("_Q", m_Q);
register_subalias("Q", m_RV.m_P);
connect(m_RV.m_N, m_Q);
m_Q.initial(0.0);
}
ATTR_COLD void nld_d_to_a_proxy::reset()
{
m_RV.do_reset();
}
ATTR_COLD netlist_core_terminal_t &nld_d_to_a_proxy::out()
{
return m_RV.m_P;
}
ATTR_HOT ATTR_ALIGN void nld_d_to_a_proxy::update()
{
double R = INPLOGIC(m_I) ? m_family_desc->m_R_high : m_family_desc->m_R_low;
double V = INPLOGIC(m_I) ? m_family_desc->m_high_V : m_family_desc->m_low_V;
const int state = INPLOGIC(m_I);
if (state != m_last_state)
{
m_last_state = state;
const double R = state ? m_family_desc->m_R_high : m_family_desc->m_R_low;
const double V = state ? m_family_desc->m_high_V : m_family_desc->m_low_V;
m_R.update_dev();
OUTANALOG(m_Q, V);
m_R.set_R(R);
// We only need to update the net first if this is a time stepping net
if (m_RV.m_P.net().as_analog().solver()->is_timestep())
{
m_RV.update_dev();
m_RV.set(1.0 / R, V, 0.0);
m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
}
else
{
m_RV.set(1.0 / R, V, 0.0);
m_RV.update_dev();
}
}
}

View File

@ -225,39 +225,27 @@ class nld_d_to_a_proxy : public nld_base_d_to_a_proxy
{
public:
ATTR_COLD nld_d_to_a_proxy(netlist_output_t &out_proxied)
: nld_base_d_to_a_proxy(out_proxied)
: nld_base_d_to_a_proxy(out_proxied)
, m_RV(TWOTERM)
, m_last_state(-1)
{
}
ATTR_COLD virtual ~nld_d_to_a_proxy() {}
protected:
ATTR_COLD void start()
{
nld_base_d_to_a_proxy::start();
ATTR_COLD virtual void start();
register_sub(m_R, "R");
register_output("_Q", m_Q);
register_subalias("Q", m_R.m_P);
ATTR_COLD virtual void reset();
connect(m_R.m_N, m_Q);
}
ATTR_COLD void reset()
{
m_R.do_reset();
}
ATTR_COLD virtual netlist_core_terminal_t &out()
{
return m_R.m_P;
}
ATTR_COLD virtual netlist_core_terminal_t &out();
ATTR_HOT ATTR_ALIGN void update();
private:
netlist_analog_output_t m_Q;
nld_R_base m_R;
nld_twoterm m_RV;
int m_last_state;
};
#endif

View File

@ -356,7 +356,7 @@ ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE(
// ----------------------------------------------------------------------------------------
// net_device_t
// netlist_device_t
// ----------------------------------------------------------------------------------------
netlist_device_t::netlist_device_t()
@ -448,7 +448,7 @@ template ATTR_COLD void netlist_device_t::register_param(const pstring &sname, n
// ----------------------------------------------------------------------------------------
// net_net_t
// netlist_net_t
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_net_t::netlist_net_t(const family_t afamily)
@ -471,19 +471,11 @@ ATTR_COLD netlist_net_t::~netlist_net_t()
netlist().remove_save_items(this);
}
ATTR_COLD netlist_analog_net_t::netlist_analog_net_t()
: netlist_net_t(ANALOG)
, m_DD_n_m_1(0.0)
, m_h_n_m_1(1e-6)
, m_solver(NULL)
ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname)
{
};
ATTR_COLD netlist_logic_net_t::netlist_logic_net_t()
: netlist_net_t(LOGIC)
{
};
netlist_object_t::init_object(nl, aname);
nl.m_nets.add(this);
}
ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term)
{
@ -530,6 +522,12 @@ ATTR_HOT void netlist_net_t::dec_active(netlist_core_terminal_t &term)
}
}
ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr)
{
assert(m_railterminal == NULL);
m_railterminal = &mr;
}
ATTR_COLD void netlist_net_t::rebuild_list()
{
/* rebuild m_list */
@ -540,6 +538,64 @@ ATTR_COLD void netlist_net_t::rebuild_list()
m_list_active.add(*m_core_terms[i]);
}
ATTR_COLD void netlist_net_t::save_register()
{
save(NAME(m_time));
save(NAME(m_active));
save(NAME(m_in_queue));
save(NAME(m_last_Analog));
save(NAME(m_cur_Analog));
save(NAME(m_last_Q));
save(NAME(m_cur_Q));
save(NAME(m_new_Q));
netlist_object_t::save_register();
}
ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask)
{
if ((inp->state() & mask) != 0)
{
netlist_core_device_t &netdev = inp->netdev();
begin_timing(netdev.total_time);
inc_stat(netdev.stat_count);
netdev.update_dev();
end_timing(netdev().total_time);
}
}
ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs()
{
//assert(m_num_cons != 0);
assert(this->isRailNet());
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_list_active.first();
m_in_queue = 2; /* mark as taken ... */
m_cur_Q = m_new_Q;
switch (m_active)
{
case 2:
update_dev(p, mask);
p = m_list_active.next(p);
if (p == NULL) break;
case 1:
update_dev(p, mask);
break;
default:
while (p != NULL)
{
update_dev(p, mask);
p = m_list_active.next(p);
}
break;
}
m_last_Q = m_cur_Q;
m_last_Analog = m_cur_Analog;
}
ATTR_COLD void netlist_net_t::reset()
{
m_time = netlist_time::zero;
@ -566,51 +622,24 @@ ATTR_COLD void netlist_net_t::reset()
m_active++;
}
ATTR_COLD void netlist_logic_net_t::reset()
ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal)
{
netlist_net_t::reset();
terminal.set_net(*this);
m_core_terms.add(&terminal);
if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE)
m_active++;
}
ATTR_COLD void netlist_analog_net_t::reset()
ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net)
{
netlist_net_t::reset();
}
ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname)
{
netlist_object_t::init_object(nl, aname);
nl.m_nets.add(this);
}
ATTR_COLD void netlist_net_t::save_register()
{
save(NAME(m_time));
save(NAME(m_active));
save(NAME(m_in_queue));
save(NAME(m_last_Analog));
save(NAME(m_cur_Analog));
save(NAME(m_last_Q));
save(NAME(m_cur_Q));
save(NAME(m_new_Q));
netlist_object_t::save_register();
}
ATTR_COLD void netlist_analog_net_t::save_register()
{
save(NAME(m_DD_n_m_1));
save(NAME(m_h_n_m_1));
netlist_net_t::save_register();
}
ATTR_COLD void netlist_logic_net_t::save_register()
{
netlist_net_t::save_register();
}
ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr)
{
assert(m_railterminal == NULL);
m_railterminal = &mr;
for (int i = 0; i < m_core_terms.count(); i++)
{
netlist_core_terminal_t *p = m_core_terms[i];
dest_net->register_con(*p);
}
m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory
}
ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet)
@ -639,14 +668,48 @@ ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet)
}
}
ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net)
// ----------------------------------------------------------------------------------------
// netlist_logic_net_t
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_logic_net_t::netlist_logic_net_t()
: netlist_net_t(LOGIC)
{
for (int i = 0; i < m_core_terms.count(); i++)
{
netlist_core_terminal_t *p = m_core_terms[i];
dest_net->register_con(*p);
}
m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory
};
ATTR_COLD void netlist_logic_net_t::reset()
{
netlist_net_t::reset();
}
ATTR_COLD void netlist_logic_net_t::save_register()
{
netlist_net_t::save_register();
}
// ----------------------------------------------------------------------------------------
// netlist_analog_net_t
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_analog_net_t::netlist_analog_net_t()
: netlist_net_t(ANALOG)
, m_DD_n_m_1(0.0)
, m_h_n_m_1(1e-6)
, m_solver(NULL)
{
};
ATTR_COLD void netlist_analog_net_t::reset()
{
netlist_net_t::reset();
}
ATTR_COLD void netlist_analog_net_t::save_register()
{
save(NAME(m_DD_n_m_1));
save(NAME(m_h_n_m_1));
netlist_net_t::save_register();
}
ATTR_COLD bool netlist_analog_net_t::already_processed(list_t *groups, int cur_group)
@ -684,70 +747,8 @@ ATTR_COLD void netlist_analog_net_t::process_net(list_t *groups, int &cur_group)
}
ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal)
{
terminal.set_net(*this);
m_core_terms.add(&terminal);
if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE)
m_active++;
}
ATTR_HOT ATTR_ALIGN static inline void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask)
{
if ((inp->state() & mask) != 0)
{
netlist_core_device_t &netdev = inp->netdev();
begin_timing(netdev.total_time);
inc_stat(netdev.stat_count);
netdev.update_dev();
end_timing(netdev().total_time);
}
}
ATTR_HOT ATTR_ALIGN inline void netlist_net_t::update_devs()
{
//assert(m_num_cons != 0);
assert(this->isRailNet());
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_list_active.first();
m_in_queue = 2; /* mark as taken ... */
m_cur_Q = m_new_Q;
switch (m_active)
{
case 2:
update_dev(p, mask);
p = m_list_active.next(p);
if (p == NULL) break;
case 1:
update_dev(p, mask);
break;
default:
while (p != NULL)
{
update_dev(p, mask);
p = m_list_active.next(p);
}
break;
}
m_last_Q = m_cur_Q;
m_last_Analog = m_cur_Analog;
}
ATTR_HOT void netlist_analog_net_t::schedule_solve()
{
if (m_solver != NULL)
m_solver->update_forced();
}
// ----------------------------------------------------------------------------------------
// netlist_terminal_t
// netlist_core_terminal_t
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, const family_t afamily)
@ -759,6 +760,15 @@ ATTR_COLD netlist_core_terminal_t::netlist_core_terminal_t(const type_t atype, c
{
}
ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet)
{
m_net = &anet;
}
// ----------------------------------------------------------------------------------------
// netlist_terminal_t
// ----------------------------------------------------------------------------------------
ATTR_COLD netlist_terminal_t::netlist_terminal_t()
: netlist_core_terminal_t(TERMINAL, ANALOG)
, m_Idr1(NULL)
@ -768,6 +778,15 @@ ATTR_COLD netlist_terminal_t::netlist_terminal_t()
{
}
ATTR_HOT void netlist_terminal_t::schedule_solve()
{
net().as_analog().solver()->update_forced();
}
ATTR_HOT void netlist_terminal_t::schedule_after(const netlist_time &after)
{
net().as_analog().solver()->update_after(after);
}
ATTR_COLD void netlist_terminal_t::reset()
{
@ -787,11 +806,6 @@ ATTR_COLD void netlist_terminal_t::save_register()
}
ATTR_COLD void netlist_core_terminal_t::set_net(netlist_net_t &anet)
{
m_net = &anet;
}
// ----------------------------------------------------------------------------------------
// net_input_t
// ----------------------------------------------------------------------------------------

View File

@ -296,18 +296,19 @@ public:
};
enum family_t {
// Terminal families
LOGIC = 1,
ANALOG = 2,
LOGIC,
ANALOG,
// Device families
GENERIC = 3, // <== devices usually fall into this category
RESISTOR = 4, // Resistor
CAPACITOR = 5, // Capacitor
DIODE = 6, // Diode
BJT_SWITCH = 7, // BJT(Switch)
VCVS = 8, // Voltage controlled voltage source
VCCS = 9, // Voltage controlled current source
BJT_EB = 10, // BJT(Ebers-Moll)
GND = 11, // GND device
GENERIC, // <== devices usually fall into this category
TWOTERM, // Generic twoterm ...
RESISTOR, // Resistor
CAPACITOR, // Capacitor
DIODE, // Diode
BJT_EB, // BJT(Ebers-Moll)
BJT_SWITCH, // BJT(Switch)
VCVS, // Voltage controlled voltage source
VCCS, // Voltage controlled current source
GND, // GND device
};
ATTR_COLD netlist_object_t(const type_t atype, const family_t afamily);
@ -458,6 +459,8 @@ public:
set_ptr(m_gt1, GT);
}
ATTR_HOT void schedule_solve();
ATTR_HOT void schedule_after(const netlist_time &after);
netlist_terminal_t *m_otherterm;
@ -715,7 +718,7 @@ public:
return m_cur_Analog;
}
ATTR_HOT void schedule_solve();
ATTR_HOT inline netlist_matrix_solver_t *solver() { return m_solver; }
ATTR_COLD bool already_processed(list_t *groups, int cur_group);
ATTR_COLD void process_net(list_t *groups, int &cur_group);
@ -734,8 +737,6 @@ public:
//FIXME: needed by current solver code
netlist_matrix_solver_t *m_solver;
// netlist_terminal_t::list_t m_terms;
// netlist_terminal_t::list_t m_rails;
};
// ----------------------------------------------------------------------------------------
@ -964,7 +965,12 @@ public:
out.set_Q(val, delay);
}
ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const
ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const
{
return (inp.last_Q() != inp.Q());
}
ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const
{
return ((inp.last_Q() & !inp.Q()) == 1);
}