Optimized some netlist code by inlining clock device. This improves pongf performance by approx. 10%.

This commit is contained in:
Couriersud 2013-10-06 17:18:23 +00:00
parent ac0df6a72b
commit b24c31f64f
5 changed files with 298 additions and 214 deletions

View File

@ -84,7 +84,7 @@ NETLIB_UPDATE_PARAM(netdev_clock)
NETLIB_UPDATE(netdev_clock)
{
m_Q.setToNoCheckPS(!m_Q.new_Q(), m_inc );
m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
}
NETLIB_START(nicMultiSwitch)
@ -282,9 +282,9 @@ NETLIB_START(nic7404)
NETLIB_UPDATE(nic7404)
{
static netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
static const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
UINT8 t = (INPVAL(m_I)) ^ 1;
m_Q.setToPS(t, delay[t]);
m_Q.setTo(t, delay[t]);
}
NETLIB_START(nic7486)
@ -296,9 +296,9 @@ NETLIB_START(nic7486)
NETLIB_UPDATE(nic7486)
{
static netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
static const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
UINT8 t = INPVAL(m_I0) ^ INPVAL(m_I1);
m_Q.setToPS(t, delay[t]);
m_Q.setTo(t, delay[t]);
}
NETLIB_START(nic7448)
@ -335,13 +335,13 @@ NETLIB_UPDATE(nic7448)
assert(v<16);
if (v != m_state)
{
m_a.setToPS(tab7448[v][0], NLTIME_FROM_NS(100));
m_b.setToPS(tab7448[v][1], NLTIME_FROM_NS(100));
m_c.setToPS(tab7448[v][2], NLTIME_FROM_NS(100));
m_d.setToPS(tab7448[v][3], NLTIME_FROM_NS(100));
m_e.setToPS(tab7448[v][4], NLTIME_FROM_NS(100));
m_f.setToPS(tab7448[v][5], NLTIME_FROM_NS(100));
m_g.setToPS(tab7448[v][6], NLTIME_FROM_NS(100));
m_a.setTo(tab7448[v][0], NLTIME_FROM_NS(100));
m_b.setTo(tab7448[v][1], NLTIME_FROM_NS(100));
m_c.setTo(tab7448[v][2], NLTIME_FROM_NS(100));
m_d.setTo(tab7448[v][3], NLTIME_FROM_NS(100));
m_e.setTo(tab7448[v][4], NLTIME_FROM_NS(100));
m_f.setTo(tab7448[v][5], NLTIME_FROM_NS(100));
m_g.setTo(tab7448[v][6], NLTIME_FROM_NS(100));
m_state = v;
}
}
@ -380,15 +380,15 @@ NETLIB_UPDATE(nic7450)
UINT8 t1 = INPVAL(m_I0) & INPVAL(m_I1);
UINT8 t2 = INPVAL(m_I2) & INPVAL(m_I3);
UINT8 t = (t1 | t2) ^ 1;
m_Q.setToPS(t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
m_Q.setTo(t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
}
INLINE void nic7474_newstate(UINT8 state, ttl_output_t &Q, ttl_output_t &QQ)
INLINE void nic7474_newstate(const UINT8 state, ttl_output_t &Q, ttl_output_t &QQ)
{
static netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
static const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
//printf("%s %d %d %d\n", "7474", state, Q.Q(), QQ.Q());
Q.setToPS(state, delay[state]);
QQ.setToPS(!state, delay[!state]);
Q.setTo(state, delay[state]);
QQ.setTo(!state, delay[!state]);
}
#if 0
@ -499,11 +499,11 @@ NETLIB_UPDATE(nic7483)
if (r != m_lastr)
{
m_lastr = r;
m_SA.setToPS((r >> 0) & 1, NLTIME_FROM_NS(23));
m_SB.setToPS((r >> 1) & 1, NLTIME_FROM_NS(23));
m_SC.setToPS((r >> 2) & 1, NLTIME_FROM_NS(23));
m_SD.setToPS((r >> 3) & 1, NLTIME_FROM_NS(23));
m_CO.setToPS((r >> 4) & 1, NLTIME_FROM_NS(23));
m_SA.setTo((r >> 0) & 1, NLTIME_FROM_NS(23));
m_SB.setTo((r >> 1) & 1, NLTIME_FROM_NS(23));
m_SC.setTo((r >> 2) & 1, NLTIME_FROM_NS(23));
m_SD.setTo((r >> 3) & 1, NLTIME_FROM_NS(23));
m_CO.setTo((r >> 4) & 1, NLTIME_FROM_NS(23));
}
}
@ -546,17 +546,17 @@ NETLIB_UPDATE(nic7490)
#if 0
NETLIB_FUNC_VOID(nic7490, update_outputs)
{
m_QA.setToPS((m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
m_QB.setToPS((m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
m_QC.setToPS((m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
m_QD.setToPS((m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
m_QA.setTo((m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
m_QB.setTo((m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
m_QC.setTo((m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
m_QD.setTo((m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
}
#else
NETLIB_FUNC_VOID(nic7490, update_outputs)
{
static netlist_time delay[4] = { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54), NLTIME_FROM_NS(72) };
static const netlist_time delay[4] = { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54), NLTIME_FROM_NS(72) };
for (int i=0; i<4; i++)
m_Q[i].setToPS((m_cnt >> i) & 1, delay[i]);
m_Q[i].setTo((m_cnt >> i) & 1, delay[i]);
//m_QA.setToPS((m_cnt >> 0) & 1, delay[0]);
//m_QB.setToPS((m_cnt >> 1) & 1, delay[1]);
@ -591,7 +591,7 @@ NETLIB_START(nic7493)
NETLIB_UPDATE(nic7493ff)
{
//if INP_LAST(m_I) && !INP(m_I))
m_Q.setToNoCheckPS(!m_Q.new_Q(), NLTIME_FROM_NS(18));
m_Q.setToNoCheck(!m_Q.new_Q(), NLTIME_FROM_NS(18));
}
NETLIB_UPDATE(nic7493)
@ -605,10 +605,10 @@ NETLIB_UPDATE(nic7493)
B.m_I.inactivate();
C.m_I.inactivate();
D.m_I.inactivate();
A.m_Q.setToPS(0, NLTIME_FROM_NS(40));
B.m_Q.setToPS(0, NLTIME_FROM_NS(40));
C.m_Q.setToPS(0, NLTIME_FROM_NS(40));
D.m_Q.setToPS(0, NLTIME_FROM_NS(40));
A.m_Q.setTo(0, NLTIME_FROM_NS(40));
B.m_Q.setTo(0, NLTIME_FROM_NS(40));
C.m_Q.setTo(0, NLTIME_FROM_NS(40));
D.m_Q.setTo(0, NLTIME_FROM_NS(40));
}
else
{
@ -646,10 +646,10 @@ NETLIB_UPDATE(nic7493)
if (m_cnt > 0)
{
m_cnt = 0;
m_QA.setToPS(0, 40000);
m_QB.setToPS(0, 40000);
m_QC.setToPS(0, 40000);
m_QD.setToPS(0, 40000);
m_QA.setTo(0, 40000);
m_QB.setTo(0, 40000);
m_QC.setTo(0, 40000);
m_QD.setTo(0, 40000);
}
}
//else if (old_clk & !m_lastclk)
@ -664,32 +664,32 @@ NETLIB_UPDATE(nic7493)
NETLIB_FUNC_VOID(nic7493, update_outputs)
{
if (m_cnt & 1)
m_QA.setToNoCheckPS(1, 16000);
m_QA.setToNoCheck(1, 16000);
else
{
m_QA.setToNoCheckPS(0, 16000);
m_QA.setToNoCheck(0, 16000);
switch (m_cnt)
{
case 0x00:
m_QB.setToNoCheckPS(0, 34000);
m_QC.setToNoCheckPS(0, 48000);
m_QD.setToNoCheckPS(0, 70000);
m_QB.setToNoCheck(0, 34000);
m_QC.setToNoCheck(0, 48000);
m_QD.setToNoCheck(0, 70000);
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
m_QB.setToNoCheckPS(1, 34000);
m_QB.setToNoCheck(1, 34000);
break;
case 0x04:
case 0x0C:
m_QB.setToNoCheckPS(0, 34000);
m_QC.setToNoCheckPS(1, 48000);
m_QB.setToNoCheck(0, 34000);
m_QC.setToNoCheck(1, 48000);
break;
case 0x08:
m_QB.setToNoCheckPS(0, 34000);
m_QC.setToNoCheckPS(0, 48000);
m_QD.setToNoCheckPS(1, 70000);
m_QB.setToNoCheck(0, 34000);
m_QC.setToNoCheck(0, 48000);
m_QD.setToNoCheck(1, 70000);
break;
}
}
@ -717,13 +717,13 @@ INLINE void nic74107A_newstate(UINT8 state, ttl_output_t &Q, ttl_output_t &QQ)
{
if (state)
{
Q.setToNoCheckPS(1, NLTIME_FROM_NS(40));
QQ.setToNoCheckPS(0, NLTIME_FROM_NS(25));
Q.setToNoCheck(1, NLTIME_FROM_NS(40));
QQ.setToNoCheck(0, NLTIME_FROM_NS(25));
}
else
{
Q.setToNoCheckPS(0, NLTIME_FROM_NS(25));
QQ.setToNoCheckPS(1, NLTIME_FROM_NS(40));
Q.setToNoCheck(0, NLTIME_FROM_NS(25));
QQ.setToNoCheck(1, NLTIME_FROM_NS(40));
}
}
}
@ -793,11 +793,11 @@ NETLIB_UPDATE(nic74153)
{
UINT8 chan = (INPVAL(m_A) | (INPVAL(m_B)<<1));
UINT8 t = INPVAL(m_I[chan]);
m_AY.setToPS(t, t ? NLTIME_FROM_NS(18) : NLTIME_FROM_NS(23)); /* data to y only, FIXME */
m_AY.setTo(t, t ? NLTIME_FROM_NS(18) : NLTIME_FROM_NS(23)); /* data to y only, FIXME */
}
else
{
m_AY.setToPS(0, NLTIME_FROM_NS(23));
m_AY.setTo(0, NLTIME_FROM_NS(23));
}
}
@ -833,13 +833,13 @@ NETLIB_UPDATE(nic9316sub)
{
m_cnt = ( m_cnt + 1) & 0x0f;
update_outputs();
m_RC.setToPS(m_cnt == 0x0f, NLTIME_FROM_NS(20));
m_RC.setTo(m_cnt == 0x0f, NLTIME_FROM_NS(20));
}
else
{
m_cnt = (INPVAL_PASSIVE(m_D) << 3) | (INPVAL_PASSIVE(m_C) << 2) | (INPVAL_PASSIVE(m_B) << 1) | (INPVAL_PASSIVE(m_A) << 0);
update_outputs_all();
m_RC.setToPS(INPVAL(m_ENT) & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
m_RC.setTo(INPVAL(m_ENT) & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
}
}
@ -855,55 +855,55 @@ NETLIB_UPDATE(nic9316)
{
sub.m_cnt = 0;
sub.update_outputs();
sub.m_RC.setToPS(0, NLTIME_FROM_NS(20));
sub.m_RC.setTo(0, NLTIME_FROM_NS(20));
}
}
sub.m_RC.setToPS(INPVAL(sub.m_ENT) & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
sub.m_RC.setTo(INPVAL(sub.m_ENT) & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_FUNC_VOID(nic9316sub, update_outputs_all)
{
m_QA.setToPS((m_cnt >> 0) & 1, NLTIME_FROM_NS(20));
m_QB.setToPS((m_cnt >> 1) & 1, NLTIME_FROM_NS(20));
m_QC.setToPS((m_cnt >> 2) & 1, NLTIME_FROM_NS(20));
m_QD.setToPS((m_cnt >> 3) & 1, NLTIME_FROM_NS(20));
m_QA.setTo((m_cnt >> 0) & 1, NLTIME_FROM_NS(20));
m_QB.setTo((m_cnt >> 1) & 1, NLTIME_FROM_NS(20));
m_QC.setTo((m_cnt >> 2) & 1, NLTIME_FROM_NS(20));
m_QD.setTo((m_cnt >> 3) & 1, NLTIME_FROM_NS(20));
}
NETLIB_FUNC_VOID(nic9316sub, update_outputs)
{
#if 0
m_QA.setTo((m_cnt >> 0) & 1, 20);
m_QB.setTo((m_cnt >> 1) & 1, 20);
m_QC.setTo((m_cnt >> 2) & 1, 20);
m_QD.setTo((m_cnt >> 3) & 1, 20);
#if 1
m_QA.setTo((m_cnt >> 0) & 1, NLTIME_FROM_NS(20));
m_QB.setTo((m_cnt >> 1) & 1, NLTIME_FROM_NS(20));
m_QC.setTo((m_cnt >> 2) & 1, NLTIME_FROM_NS(20));
m_QD.setTo((m_cnt >> 3) & 1, NLTIME_FROM_NS(20));
#else
if ((m_cnt & 1) == 1)
m_QA.setToNoCheckPS(1, NLTIME_FROM_NS(20));
m_QA.setToNoCheck(1, NLTIME_FROM_NS(20));
else
{
m_QA.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QA.setToNoCheck(0, NLTIME_FROM_NS(20));
switch (m_cnt)
{
case 0x00:
m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QD.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheck(0, NLTIME_FROM_NS(20));
m_QD.setToNoCheck(0, NLTIME_FROM_NS(20));
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
m_QB.setToNoCheckPS(1, NLTIME_FROM_NS(20));
m_QB.setToNoCheck(1, NLTIME_FROM_NS(20));
break;
case 0x04:
case 0x0C:
m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheckPS(1, NLTIME_FROM_NS(20));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheck(1, NLTIME_FROM_NS(20));
break;
case 0x08:
m_QB.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheckPS(0, NLTIME_FROM_NS(20));
m_QD.setToNoCheckPS(1, NLTIME_FROM_NS(20));
m_QB.setToNoCheck(0, NLTIME_FROM_NS(20));
m_QC.setToNoCheck(0, NLTIME_FROM_NS(20));
m_QD.setToNoCheck(1, NLTIME_FROM_NS(20));
break;
}
@ -913,13 +913,14 @@ NETLIB_FUNC_VOID(nic9316sub, update_outputs)
#define ENTRY(_nic, _name) new net_device_t_factory< _nic >( # _name, # _nic ),
static net_device_t_base_factory *netregistry[] =
static const net_device_t_base_factory *netregistry[] =
{
ENTRY(netdev_ttl_const, NETDEV_TTL_CONST)
ENTRY(netdev_analog_const, NETDEV_ANALOG_CONST)
ENTRY(netdev_logic_input, NETDEV_LOGIC_INPUT)
ENTRY(netdev_analog_input, NETDEV_ANALOG_INPUT)
ENTRY(netdev_clock, NETDEV_CLOCK)
ENTRY(netdev_mainclock, NETDEV_MAINCLOCK)
ENTRY(netdev_callback, NETDEV_CALLBACK)
ENTRY(nicMultiSwitch, NETDEV_SWITCH2)
ENTRY(nicRSFF, NETDEV_RSFF)
@ -949,7 +950,7 @@ static net_device_t_base_factory *netregistry[] =
net_device_t *net_create_device_by_classname(const char *classname, netlist_setup_t *setup, const char *icname)
{
net_device_t_base_factory **p = &netregistry[0];
const net_device_t_base_factory **p = &netregistry[0];
while (p != NULL)
{
if (strcmp((*p)->classname(), classname) == 0)
@ -961,7 +962,7 @@ net_device_t *net_create_device_by_classname(const char *classname, netlist_setu
net_device_t *net_create_device_by_name(const char *name, netlist_setup_t *setup, const char *icname)
{
net_device_t_base_factory **p = &netregistry[0];
const net_device_t_base_factory **p = &netregistry[0];
while (p != NULL)
{
if (strcmp((*p)->name(), name) == 0)

View File

@ -54,6 +54,8 @@
// Special chips
// ----------------------------------------------------------------------------------------
#define NETDEV_MAINCLOCK(_name) \
NET_REGISTER_DEV(netdev_mainclock, _name)
#define NETDEV_CLOCK(_name) \
NET_REGISTER_DEV(netdev_clock, _name)
#define NETDEV_LOGIC_INPUT(_name) \
@ -432,10 +434,7 @@ NETLIB_DEVICE(nic7490,
UINT8 m_cnt;
ttl_output_t m_QA;
ttl_output_t m_QB;
ttl_output_t m_QC;
ttl_output_t m_QD;
ttl_output_t m_Q[4];
);
/* ripple-carry counter on low-high clock transition */

View File

@ -167,7 +167,7 @@ public:
dev = net_create_device_by_name(dev_type, &m_setup, devname);
m_setup.register_dev(dev);
skipws();
VERBOSE_OUT(("Parser: IC: %s\n", n));
VERBOSE_OUT(("Parser: IC: %s\n", devname));
cnt = 0;
while (*m_p != ')')
{
@ -307,9 +307,9 @@ public:
ATTR_HOT void update()
{
if (m_I.Q_Analog() > m_I.m_high_thresh_V)
m_Q.setToPS(1, NLTIME_FROM_NS(1));
m_Q.setTo(1, NLTIME_FROM_NS(1));
else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
m_Q.setToPS(0, NLTIME_FROM_NS(1));
m_Q.setTo(0, NLTIME_FROM_NS(1));
}
ATTR_COLD void start()
@ -340,7 +340,7 @@ NETLIB_UPDATE(netdev_ttl_const)
NETLIB_UPDATE_PARAM(netdev_ttl_const)
{
m_Q.setToPS(m_const.ValueInt(), NLTIME_IMMEDIATE);
m_Q.setTo(m_const.ValueInt(), NLTIME_IMMEDIATE);
}
NETLIB_START(netdev_analog_const)
@ -382,28 +382,66 @@ void netlist_base_t::set_clock_freq(UINT64 clockfreq)
ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
{
while ( (atime > 0) && (m_queue.is_not_empty()))
if (m_mainclock == NULL)
{
queue_t::entry_t e = m_queue.pop();
netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem);
while ( (atime > 0) && (m_queue.is_not_empty()))
{
queue_t::entry_t &e = m_queue.pop();
const netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem);
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
m_time_ps = e.time();
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
m_time_ps = e.time();
e.object()->update_devs();
e.object()->update_devs();
add_to_stat(m_perf_out_processed, 1);
add_to_stat(m_perf_list_len, m_end);
add_to_stat(m_perf_out_processed, 1);
}
if (atime > 0)
{
m_time_ps += netlist_time::from_raw(atime * m_div);
atime = 0;
}
} else {
net_output_t &mainclock_Q = m_mainclock->m_Q;
while (atime > 0)
{
if (m_queue.is_not_empty())
{
while (m_queue.peek().time() > mainclock_Q.time())
{
const netlist_time delta = mainclock_Q.time() - m_time_ps + netlist_time::from_raw(m_rem);
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
m_time_ps = mainclock_Q.time();
m_mainclock->update();
mainclock_Q.update_devs();
}
queue_t::entry_t &e = m_queue.pop();
const netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem);
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
m_time_ps = e.time();
e.object()->update_devs();
} else {
const netlist_time delta = mainclock_Q.time() - m_time_ps + netlist_time::from_raw(m_rem);
atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
m_time_ps = mainclock_Q.time();
m_mainclock->update();
mainclock_Q.update_devs();
}
add_to_stat(m_perf_out_processed, 1);
}
if (atime > 0)
{
m_time_ps += netlist_time::from_raw(atime * m_div);
atime = 0;
}
}
if (atime > 0)
{
m_time_ps += netlist_time::from_raw(atime * m_div);
atime = 0;
}
if (KEEP_STATISTICS)
printf("%f\n", (double) m_perf_list_len / (double) m_perf_out_processed);
//if (KEEP_STATISTICS)
// printf("%d\n", m_perf_out_processed);
}
// ----------------------------------------------------------------------------------------
@ -610,6 +648,16 @@ void netlist_setup_t::resolve_inputs(void)
entry->object()->netdev().update_param();
}
/* find the main clock ... */
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
{
net_device_t *dev = entry->object();
if (dynamic_cast<netdev_mainclock*>(dev) != NULL)
{
m_netlist.m_mainclock = dynamic_cast<netdev_mainclock*>(dev);
}
}
/* make sure all outputs are triggered once */
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
{
@ -656,9 +704,6 @@ ATTR_COLD void net_core_device_t::init_core(netlist_base_t *anetlist, const char
{
m_netlist = anetlist;
m_name = name;
#if USE_DELEGATES_A
h = net_update_delegate(&net_core_device_t::update, "update", this);
#endif
}
@ -777,18 +822,18 @@ ATTR_COLD void net_output_t::set_netdev(const net_core_device_t *dev)
m_netlist = dev->netlist();
}
static inline void update_dev(const net_input_t *inp, const UINT32 mask)
ATTR_HOT inline void net_output_t::update_dev(const net_input_t &inp, const UINT32 mask)
{
if ((inp->state() & mask) != 0)
if ((inp.state() & mask) != 0)
{
begin_timing(inp->netdev()->total_time);
inc_stat(inp->netdev()->stat_count);
begin_timing(inp.netdev()->total_time);
inc_stat(inp.netdev()->stat_count);
#if USE_DELEGATES
inp->h();
inp.h();
#else
inp->netdev()->update_device();
inp.netdev()->update();
#endif
end_timing(inp->netdev()->total_time);
end_timing(inp.netdev()->total_time);
}
}
@ -804,15 +849,16 @@ ATTR_HOT inline void net_output_t::update_devs()
switch (m_num_cons)
{
case 2:
update_dev(m_cons[1], mask);
update_dev(*m_cons[1], mask);
case 1:
update_dev(m_cons[0], mask);
update_dev(*m_cons[0], mask);
break;
default:
{
for (int i=0; i < m_num_cons; i++)
update_dev(m_cons[i], mask);
update_dev(*m_cons[i], mask);
}
break;
case 0:
break;
}
@ -834,7 +880,7 @@ ATTR_COLD void net_output_t::update_devs_force()
#if USE_DELEGATES
(*s)->h();
#else
(*s)->netdev()->update_device();
(*s)->netdev()->update();
#endif
s++;
}
@ -915,7 +961,6 @@ void netlist_mame_device::device_start()
m_setup->resolve_inputs();
//save_item(NAME(m_clockcnt));
save_state();
/* TODO: we have to save the round robin queue as well */

View File

@ -55,8 +55,7 @@
// SETUP
//============================================================
#define USE_DELEGATES (1)
#define USE_DELEGATES_A (0)
#define USE_DELEGATES (1)
#define NETLIST_CLOCK (U64(1000000000))
@ -92,6 +91,7 @@
#define NETLIST_START(_name) \
ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
{
#define NETLIST_END }
#define NETLIST_INCLUDE(_name) \
@ -99,6 +99,7 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
#define NETLIST_MEMREGION(_name) \
netlist.parse((char *)downcast<netlist_t &>(netlist.netlist()).machine().root_device().memregion(_name)->base());
#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
#define ATTR_ALIGN __attribute__ ((aligned(128)))
@ -170,7 +171,7 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
// ----------------------------------------------------------------------------------------
#if USE_DELEGATES || USE_DELEGATES_A
#if USE_DELEGATES
typedef delegate<void ()> net_update_delegate;
#endif
@ -200,57 +201,57 @@ public:
friend bool operator>=(const netlist_time &left, const netlist_time &right);
friend bool operator<=(const netlist_time &left, const netlist_time &right);
inline netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
inline netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
ATTR_HOT inline netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
ATTR_HOT inline netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
inline const INTERNALTYPE as_raw() const { return m_time; }
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
static inline const netlist_time from_ns(const int ns) { return netlist_time((UINT64) ns * RESOLUTION / U64(1000000000)); }
static inline const netlist_time from_us(const int us) { return netlist_time((UINT64) us * RESOLUTION / U64(1000000)); }
static inline const netlist_time from_ms(const int ms) { return netlist_time((UINT64) ms * RESOLUTION / U64(1000)); }
static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
ATTR_HOT static inline const netlist_time from_ns(const int ns) { return netlist_time((UINT64) ns * RESOLUTION / U64(1000000000)); }
ATTR_HOT static inline const netlist_time from_us(const int us) { return netlist_time((UINT64) us * RESOLUTION / U64(1000000)); }
ATTR_HOT static inline const netlist_time from_ms(const int ms) { return netlist_time((UINT64) ms * RESOLUTION / U64(1000)); }
ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
static const netlist_time zero;
protected:
inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
INTERNALTYPE m_time;
};
inline netlist_time operator-(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline netlist_time operator-(const netlist_time &left, const netlist_time &right)
{
return netlist_time::from_raw(left.m_time - right.m_time);
}
inline netlist_time operator*(const netlist_time &left, const UINT64 factor)
ATTR_HOT inline netlist_time operator*(const netlist_time &left, const UINT64 factor)
{
return netlist_time::from_raw(left.m_time * factor);
}
inline netlist_time operator+(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline netlist_time operator+(const netlist_time &left, const netlist_time &right)
{
return netlist_time::from_raw(left.m_time + right.m_time);
}
inline bool operator<(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
{
return (left.m_time < right.m_time);
}
inline bool operator>(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
{
return (left.m_time > right.m_time);
}
inline bool operator<=(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
{
return (left.m_time <= right.m_time);
}
inline bool operator>=(const netlist_time &left, const netlist_time &right)
ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
{
return (left.m_time >= right.m_time);
}
@ -305,6 +306,7 @@ public:
_QC m_object;
};
//static const int SIZE = ((1 << _Size) - 1);
netlist_timed_queue()
{
@ -314,7 +316,7 @@ public:
ATTR_HOT inline bool is_empty() { return ((m_start & SIZE) == (m_end & SIZE)); }
ATTR_HOT inline bool is_not_empty() { return ((m_start & SIZE) != (m_end & SIZE)); }
ATTR_HOT void push(const entry_t &e);
ATTR_HOT inline void push(const entry_t &e);
ATTR_HOT inline entry_t &pop()
{
@ -322,13 +324,18 @@ public:
return item(m_end);
}
ATTR_HOT inline entry_t &peek()
{
return item(m_end-1);
}
ATTR_COLD void clear()
{
m_end = m_start = (1 << _Size) >> 1;
}
private:
ATTR_HOT inline entry_t &item(UINT32 x) { return m_list[x & SIZE]; }
ATTR_HOT inline void set_item(UINT32 x, const entry_t &aitem) { m_list[x & SIZE] = aitem; }
ATTR_HOT inline entry_t &item(const UINT32 x) { return m_list[x & SIZE]; }
ATTR_HOT inline void set_item(const UINT32 x, const entry_t &aitem) { m_list[x & SIZE] = aitem; }
UINT32 m_start;
UINT32 m_end;
@ -336,14 +343,16 @@ private:
};
template <class _QC, int _Size>
ATTR_HOT ATTR_ALIGN void netlist_timed_queue<_QC, _Size>::push(const entry_t &e)
ATTR_HOT ATTR_ALIGN inline void netlist_timed_queue<_QC, _Size>::push(const entry_t &e)
{
if (is_empty() || (e.time() <= item(m_end - 1).time()))
const netlist_time &t = e.time();
if (is_empty() || (t <= item(m_end - 1).time()))
{
set_item(m_end, e);
m_end++;
}
else if (e.time() >= item(m_start).time())
else if (t >= item(m_start).time())
{
m_start--;
set_item(m_start, e);
@ -351,13 +360,11 @@ ATTR_HOT ATTR_ALIGN void netlist_timed_queue<_QC, _Size>::push(const entry_t &e)
else
{
register UINT32 i = m_end;
register UINT32 j = i - 1;
m_end++;
while ((e.time() > item(j).time()))
while ((t > item(i-1).time()))
{
set_item(i, item(j));
i = j;
j--;
set_item(i, item(i-1));
i--;
}
set_item(i, e);
}
@ -373,7 +380,7 @@ class netlist_setup_t;
class netlist_base_t;
// ----------------------------------------------------------------------------------------
// net_input_t
// net_object_t
// ----------------------------------------------------------------------------------------
class net_object_t
@ -401,6 +408,11 @@ private:
};
// ----------------------------------------------------------------------------------------
// net_input_t
// ----------------------------------------------------------------------------------------
class net_input_t : public net_object_t
{
public:
@ -515,6 +527,7 @@ public:
ATTR_COLD void register_con(net_input_t &inp);
ATTR_HOT void update_dev(const net_input_t &inp, const UINT32 mask);
ATTR_HOT void update_devs();
ATTR_COLD void update_devs_force();
@ -523,6 +536,8 @@ public:
ATTR_HOT inline void inc_active();
ATTR_HOT inline void dec_active() { m_active--; }
ATTR_HOT inline int active_count() { return m_active; }
ATTR_HOT inline netlist_time time() { return m_time; }
ATTR_HOT inline void set_time(netlist_time ntime) { m_time = ntime; }
ATTR_COLD void set_netdev(const net_core_device_t *dev);
@ -533,38 +548,39 @@ protected:
*/
ATTR_HOT inline const net_sig_t Q() const { return m_Q; }
ATTR_HOT inline void register_in_listPS(const netlist_time &delay_ps);
ATTR_HOT inline void push_to_queue(const netlist_time &delay);
ATTR_HOT inline void set_Q_PS(const net_sig_t newQ, const netlist_time &delay_ps)
ATTR_HOT inline void set_Q(const net_sig_t newQ, const netlist_time &delay)
{
if (newQ != m_new_Q)
{
m_new_Q = newQ;
register_in_listPS(delay_ps);
push_to_queue(delay);
}
}
ATTR_HOT inline void set_Q_NoCheckPS(const net_sig_t val, const netlist_time &delay_ps)
ATTR_HOT inline void set_Q_NoCheck(const net_sig_t val, const netlist_time &delay)
{
m_new_Q = val;
register_in_listPS(delay_ps);
push_to_queue(delay);
}
ATTR_HOT inline void set_Q_PS_Analog(const double newQ, const netlist_time &delay_ps)
ATTR_HOT inline void set_Q_Analog(const double newQ, const netlist_time &delay)
{
if (newQ != m_new_Q_analog)
{
m_new_Q_analog = newQ;
register_in_listPS(delay_ps);
push_to_queue(delay);
}
}
ATTR_HOT inline void set_Q_NoCheckPS_Analog(const double val, const netlist_time &delay_ps)
ATTR_HOT inline void set_Q_NoCheck_Analog(const double val, const netlist_time &delay)
{
m_new_Q_analog = val;
register_in_listPS(delay_ps);
push_to_queue(delay);
}
netlist_time m_time;
int m_in_queue;
UINT8 m_in_queue;
UINT8 m_active;
net_sig_t m_Q;
net_sig_t m_new_Q;
@ -574,7 +590,6 @@ protected:
netlist_base_t *m_netlist;
int m_active;
int m_num_cons;
net_input_t *m_cons[48];
@ -592,15 +607,15 @@ public:
: net_output_t(OUTPUT | SIGNAL_DIGITAL)
{
// Default to TTL
m_low_V = 0.3;
m_high_V = 3.4;
m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications.
m_high_V = 4.8;
}
ATTR_COLD void initial(const net_sig_t val) { m_Q = val; m_new_Q = val; m_last_Q = !val; }
ATTR_HOT inline void clear() { set_Q_PS(0, netlist_time::zero); }
ATTR_HOT inline void set() { set_Q_PS(1, netlist_time::zero); }
ATTR_HOT inline void setToPS(const UINT8 val, const netlist_time &delay_ps) { set_Q_PS(val, delay_ps); }
ATTR_HOT inline void setToNoCheckPS(const UINT8 val, const netlist_time &delay_ps) { set_Q_NoCheckPS(val, delay_ps); }
ATTR_HOT inline void clear() { set_Q(0, netlist_time::zero); }
ATTR_HOT inline void set() { set_Q(1, netlist_time::zero); }
ATTR_HOT inline void setTo(const UINT8 val, const netlist_time &delay) { set_Q(val, delay); }
ATTR_HOT inline void setToNoCheck(const UINT8 val, const netlist_time &delay) { set_Q_NoCheck(val, delay); }
ATTR_COLD inline void set_levels(const double low, const double high)
{
m_low_V = low;
@ -626,8 +641,8 @@ public:
: net_output_t(OUTPUT | SIGNAL_ANALOG) { }
ATTR_COLD void initial(double val) { m_Q_analog = val; m_new_Q_analog = val; }
ATTR_HOT inline void setToPS(const double val, const netlist_time &delay_ps) { set_Q_PS_Analog(val,delay_ps); }
ATTR_HOT inline void setToNoCheckPS(const double val, const netlist_time &delay_ps) { set_Q_NoCheckPS_Analog(val,delay_ps); }
ATTR_HOT inline void setToPS(const double val, const netlist_time &delay) { set_Q_Analog(val,delay); }
ATTR_HOT inline void setToNoCheckPS(const double val, const netlist_time &delay) { set_Q_NoCheck_Analog(val,delay); }
};
// ----------------------------------------------------------------------------------------
@ -638,10 +653,6 @@ class net_core_device_t : public net_object_t
{
public:
#if USE_DELEGATES
friend class net_input_t; // for access to update
#endif
net_core_device_t();
virtual ~net_core_device_t();
@ -650,17 +661,12 @@ public:
ATTR_COLD const char *name() const { return m_name; }
ATTR_HOT inline void update_device()
{
#if USE_DELEGATES_A
h();
#else
update();
#endif
}
ATTR_HOT inline void update_device() { update(); }
ATTR_HOT virtual void update_param() {}
ATTR_HOT virtual void update() { }
ATTR_HOT inline net_sig_t INPVAL_PASSIVE(logic_input_t &inp)
{
net_sig_t ret;
@ -692,15 +698,15 @@ public:
protected:
ATTR_HOT virtual void update() { }
ATTR_COLD void register_subdevice(net_core_device_t &subdev);
netlist_base_t *m_netlist;
private:
#if USE_DELEGATES
net_update_delegate h;
#endif
const char *m_name;
};
@ -796,14 +802,14 @@ public:
m_i[i].activate();
if (INPVAL(m_i[i]) == _check)
{
m_Q.setToPS(!_check, times[_check]);// ? 15000 : 22000);
m_Q.setTo(!_check, times[_check]);// ? 15000 : 22000);
for (int j = i + 1; j < _numdev; j++)
m_i[j].inactivate();
return;
}
m_i[i].inactivate();
}
m_Q.setToPS(_check, times[1-_check]);// ? 22000 : 15000);
m_Q.setTo(_check, times[1-_check]);// ? 22000 : 15000);
for (int i = 0; i < _numdev; i++)
m_i[i].activate();
}
@ -872,6 +878,8 @@ private:
const char *resolve_alias(const char *name) const;
};
class netdev_mainclock;
// ----------------------------------------------------------------------------------------
// netlist_base_t
// ----------------------------------------------------------------------------------------
@ -880,14 +888,6 @@ class netlist_base_t
{
public:
struct entry_t
{
public:
entry_t() {}
entry_t(netlist_time atime, net_output_t *aout) : time(atime), out(aout) {}
netlist_time time;
net_output_t *out;
};
typedef netlist_timed_queue<net_output_t *, 9> queue_t;
netlist_base_t();
@ -895,7 +895,7 @@ public:
void set_clock_freq(UINT64 clockfreq);
ATTR_HOT inline void register_in_listPS1(net_output_t *out, const netlist_time &attime)
ATTR_HOT inline void push_to_queue(net_output_t *out, const netlist_time &attime)
{
m_queue.push(queue_t::entry_t(attime, out));
}
@ -904,6 +904,8 @@ public:
ATTR_HOT inline netlist_time &time() { return m_time_ps; }
netdev_mainclock *m_mainclock;
protected:
netlist_time m_time_ps;
UINT32 m_rem;
@ -915,13 +917,43 @@ protected:
int m_perf_out_processed;
int m_perf_inp_processed;
int m_perf_inp_active;
UINT64 m_perf_list_len;
private:
};
// ----------------------------------------------------------------------------------------
// netdev_mainclock
// ----------------------------------------------------------------------------------------
NETLIB_DEVICE_WITH_PARAMS(netdev_mainclock,
ttl_output_t m_Q;
net_param_t m_freq;
netlist_time m_inc;
);
inline NETLIB_START(netdev_mainclock)
{
register_output("Q", m_Q);
//register_input("FB", m_feedback);
register_param("FREQ", m_freq, 7159000.0 * 5);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
inline NETLIB_UPDATE_PARAM(netdev_mainclock)
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
inline NETLIB_UPDATE(netdev_mainclock)
{
*m_Q.new_Q_ptr() = !m_Q.new_Q();
m_Q.set_time(m_netlist->time() + m_inc);
//m_Q.setToNoCheckPS(!m_Q.new_Q(), m_inc );
}
// ----------------------------------------------------------------------------------------
// netdev_callback
@ -1006,14 +1038,14 @@ ATTR_HOT inline void net_input_t::activate_lh()
}
ATTR_HOT inline void net_output_t::register_in_listPS(const netlist_time &delay_ps)
ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay)
{
m_time = m_netlist->time() + delay_ps;
m_time = m_netlist->time() + delay;
m_in_queue = 0; /* not queued */
if (m_active > 0)
{
m_in_queue = 1; /* pending */
m_netlist->register_in_listPS1(this, m_time);
m_netlist->push_to_queue(this, m_time);
}
}
@ -1025,7 +1057,7 @@ ATTR_HOT inline void net_output_t::inc_active()
if (m_time >= m_netlist->time())
{
m_in_queue = 1; /* pending */
m_netlist->register_in_listPS1(this, m_time);
m_netlist->push_to_queue(this, m_time);
}
else
{
@ -1050,10 +1082,10 @@ class net_device_t_base_factory
{
public:
virtual ~net_device_t_base_factory() {}
virtual net_device_t *Create(netlist_setup_t *setup, const char *name) = 0;
virtual net_device_t *Create(netlist_setup_t *setup, const char *name) const = 0;
const char *name() { return m_name; }
const char *classname() { return m_classname; }
const char *name() const { return m_name; }
const char *classname() const { return m_classname; }
protected:
const char *m_name; /* device name */
const char *m_classname; /* device class name */
@ -1064,7 +1096,7 @@ class net_device_t_factory : public net_device_t_base_factory
{
public:
net_device_t_factory(const char *name, const char *classname) { m_name = name; m_classname = classname; }
net_device_t *Create(netlist_setup_t *setup, const char *name)
net_device_t *Create(netlist_setup_t *setup, const char *name) const
{
net_device_t *r = global_alloc_clear(C());
r->init(setup, name);
@ -1144,7 +1176,6 @@ protected:
private:
void step_one_clock();
void save_state();
void (*m_setup_func)(netlist_setup_t &);
@ -1199,6 +1230,8 @@ class netlist_mame_device::optional_output : public netlist_mame_device::output_
public:
optional_output(device_t &base, const char *tag, const char *output) : output_finder<false, net_output_t>(base, tag, output) { }
virtual ~optional_output() {};
virtual bool OnDeviceStart()
{
this->m_target = &m_netlist->setup().find_output(m_output);
@ -1214,6 +1247,8 @@ class netlist_mame_device::required_output : public netlist_mame_device::output_
public:
required_output(device_t &base, const char *tag, const char *output) : output_finder<true, C>(base, tag, output) { }
virtual ~required_output() {};
virtual bool OnDeviceStart()
{
this->m_target = (C *) &(this->m_netlist->setup().find_output(this->m_output));

View File

@ -55,7 +55,7 @@ TODO:
#define VBSTART (V_TOTAL)
#define VBEND (16)
#define HRES_MULT (1)
#define HRES_MULT (2)
enum input_changed_enum
{
@ -70,7 +70,7 @@ enum input_changed_enum
static NETLIST_START(pong_schematics)
NETDEV_TTL_CONST(high, 1)
NETDEV_TTL_CONST(low, 0)
NETDEV_CLOCK(clk)
NETDEV_MAINCLOCK(clk)
NETDEV_PARAM(clk.FREQ, 7159000.0)
NETDEV_LOGIC_INPUT(SRST)
NETDEV_ANALOG_INPUT(P1)
@ -287,7 +287,7 @@ static NETLIST_START(pong_schematics)
NE555N_MSTABLE(ic_b9, 256VQ, P1)
NETDEV_PARAM(ic_b9.R, RES_K(90))
NETDEV_PARAM(ic_b9.C, CAP_U(.1))
NETDEV_PARAM(ic_b9.VL, 0.7)
NETDEV_PARAM(ic_b9.VL, 0.5) // 1N914
TTL_7404_INVERT(ic_c9b, ic_b9.Q)
TTL_7400_NAND(ic_b7b, ic_a7b.Q, hsyncQ)
TTL_7493(ic_b8, ic_b7b.Q, ic_b8.QA, ic_b9.Q, ic_b9.Q)
@ -304,7 +304,7 @@ static NETLIST_START(pong_schematics)
NE555N_MSTABLE(ic_a9, 256VQ, P2)
NETDEV_PARAM(ic_a9.R, RES_K(90))
NETDEV_PARAM(ic_a9.C, CAP_U(.1))
NETDEV_PARAM(ic_a9.VL, 0.7)
NETDEV_PARAM(ic_a9.VL, 0.5) // 1N914
TTL_7404_INVERT(ic_c9a, ic_a9.Q)
TTL_7400_NAND(ic_b7c, ic_a7a.Q, hsyncQ)
TTL_7493(ic_a8, ic_b7c.Q, ic_a8.QA, ic_a9.Q, ic_a9.Q)
@ -558,6 +558,7 @@ private:
}
else if (time >= hsync_min_time)
{
//printf("%d\n", m_last_x);
m_last_x = 0; // hsync
m_last_y++;
m_line_clock = clocks;
@ -608,6 +609,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
{
static const double NE555_R = RES_K(5);
static const double PRE_R = RES_R(470);
static const double POT_R = RES_K(1);
double pad;
int numpad = (FPTR) (param);
@ -620,8 +622,9 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
// http://ion.chem.usu.edu/~sbialkow/Classes/564/Thevenin/Thevenin.html
double fac = (double) newval / (double) 256;
double R1 = fac * RES_K(10);
double R3 = (1.0 - fac) * RES_K(10);
fac = (exp(fac) - 1.0) / (exp(1.0) -1.0) ;
double R1 = fac * POT_R;
double R3 = (1.0 - fac) * POT_R;
double vA = 5.0 * R3 / (R3 + R1);
double vB = 5.0 * 2 * NE555_R / (2 * NE555_R + NE555_R);
double Req = RES_2_PARALLEL(R1, R3) + RES_2_PARALLEL(NE555_R, 2.0 * NE555_R);
@ -631,6 +634,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
case IC_PADDLE1: m_p_V0->setToPS(pad, NLTIME_FROM_NS(0)); break;
case IC_PADDLE2: m_p_V1->setToPS(pad, NLTIME_FROM_NS(0)); break;
}
printf("%d %f\n", newval, (float) pad);
break;
}
case IC_SWITCH:
@ -638,7 +642,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
m_sw1b->setTo(newval ? 1 : 0);
break;
case IC_COIN:
m_srst->setToPS(newval & 1, NLTIME_FROM_US(500));
m_srst->setTo(newval & 1, NLTIME_FROM_US(500));
break;
case IC_VR1:
case IC_VR2: