mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
Implemented an improved solving scheme into netlist. This improves performance for pong. However, it revealed issues around resetting netlist. "Reset(F3)" does not work properly now.
Also set pong frequency to NETLIST_CLOCK. This is necessary to avoid issues with time conversion into attotime and consequently rounding issues in fixfreq.
This commit is contained in:
parent
f28670c9e0
commit
9a3fd8d1fd
@ -69,41 +69,42 @@ NETLIB_START(QBJT_switch)
|
||||
|
||||
m_state_on = 0;
|
||||
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
|
||||
double alpha = BF / (1.0 + BF);
|
||||
|
||||
diode d(IS, NF);
|
||||
|
||||
// Assume 5mA Collector current for switch operation
|
||||
|
||||
m_V = d.V(0.005 / alpha);
|
||||
|
||||
/* Base current is 0.005 / beta
|
||||
* as a rough estimate, we just scale the conductance down */
|
||||
|
||||
m_gB = d.gI(0.005 / alpha) / BF;
|
||||
|
||||
if (m_gB < NETLIST_GMIN)
|
||||
m_gB = NETLIST_GMIN;
|
||||
m_gC = BF * m_gB; // very rough estimate
|
||||
//printf("%f %f \n", m_V, m_gB);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(Q)
|
||||
{
|
||||
netlist().solver()->schedule();
|
||||
netlist().solver()->schedule1();
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(QBJT_switch)
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
|
||||
double alpha = BF / (1.0 + BF);
|
||||
|
||||
diode d(IS, NF);
|
||||
|
||||
// Assume 5mA Collector current for switch operation
|
||||
|
||||
m_V = d.V(0.005 / alpha);
|
||||
|
||||
/* Base current is 0.005 / beta
|
||||
* as a rough estimate, we just scale the conductance down */
|
||||
|
||||
m_gB = d.gI(0.005 / alpha) / BF;
|
||||
|
||||
if (m_gB < NETLIST_GMIN)
|
||||
m_gB = NETLIST_GMIN;
|
||||
m_gC = BF * m_gB; // very rough estimate
|
||||
//printf("%f %f \n", m_V, m_gB);
|
||||
m_RB.set(NETLIST_GMIN, 0.0, 0.0);
|
||||
m_RC.set(NETLIST_GMIN, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -136,25 +137,37 @@ NETLIB_START(QBJT_EB)
|
||||
m_gD_BE.save("m_D_BE", *this);
|
||||
m_gD_BC.save("m_D_BC", *this);
|
||||
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
double BR = m_model.model_value("BR", 1);
|
||||
double NR = m_model.model_value("NR", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
|
||||
m_alpha_f = BF / (1.0 + BF);
|
||||
m_alpha_r = BR / (1.0 + BR);
|
||||
|
||||
m_gD_BE.set_param(IS / m_alpha_f, NF);
|
||||
m_gD_BC.set_param(IS / m_alpha_r, NR);
|
||||
}
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(QBJT_EB)
|
||||
{
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
m_D_BE.m_P.net().solve();
|
||||
m_D_BE.m_N.net().solve();
|
||||
m_D_BC.m_P.net().solve();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
NETLIB_UPDATE_PARAM(QBJT_EB)
|
||||
{
|
||||
double IS = m_model.model_value("IS", 1e-15);
|
||||
double BF = m_model.model_value("BF", 100);
|
||||
double NF = m_model.model_value("NF", 1);
|
||||
double BR = m_model.model_value("BR", 1);
|
||||
double NR = m_model.model_value("NR", 1);
|
||||
//double VJE = m_model.dValue("VJE", 0.75);
|
||||
|
||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||
|
||||
m_alpha_f = BF / (1.0 + BF);
|
||||
m_alpha_r = BR / (1.0 + BR);
|
||||
|
||||
m_gD_BE.set_param(IS / m_alpha_f, NF);
|
||||
m_gD_BC.set_param(IS / m_alpha_r, NR);
|
||||
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,7 @@ protected:
|
||||
|
||||
ATTR_COLD virtual void start();
|
||||
ATTR_HOT void update_param();
|
||||
ATTR_HOT ATTR_ALIGN void virtual update();
|
||||
|
||||
netlist_generic_diode m_gD_BC;
|
||||
netlist_generic_diode m_gD_BE;
|
||||
|
@ -55,7 +55,14 @@ NETLIB_UPDATE_PARAM(VCCS)
|
||||
NETLIB_UPDATE(VCCS)
|
||||
{
|
||||
/* only called if connected to a rail net ==> notify the solver to recalculate */
|
||||
netlist().solver()->schedule();
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
m_IP.net().solve();
|
||||
m_IN.net().solve();
|
||||
m_OP.net().solve();
|
||||
m_ON.net().solve();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -186,6 +186,23 @@ ATTR_HOT inline bool netlist_matrix_solver_t::solve()
|
||||
return m_resched;
|
||||
}
|
||||
|
||||
ATTR_HOT void netlist_matrix_solver_t::schedule()
|
||||
{
|
||||
if (!solve())
|
||||
{
|
||||
// printf("update_inputs\n");
|
||||
update_inputs();
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("resched\n");
|
||||
if (m_owner != NULL) this->m_owner->schedule1();
|
||||
}
|
||||
//solve();
|
||||
// update_inputs();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// solver
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -275,6 +292,9 @@ NETLIB_UPDATE(solver)
|
||||
{
|
||||
netlist_time now = netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
bool do_full = (USE_ALTERNATE_SCHEDULING ? false : true);
|
||||
bool global_resched = false;
|
||||
bool this_resched[100];
|
||||
|
||||
if (delta >= m_inc)
|
||||
{
|
||||
@ -285,9 +305,9 @@ NETLIB_UPDATE(solver)
|
||||
{
|
||||
(*e)->step(delta);
|
||||
}
|
||||
}
|
||||
bool global_resched = false;
|
||||
bool this_resched[100];
|
||||
} else
|
||||
do_full = true; // we have been called inbetween updates
|
||||
|
||||
|
||||
#if HAS_OPENMP && USE_OPENMP
|
||||
int t_cnt = m_mat_solvers.count();
|
||||
@ -305,19 +325,24 @@ NETLIB_UPDATE(solver)
|
||||
#else
|
||||
for (int i = 0; i < m_mat_solvers.count(); i++)
|
||||
{
|
||||
this_resched[i] = m_mat_solvers[i]->solve();
|
||||
if (do_full || (m_mat_solvers[i]->is_timestep()))
|
||||
this_resched[i] = m_mat_solvers[i]->solve();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < m_mat_solvers.count(); i++)
|
||||
{
|
||||
if (do_full || m_mat_solvers[i]->is_timestep())
|
||||
{
|
||||
global_resched = global_resched || this_resched[i];
|
||||
if (!this_resched[i])
|
||||
m_mat_solvers[i]->update_inputs();
|
||||
}
|
||||
}
|
||||
|
||||
if (global_resched)
|
||||
{
|
||||
schedule();
|
||||
schedule1();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
typedef netlist_list_t<netlist_matrix_solver_t *> list_t;
|
||||
typedef netlist_core_device_t::list_t dev_list_t;
|
||||
|
||||
netlist_matrix_solver_t() : m_resched(false) {}
|
||||
netlist_matrix_solver_t() : m_resched(false), m_owner(NULL) {}
|
||||
|
||||
ATTR_COLD void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner);
|
||||
|
||||
@ -40,6 +40,8 @@ public:
|
||||
ATTR_HOT void step(const netlist_time delta);
|
||||
ATTR_HOT void update_inputs();
|
||||
|
||||
ATTR_HOT void schedule();
|
||||
|
||||
ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; }
|
||||
ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; }
|
||||
|
||||
@ -83,7 +85,7 @@ public:
|
||||
|
||||
ATTR_COLD ~NETLIB_NAME(solver)();
|
||||
|
||||
ATTR_HOT inline void schedule();
|
||||
ATTR_HOT inline void schedule1();
|
||||
|
||||
ATTR_COLD void post_start();
|
||||
ATTR_COLD void reset()
|
||||
@ -92,7 +94,7 @@ public:
|
||||
}
|
||||
);
|
||||
|
||||
ATTR_HOT inline void NETLIB_NAME(solver)::schedule()
|
||||
ATTR_HOT inline void NETLIB_NAME(solver)::schedule1()
|
||||
{
|
||||
if (!m_Q_sync.net().is_queued())
|
||||
m_Q_sync.net().push_to_queue(m_nt_sync_delay);
|
||||
|
@ -44,6 +44,9 @@ NETLIB_UPDATE_PARAM(switch2)
|
||||
m_R[0].set_R(R_OFF);
|
||||
m_R[1].set_R(R_ON);
|
||||
}
|
||||
m_R[0].update_dev();
|
||||
m_R[1].update_dev();
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
m_R[0].update_dev();
|
||||
m_R[1].update_dev();
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,13 @@ NETLIB_START(twoterm)
|
||||
NETLIB_UPDATE(twoterm)
|
||||
{
|
||||
/* only called if connected to a rail net ==> notify the solver to recalculate */
|
||||
netlist().solver()->schedule();
|
||||
#if !(USE_ALTERNATE_SCHEDULING)
|
||||
netlist().solver()->schedule1();
|
||||
#else
|
||||
/* we only need to call the non-rail terminal */
|
||||
m_P.net().solve();
|
||||
m_N.net().solve();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -57,6 +63,8 @@ NETLIB_UPDATE_PARAM(R)
|
||||
{
|
||||
//printf("updating %s to %f\n", name().cstr(), m_R.Value());
|
||||
set_R(m_R.Value());
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
update_dev();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -93,7 +101,14 @@ NETLIB_UPDATE_PARAM(POT)
|
||||
v = (exp(v) - 1.0) / (exp(1.0) - 1.0);
|
||||
m_R1.set_R(MAX(m_R.Value() * v, NETLIST_GMIN));
|
||||
m_R2.set_R(MAX(m_R.Value() * (1.0 - v), NETLIST_GMIN));
|
||||
// force a schedule all
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
m_R1.update_dev();
|
||||
m_R2.update_dev();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nld_C
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -104,12 +119,14 @@ NETLIB_START(C)
|
||||
register_terminal("2", m_N);
|
||||
|
||||
register_param("C", m_C, 1e-6);
|
||||
|
||||
// set up the element
|
||||
set(m_C.Value() / 1e-9, 0.0, 0.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(C)
|
||||
{
|
||||
// set to some very small step time for now
|
||||
step_time(1e-9);
|
||||
//step_time(1e-9);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(C)
|
||||
|
@ -160,7 +160,10 @@ protected:
|
||||
class netlist_generic_diode
|
||||
{
|
||||
public:
|
||||
netlist_generic_diode() {}
|
||||
netlist_generic_diode()
|
||||
{
|
||||
m_Vd = 0.7;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void update_diode(const double nVd)
|
||||
{
|
||||
@ -205,8 +208,6 @@ public:
|
||||
|
||||
m_Vcrit = m_Vt * log(m_Vt / m_Is / sqrt(2.0));
|
||||
m_VtInv = 1.0 / m_Vt;
|
||||
|
||||
m_Vd = 0.7;
|
||||
}
|
||||
|
||||
ATTR_HOT inline double I() { return m_Id; }
|
||||
|
@ -137,6 +137,8 @@ NETLIB_FUNC_VOID(nic7448_sub, update_outputs, (UINT8 v))
|
||||
assert(v<16);
|
||||
if (v != m_state)
|
||||
{
|
||||
// max transfer time is 100 NS */
|
||||
|
||||
OUTLOGIC(m_a, tab7448[v][0], NLTIME_FROM_NS(100));
|
||||
OUTLOGIC(m_b, tab7448[v][1], NLTIME_FROM_NS(100));
|
||||
OUTLOGIC(m_c, tab7448[v][2], NLTIME_FROM_NS(100));
|
||||
|
@ -18,11 +18,12 @@ NETLIB_START(ttl_const)
|
||||
|
||||
NETLIB_UPDATE(ttl_const)
|
||||
{
|
||||
OUTLOGIC(m_Q, m_const.Value(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(ttl_const)
|
||||
{
|
||||
OUTLOGIC(m_Q, m_const.Value(), NLTIME_IMMEDIATE);
|
||||
OUTLOGIC(m_Q, m_const.Value(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_START(analog_const)
|
||||
@ -33,6 +34,7 @@ NETLIB_START(analog_const)
|
||||
|
||||
NETLIB_UPDATE(analog_const)
|
||||
{
|
||||
OUTANALOG(m_Q, m_const.Value(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(analog_const)
|
||||
@ -79,6 +81,7 @@ NETLIB_START(logic_input)
|
||||
|
||||
NETLIB_UPDATE(logic_input)
|
||||
{
|
||||
OUTLOGIC(m_Q, m_OUT.Value() & 1, NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(logic_input)
|
||||
@ -98,6 +101,7 @@ NETLIB_START(analog_input)
|
||||
|
||||
NETLIB_UPDATE(analog_input)
|
||||
{
|
||||
OUTANALOG(m_Q, m_OUT.Value(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(analog_input)
|
||||
|
@ -174,19 +174,19 @@ ATTR_COLD void netlist_base_t::reset()
|
||||
if (m_solver != NULL)
|
||||
m_solver->reset();
|
||||
|
||||
// FIXME: some const devices rely on this
|
||||
/* make sure params are set now .. */
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
entry->object()->update_param();
|
||||
}
|
||||
|
||||
// Step all devices once !
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
netlist_device_t *dev = entry->object();
|
||||
dev->update_dev();
|
||||
}
|
||||
|
||||
// FIXME: some const devices rely on this
|
||||
/* make sure params are set now .. */
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
entry->object()->update_param();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -535,6 +535,12 @@ ATTR_HOT inline void netlist_net_t::update_devs()
|
||||
m_last = m_cur;
|
||||
}
|
||||
|
||||
ATTR_HOT void netlist_net_t::solve()
|
||||
{
|
||||
if (m_solver != NULL)
|
||||
m_solver->schedule();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_terminal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -605,6 +605,8 @@ public:
|
||||
terminal_list_t m_terms;
|
||||
netlist_matrix_solver_t *m_solver;
|
||||
|
||||
ATTR_HOT void solve();
|
||||
|
||||
netlist_core_terminal_t *m_head;
|
||||
|
||||
/* use this to register state.... */
|
||||
|
@ -34,6 +34,8 @@
|
||||
#define NETLIST_INTERNAL_RES (U64(1000000000))
|
||||
//#define NETLIST_INTERNAL_RES (U64(1000000000000))
|
||||
|
||||
#define USE_ALTERNATE_SCHEDULING (1)
|
||||
|
||||
#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
|
||||
|
||||
#define NETLIST_GMIN (1e-9)
|
||||
@ -119,7 +121,7 @@ typedef UINT8 netlist_sig_t;
|
||||
//============================================================
|
||||
|
||||
#if (USE_OPENMP)
|
||||
#if (!HAS_OPEN_MP)
|
||||
#if (!(HAS_OPENMP))
|
||||
#warning To use openmp compile and link with "-fopenmp"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define NLTIME_FROM_NS(_t) netlist_time::from_nsec(_t)
|
||||
#define NLTIME_FROM_US(_t) netlist_time::from_usec(_t)
|
||||
#define NLTIME_FROM_MS(_t) netlist_time::from_msec(_t)
|
||||
#define NLTIME_IMMEDIATE netlist_time::from_nsec(0)
|
||||
#define NLTIME_IMMEDIATE netlist_time::from_nsec(1)
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_list_time
|
||||
|
@ -758,7 +758,8 @@ INPUT_PORTS_END
|
||||
static MACHINE_CONFIG_START( pong, pong_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_NETLIST_ADD("maincpu", pong, MASTER_CLOCK * 2)
|
||||
//MCFG_NETLIST_ADD("maincpu", pong, MASTER_CLOCK * 8)
|
||||
MCFG_NETLIST_ADD("maincpu", pong, NETLIST_CLOCK)
|
||||
MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr0", "ic_b9_R.R")
|
||||
MCFG_NETLIST_ANALOG_INPUT_MULT_OFFSET(1.0 / 100.0 * RES_K(50), RES_K(56) )
|
||||
MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr1", "ic_a9_R.R")
|
||||
|
Loading…
Reference in New Issue
Block a user