- code cleanup
- logs on demand ... NL_LOGS=EBUF.OP:4V ./mame64 -np 4 pongf 
  No recompile or dealing with roms
This commit is contained in:
Couriersud 2013-12-12 20:19:29 +00:00
parent 0a61ffafc2
commit 2fa537b49f
24 changed files with 1416 additions and 1078 deletions

9
.gitattributes vendored
View File

@ -2139,15 +2139,23 @@ src/emu/netlist/devices/nld_7427.h svneol=native#text/plain
src/emu/netlist/devices/nld_7430.h svneol=native#text/plain
src/emu/netlist/devices/nld_7474.c svneol=native#text/plain
src/emu/netlist/devices/nld_7474.h svneol=native#text/plain
src/emu/netlist/devices/nld_7483.c svneol=native#text/plain
src/emu/netlist/devices/nld_7483.h svneol=native#text/plain
src/emu/netlist/devices/nld_7486.c svneol=native#text/plain
src/emu/netlist/devices/nld_7486.h svneol=native#text/plain
src/emu/netlist/devices/nld_7490.c svneol=native#text/plain
src/emu/netlist/devices/nld_7490.h svneol=native#text/plain
src/emu/netlist/devices/nld_7493.c svneol=native#text/plain
src/emu/netlist/devices/nld_7493.h svneol=native#text/plain
src/emu/netlist/devices/nld_9316.c svneol=native#text/plain
src/emu/netlist/devices/nld_9316.h svneol=native#text/plain
src/emu/netlist/devices/nld_NE555.c svneol=native#text/plain
src/emu/netlist/devices/nld_NE555.h svneol=native#text/plain
src/emu/netlist/devices/nld_log.c svneol=native#text/plain
src/emu/netlist/devices/nld_log.h svneol=native#text/plain
src/emu/netlist/devices/nld_signal.h svneol=native#text/plain
src/emu/netlist/devices/nld_solver.c svneol=native#text/plain
src/emu/netlist/devices/nld_solver.h svneol=native#text/plain
src/emu/netlist/devices/nld_system.c svneol=native#text/plain
src/emu/netlist/devices/nld_system.h svneol=native#text/plain
src/emu/netlist/devices/nld_twoterm.c svneol=native#text/plain
@ -2162,6 +2170,7 @@ src/emu/netlist/nl_parser.h svneol=native#text/plain
src/emu/netlist/nl_setup.c svneol=native#text/plain
src/emu/netlist/nl_setup.h svneol=native#text/plain
src/emu/netlist/nl_time.h svneol=native#text/plain
src/emu/netlist/nl_util.h svneol=native#text/plain
src/emu/netlist/pstring.c svneol=native#text/plain
src/emu/netlist/pstring.h svneol=native#text/plain
src/emu/network.c svneol=native#text/plain

View File

@ -50,159 +50,141 @@
#include "net_lib.h"
#include "nld_system.h"
NETLIB_START(logic_input)
{
register_output("Q", m_Q);
}
NETLIB_UPDATE(logic_input)
{
}
NETLIB_START(analog_input)
{
register_output("Q", m_Q);
}
NETLIB_UPDATE(analog_input)
{
}
NETLIB_START(nicMultiSwitch)
{
static const char *sIN[8] = { "i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8" };
int i;
static const char *sIN[8] = { "i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8" };
int i;
m_position = 0;
m_low.initial(0);
m_position = 0;
m_low.initial(0);
for (i=0; i<8; i++)
{
register_input(sIN[i], m_I[i]);
m_low.net().register_con(m_I[i]);
//m_I[i].set_net(m_low.m_net);
}
register_param("POS", m_POS, 0);
register_output("Q", m_Q);
for (i=0; i<8; i++)
{
register_input(sIN[i], m_I[i]);
m_low.net().register_con(m_I[i]);
//m_I[i].set_net(m_low.m_net);
}
register_param("POS", m_POS, 0);
register_output("Q", m_Q);
m_variable_input_count = true;
m_variable_input_count = true;
}
NETLIB_UPDATE(nicMultiSwitch)
{
assert(m_position<8);
OUTANALOG(m_Q, INPANALOG(m_I[m_position]), NLTIME_FROM_NS(1));
assert(m_position<8);
OUTANALOG(m_Q, INPANALOG(m_I[m_position]), NLTIME_FROM_NS(1));
}
NETLIB_UPDATE_PARAM(nicMultiSwitch)
{
m_position = m_POS.Value();
//update();
m_position = m_POS.Value();
//update();
}
NETLIB_START(nicMixer8)
{
static const char *sI[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
static const char *sR[8] = { "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8" };
int i;
static const char *sI[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
static const char *sR[8] = { "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8" };
int i;
m_low.initial(0);
m_low.initial(0);
for (i=0; i<8; i++)
{
register_input(sI[i], m_I[i]);
m_low.net().register_con(m_I[i]);
//m_I[i].set_output(m_low);
register_param(sR[i], m_R[i], 1e12);
}
register_output("Q", m_Q);
for (i=0; i<8; i++)
{
register_input(sI[i], m_I[i]);
m_low.net().register_con(m_I[i]);
//m_I[i].set_output(m_low);
register_param(sR[i], m_R[i], 1e12);
}
register_output("Q", m_Q);
m_variable_input_count = true;
m_variable_input_count = true;
}
NETLIB_UPDATE(nicMixer8)
{
int i;
double r = 0;
int i;
double r = 0;
for (i=0; i<8; i++)
{
r += m_w[i] * INPANALOG(m_I[i]);
}
OUTANALOG(m_Q, r, NLTIME_IMMEDIATE);
for (i=0; i<8; i++)
{
r += m_w[i] * INPANALOG(m_I[i]);
}
OUTANALOG(m_Q, r, NLTIME_IMMEDIATE);
}
NETLIB_UPDATE_PARAM(nicMixer8)
{
double t = 0;
int i;
double t = 0;
int i;
for (i=0; i<8; i++)
t += 1.0 / m_R[i].Value();
t = 1.0 / t;
for (i=0; i<8; i++)
t += 1.0 / m_R[i].Value();
t = 1.0 / t;
for (i=0; i<8; i++)
m_w[i] = t / m_R[i].Value();
for (i=0; i<8; i++)
m_w[i] = t / m_R[i].Value();
}
NETLIB_START(nicRSFF)
{
register_input("S", m_S);
register_input("R", m_R);
register_output("Q", m_Q);
register_output("QQ", m_QQ);
m_Q.initial(0);
m_QQ.initial(1);
register_input("S", m_S);
register_input("R", m_R);
register_output("Q", m_Q);
register_output("QQ", m_QQ);
m_Q.initial(0);
m_QQ.initial(1);
}
NETLIB_UPDATE(nicRSFF)
{
if (INPLOGIC(m_S))
{
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 0, NLTIME_FROM_NS(10));
}
else if (INPLOGIC(m_R))
{
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10));
}
if (INPLOGIC(m_S))
{
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 0, NLTIME_FROM_NS(10));
}
else if (INPLOGIC(m_R))
{
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10));
OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10));
}
}
NETLIB_START(nicNE555N_MSTABLE)
{
register_input("TRIG", m_trigger);
register_input("CV", m_CV);
register_input("TRIG", m_trigger);
register_input("CV", m_CV);
register_output("Q", m_Q);
register_param("R", m_R, 0.0);
register_param("C", m_C, 0.0);
register_param("VS", m_VS, 5.0);
register_param("VL", m_VL, 0.0 *5.0);
register_output("Q", m_Q);
register_param("R", m_R, 0.0);
register_param("C", m_C, 0.0);
register_param("VS", m_VS, 5.0);
register_param("VL", m_VL, 0.0 *5.0);
m_THRESHOLD_OUT.init_object(*this, "THRESHOLD");
register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT, netlist_input_t::STATE_INP_ACTIVE);
m_THRESHOLD_OUT.init_object(*this, "THRESHOLD");
register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT, netlist_input_t::STATE_INP_ACTIVE);
m_Q.initial(5.0 * 0.4);
m_last = false;
m_Q.initial(5.0 * 0.4);
m_last = false;
}
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_cv()
{
return (m_CV.is_highz() ? 0.67 * m_VS.Value() : INPANALOG(m_CV));
return (m_CV.is_highz() ? 0.67 * m_VS.Value() : INPANALOG(m_CV));
}
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_clamp(const double v, const double a, const double b)
{
double ret = v;
if (ret > m_VS.Value() - a)
ret = m_VS.Value() - a;
if (ret < b)
ret = b;
return ret;
double ret = v;
if (ret > m_VS.Value() - a)
ret = m_VS.Value() - a;
if (ret < b)
ret = b;
return ret;
}
NETLIB_UPDATE_PARAM(nicNE555N_MSTABLE)
@ -211,97 +193,97 @@ NETLIB_UPDATE_PARAM(nicNE555N_MSTABLE)
NETLIB_UPDATE(nicNE555N_MSTABLE)
{
update_param(); // FIXME : m_CV should be on a sub device ...
update_param(); // FIXME : m_CV should be on a sub device ...
double vt = nicNE555N_clamp(nicNE555N_cv(), 0.7, 1.4);
bool bthresh = (INPANALOG(m_THRESHOLD) > vt);
bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(nicNE555N_cv() * 0.5, 0.7, 1.4));
bool out = m_last;
double vt = nicNE555N_clamp(nicNE555N_cv(), 0.7, 1.4);
bool bthresh = (INPANALOG(m_THRESHOLD) > vt);
bool btrig = (INPANALOG(m_trigger) > nicNE555N_clamp(nicNE555N_cv() * 0.5, 0.7, 1.4));
bool out = m_last;
if (!btrig)
{
out = true;
}
else if (bthresh)
{
out = false;
}
if (!btrig)
{
out = true;
}
else if (bthresh)
{
out = false;
}
if (!m_last && out)
{
double vl = m_VL.Value();
double time;
if (!m_last && out)
{
double vl = m_VL.Value();
double time;
// FIXME : m_CV should be on a sub device ...
// FIXME : m_CV should be on a sub device ...
// TI datasheet states minimum pulse of 10 us
if (vt<vl)
time = 10;
else
{
time = - log((m_VS.Value()-vt)/(m_VS.Value()-vl)) * m_R.Value() * m_C.Value() * 1.0e6; // in us
if (time < 10.0)
time = 10.0;
}
// TI datasheet states minimum pulse of 10 us
if (vt<vl)
time = 10;
else
{
time = - log((m_VS.Value()-vt)/(m_VS.Value()-vl)) * m_R.Value() * m_C.Value() * 1.0e6; // in us
if (time < 10.0)
time = 10.0;
}
OUTANALOG(m_Q, m_VS.Value() * 0.7, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, m_VS.Value(), NLTIME_FROM_US(time ));
}
else if (m_last && !out)
{
OUTANALOG(m_Q, 0.25, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, 0.0, NLTIME_FROM_NS(1));
}
m_last = out;
OUTANALOG(m_Q, m_VS.Value() * 0.7, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, m_VS.Value(), NLTIME_FROM_US(time ));
}
else if (m_last && !out)
{
OUTANALOG(m_Q, 0.25, NLTIME_FROM_NS(100));
OUTANALOG(m_THRESHOLD_OUT, 0.0, NLTIME_FROM_NS(1));
}
m_last = out;
}
NETLIB_START(nic7448)
{
register_sub(sub, "sub");
register_sub(sub, "sub");
register_subalias("A0", sub.m_A0);
register_subalias("A1", sub.m_A1);
register_subalias("A2", sub.m_A2);
register_subalias("A3", sub.m_A3);
register_input("LTQ", m_LTQ);
register_input("BIQ", m_BIQ);
register_subalias("RBIQ",sub.m_RBIQ);
register_subalias("A0", sub.m_A0);
register_subalias("A1", sub.m_A1);
register_subalias("A2", sub.m_A2);
register_subalias("A3", sub.m_A3);
register_input("LTQ", m_LTQ);
register_input("BIQ", m_BIQ);
register_subalias("RBIQ",sub.m_RBIQ);
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("e", sub.m_e);
register_subalias("f", sub.m_f);
register_subalias("g", sub.m_g);
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("e", sub.m_e);
register_subalias("f", sub.m_f);
register_subalias("g", sub.m_g);
}
NETLIB_UPDATE(nic7448)
{
if (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ))
{
sub.update_outputs(8);
}
else if (!INPLOGIC(m_BIQ))
{
sub.update_outputs(15);
}
if (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ))
{
sub.update_outputs(8);
}
else if (!INPLOGIC(m_BIQ))
{
sub.update_outputs(15);
}
if (!INPLOGIC(m_BIQ) || (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ)))
{
sub.m_A0.inactivate();
sub.m_A1.inactivate();
sub.m_A2.inactivate();
sub.m_A3.inactivate();
sub.m_RBIQ.inactivate();
} else {
sub.m_RBIQ.activate();
sub.m_A3.activate();
sub.m_A2.activate();
sub.m_A1.activate();
sub.m_A0.activate();
sub.update();
}
if (!INPLOGIC(m_BIQ) || (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ)))
{
sub.m_A0.inactivate();
sub.m_A1.inactivate();
sub.m_A2.inactivate();
sub.m_A3.inactivate();
sub.m_RBIQ.inactivate();
} else {
sub.m_RBIQ.activate();
sub.m_A3.activate();
sub.m_A2.activate();
sub.m_A1.activate();
sub.m_A0.activate();
sub.update();
}
}
@ -326,189 +308,100 @@ NETLIB_START(nic7448_sub)
NETLIB_UPDATE(nic7448_sub)
{
UINT8 v;
UINT8 v;
v = (INPLOGIC(m_A0) << 0) | (INPLOGIC(m_A1) << 1) | (INPLOGIC(m_A2) << 2) | (INPLOGIC(m_A3) << 3);
if ((!INPLOGIC(m_RBIQ) && (v==0)))
v = 15;
update_outputs(v);
v = (INPLOGIC(m_A0) << 0) | (INPLOGIC(m_A1) << 1) | (INPLOGIC(m_A2) << 2) | (INPLOGIC(m_A3) << 3);
if ((!INPLOGIC(m_RBIQ) && (v==0)))
v = 15;
update_outputs(v);
}
NETLIB_FUNC_VOID(nic7448_sub, update_outputs, (UINT8 v))
{
assert(v<16);
if (v != m_state)
{
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));
OUTLOGIC(m_d, tab7448[v][3], NLTIME_FROM_NS(100));
OUTLOGIC(m_e, tab7448[v][4], NLTIME_FROM_NS(100));
OUTLOGIC(m_f, tab7448[v][5], NLTIME_FROM_NS(100));
OUTLOGIC(m_g, tab7448[v][6], NLTIME_FROM_NS(100));
m_state = v;
}
assert(v<16);
if (v != m_state)
{
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));
OUTLOGIC(m_d, tab7448[v][3], NLTIME_FROM_NS(100));
OUTLOGIC(m_e, tab7448[v][4], NLTIME_FROM_NS(100));
OUTLOGIC(m_f, tab7448[v][5], NLTIME_FROM_NS(100));
OUTLOGIC(m_g, tab7448[v][6], NLTIME_FROM_NS(100));
m_state = v;
}
}
const UINT8 NETLIB_NAME(nic7448_sub)::tab7448[16][7] =
{
{ 1, 1, 1, 1, 1, 1, 0 }, /* 00 - not blanked ! */
{ 0, 1, 1, 0, 0, 0, 0 }, /* 01 */
{ 1, 1, 0, 1, 1, 0, 1 }, /* 02 */
{ 1, 1, 1, 1, 0, 0, 1 }, /* 03 */
{ 0, 1, 1, 0, 0, 1, 1 }, /* 04 */
{ 1, 0, 1, 1, 0, 1, 1 }, /* 05 */
{ 0, 0, 1, 1, 1, 1, 1 }, /* 06 */
{ 1, 1, 1, 0, 0, 0, 0 }, /* 07 */
{ 1, 1, 1, 1, 1, 1, 1 }, /* 08 */
{ 1, 1, 1, 0, 0, 1, 1 }, /* 09 */
{ 0, 0, 0, 1, 1, 0, 1 }, /* 10 */
{ 0, 0, 1, 1, 0, 0, 1 }, /* 11 */
{ 0, 1, 0, 0, 0, 1, 1 }, /* 12 */
{ 1, 0, 0, 1, 0, 1, 1 }, /* 13 */
{ 0, 0, 0, 1, 1, 1, 1 }, /* 14 */
{ 0, 0, 0, 0, 0, 0, 0 }, /* 15 */
{ 1, 1, 1, 1, 1, 1, 0 }, /* 00 - not blanked ! */
{ 0, 1, 1, 0, 0, 0, 0 }, /* 01 */
{ 1, 1, 0, 1, 1, 0, 1 }, /* 02 */
{ 1, 1, 1, 1, 0, 0, 1 }, /* 03 */
{ 0, 1, 1, 0, 0, 1, 1 }, /* 04 */
{ 1, 0, 1, 1, 0, 1, 1 }, /* 05 */
{ 0, 0, 1, 1, 1, 1, 1 }, /* 06 */
{ 1, 1, 1, 0, 0, 0, 0 }, /* 07 */
{ 1, 1, 1, 1, 1, 1, 1 }, /* 08 */
{ 1, 1, 1, 0, 0, 1, 1 }, /* 09 */
{ 0, 0, 0, 1, 1, 0, 1 }, /* 10 */
{ 0, 0, 1, 1, 0, 0, 1 }, /* 11 */
{ 0, 1, 0, 0, 0, 1, 1 }, /* 12 */
{ 1, 0, 0, 1, 0, 1, 1 }, /* 13 */
{ 0, 0, 0, 1, 1, 1, 1 }, /* 14 */
{ 0, 0, 0, 0, 0, 0, 0 }, /* 15 */
};
NETLIB_START(nic7450)
{
register_input("I1", m_I0);
register_input("I2", m_I1);
register_input("I3", m_I2);
register_input("I4", m_I3);
register_output("Q", m_Q);
register_input("I1", m_I0);
register_input("I2", m_I1);
register_input("I3", m_I2);
register_input("I4", m_I3);
register_output("Q", m_Q);
}
NETLIB_UPDATE(nic7450)
{
m_I0.activate();
m_I1.activate();
m_I2.activate();
m_I3.activate();
UINT8 t1 = INPLOGIC(m_I0) & INPLOGIC(m_I1);
UINT8 t2 = INPLOGIC(m_I2) & INPLOGIC(m_I3);
m_I0.activate();
m_I1.activate();
m_I2.activate();
m_I3.activate();
UINT8 t1 = INPLOGIC(m_I0) & INPLOGIC(m_I1);
UINT8 t2 = INPLOGIC(m_I2) & INPLOGIC(m_I3);
#if 0
UINT8 t = (t1 | t2) ^ 1;
OUTLOGIC(m_Q, t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
UINT8 t = (t1 | t2) ^ 1;
OUTLOGIC(m_Q, t, t ? NLTIME_FROM_NS(22) : NLTIME_FROM_NS(15));
#else
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
UINT8 res = 0;
if (t1 ^ 1)
{
if (t2 ^ 1)
{
res = 1;
}
else
{
m_I0.inactivate();
m_I1.inactivate();
}
} else {
if (t2 ^ 1)
{
m_I2.inactivate();
m_I3.inactivate();
}
}
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
UINT8 res = 0;
if (t1 ^ 1)
{
if (t2 ^ 1)
{
res = 1;
}
else
{
m_I0.inactivate();
m_I1.inactivate();
}
} else {
if (t2 ^ 1)
{
m_I2.inactivate();
m_I3.inactivate();
}
}
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
#endif
}
NETLIB_START(nic7483)
{
m_lastr = 0;
register_input("A1", m_A1);
register_input("A2", m_A2);
register_input("A3", m_A3);
register_input("A4", m_A4);
register_input("B1", m_B1);
register_input("B2", m_B2);
register_input("B3", m_B3);
register_input("B4", m_B4);
register_input("CI", m_CI);
register_output("SA", m_SA);
register_output("SB", m_SB);
register_output("SC", m_SC);
register_output("SD", m_SD);
register_output("CO", m_CO);
}
NETLIB_UPDATE(nic7483)
{
UINT8 a = (INPLOGIC(m_A1) << 0) | (INPLOGIC(m_A2) << 1) | (INPLOGIC(m_A3) << 2) | (INPLOGIC(m_A4) << 3);
UINT8 b = (INPLOGIC(m_B1) << 0) | (INPLOGIC(m_B2) << 1) | (INPLOGIC(m_B3) << 2) | (INPLOGIC(m_B4) << 3);
UINT8 r = a + b + INPLOGIC(m_CI);
if (r != m_lastr)
{
m_lastr = r;
OUTLOGIC(m_SA, (r >> 0) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SB, (r >> 1) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SC, (r >> 2) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SD, (r >> 3) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_CO, (r >> 4) & 1, NLTIME_FROM_NS(23));
}
}
NETLIB_START(nic7490)
{
m_cnt = 0;
register_input("CLK", m_clk);
register_input("R1", m_R1);
register_input("R2", m_R2);
register_input("R91", m_R91);
register_input("R92", m_R92);
register_output("QA", m_Q[0]);
register_output("QB", m_Q[1]);
register_output("QC", m_Q[2]);
register_output("QD", m_Q[3]);
}
NETLIB_UPDATE(nic7490)
{
if (INPLOGIC(m_R91) & INPLOGIC(m_R92))
{
m_cnt = 9;
update_outputs();
}
else if (INPLOGIC(m_R1) & INPLOGIC(m_R2))
{
m_cnt = 0;
update_outputs();
}
else if (INP_HL(m_clk))
{
m_cnt++;
if (m_cnt >= 10)
m_cnt = 0;
update_outputs();
}
}
#if 0
NETLIB_FUNC_VOID(nic7490, update_outputs)
{
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
}
#else
NETLIB_FUNC_VOID(nic7490, update_outputs, (void))
{
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++)
OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
}
#endif
NETLIB_START(nic74107Asub)
{
@ -522,245 +415,110 @@ NETLIB_START(nic74107Asub)
NETLIB_START(nic74107A)
{
register_sub(sub, "sub");
register_sub(sub, "sub");
register_subalias("CLK", sub.m_clk);
register_input("J", m_J);
register_input("K", m_K);
register_input("CLRQ", m_clrQ);
register_subalias("Q", sub.m_Q);
register_subalias("QQ", sub.m_QQ);
register_subalias("CLK", sub.m_clk);
register_input("J", m_J);
register_input("K", m_K);
register_input("CLRQ", m_clrQ);
register_subalias("Q", sub.m_Q);
register_subalias("QQ", sub.m_QQ);
sub.m_Q.initial(0);
sub.m_QQ.initial(1);
sub.m_Q.initial(0);
sub.m_QQ.initial(1);
}
ATTR_HOT inline void NETLIB_NAME(nic74107Asub)::newstate(const netlist_sig_t state)
{
const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
#if 1
OUTLOGIC(m_Q, state, delay[state ^ 1]);
OUTLOGIC(m_QQ, state ^ 1, delay[state]);
OUTLOGIC(m_Q, state, delay[state ^ 1]);
OUTLOGIC(m_QQ, state ^ 1, delay[state]);
#else
if (state != Q.new_Q())
{
Q.setToNoCheck(state, delay[1-state]);
QQ.setToNoCheck(1-state, delay[state]);
}
if (state != Q.new_Q())
{
Q.setToNoCheck(state, delay[1-state]);
QQ.setToNoCheck(1-state, delay[state]);
}
#endif
}
NETLIB_UPDATE(nic74107Asub)
{
{
const netlist_sig_t t = m_Q.net().new_Q();
newstate((!t & m_Q1) | (t & m_Q2) | m_F);
if (!m_Q1)
m_clk.inactivate();
}
{
const netlist_sig_t t = m_Q.net().new_Q();
newstate((!t & m_Q1) | (t & m_Q2) | m_F);
if (!m_Q1)
m_clk.inactivate();
}
}
NETLIB_UPDATE(nic74107A)
{
if (INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 1;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (!INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (INPLOGIC(m_J) & !INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
sub.m_F = 1;
}
else
{
sub.m_Q1 = 0;
sub.m_Q2 = 1;
sub.m_F = 0;
sub.m_clk.inactivate();
}
if (!INPLOGIC(m_clrQ))
{
sub.m_clk.inactivate();
sub.newstate(0);
}
else if (!sub.m_Q2)
sub.m_clk.activate_hl();
//if (!sub.m_Q2 & INPLOGIC(m_clrQ))
// sub.m_clk.activate_hl();
if (INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 1;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (!INPLOGIC(m_J) & INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
sub.m_F = 0;
}
else if (INPLOGIC(m_J) & !INPLOGIC(m_K))
{
sub.m_Q1 = 0;
sub.m_Q2 = 0;
sub.m_F = 1;
}
else
{
sub.m_Q1 = 0;
sub.m_Q2 = 1;
sub.m_F = 0;
sub.m_clk.inactivate();
}
if (!INPLOGIC(m_clrQ))
{
sub.m_clk.inactivate();
sub.newstate(0);
}
else if (!sub.m_Q2)
sub.m_clk.activate_hl();
//if (!sub.m_Q2 & INPLOGIC(m_clrQ))
// sub.m_clk.activate_hl();
}
NETLIB_START(nic74153)
{
register_input("A1", m_I[0]);
register_input("A2", m_I[1]);
register_input("A3", m_I[2]);
register_input("A4", m_I[3]);
register_input("A", m_A);
register_input("B", m_B);
register_input("GA", m_GA);
register_input("A1", m_I[0]);
register_input("A2", m_I[1]);
register_input("A3", m_I[2]);
register_input("A4", m_I[3]);
register_input("A", m_A);
register_input("B", m_B);
register_input("GA", m_GA);
register_output("AY", m_AY);
register_output("AY", m_AY);
}
NETLIB_UPDATE(nic74153)
{
const netlist_time delay[2] = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) };
if (!INPLOGIC(m_GA))
{
UINT8 chan = (INPLOGIC(m_A) | (INPLOGIC(m_B)<<1));
UINT8 t = INPLOGIC(m_I[chan]);
OUTLOGIC(m_AY, t, delay[t] ); /* data to y only, FIXME */
}
else
{
OUTLOGIC(m_AY, 0, delay[0]);
}
const netlist_time delay[2] = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) };
if (!INPLOGIC(m_GA))
{
UINT8 chan = (INPLOGIC(m_A) | (INPLOGIC(m_B)<<1));
UINT8 t = INPLOGIC(m_I[chan]);
OUTLOGIC(m_AY, t, delay[t] ); /* data to y only, FIXME */
}
else
{
OUTLOGIC(m_AY, 0, delay[0]);
}
}
NETLIB_START(nic9316)
{
register_sub(sub, "sub");
register_subalias("CLK", sub.m_clk);
register_input("ENP", m_ENP);
register_input("ENT", m_ENT);
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("QA", sub.m_QA);
register_subalias("QB", sub.m_QB);
register_subalias("QC", sub.m_QC);
register_subalias("QD", sub.m_QD);
register_subalias("RC", sub.m_RC);
}
NETLIB_START(nic9316_sub)
{
m_cnt = 0;
m_loadq = 1;
m_ent = 1;
register_input("CLK", m_clk, netlist_input_t::STATE_INP_LH);
register_input("A", m_A, netlist_input_t::STATE_INP_PASSIVE);
register_input("B", m_B, netlist_input_t::STATE_INP_PASSIVE);
register_input("C", m_C, netlist_input_t::STATE_INP_PASSIVE);
register_input("D", m_D, netlist_input_t::STATE_INP_PASSIVE);
register_output("QA", m_QA);
register_output("QB", m_QB);
register_output("QC", m_QC);
register_output("QD", m_QD);
register_output("RC", m_RC);
}
NETLIB_UPDATE(nic9316_sub)
{
if (m_loadq)
{
m_cnt = ( m_cnt + 1) & 0x0f;
update_outputs();
}
else
{
m_cnt = (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
update_outputs_all();
}
OUTLOGIC(m_RC, m_ent & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_UPDATE(nic9316)
{
sub.m_loadq = INPLOGIC(m_LOADQ);
sub.m_ent = INPLOGIC(m_ENT);
const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
{
sub.m_clk.activate_lh();
}
else
{
sub.m_clk.inactivate();
if (!clrq & (sub.m_cnt>0))
{
sub.m_cnt = 0;
sub.update_outputs();
OUTLOGIC(sub.m_RC, 0, NLTIME_FROM_NS(20));
return;
}
}
OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs_all, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
#if 0
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
#else
if ((m_cnt & 1) == 1)
OUTLOGIC(m_QA, 1, out_delay);
else
{
OUTLOGIC(m_QA, 0, out_delay);
switch (m_cnt)
{
case 0x00:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 0, out_delay);
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
OUTLOGIC(m_QB, 1, out_delay);
break;
case 0x04:
case 0x0C:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 1, out_delay);
break;
case 0x08:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 1, out_delay);
break;
}
}
#endif
}
#define xstr(s) # s
#define ENTRY1(_nic, _name) m_list.add(new net_device_t_factory< _nic >( # _name, xstr(_nic) ));
@ -795,6 +553,7 @@ void netlist_factory::initialize()
ENTRY(logic_input, NETDEV_LOGIC_INPUT)
ENTRY(analog_input, NETDEV_ANALOG_INPUT)
ENTRY(log, NETDEV_LOG)
ENTRY(logD, NETDEV_LOGD)
ENTRY(clock, NETDEV_CLOCK)
ENTRY(mainclock, NETDEV_MAINCLOCK)
ENTRY(solver, NETDEV_SOLVER)

View File

@ -64,26 +64,24 @@
#include "nld_7427.h"
#include "nld_7430.h"
#include "nld_7474.h"
#include "nld_7483.h"
#include "nld_7486.h"
#include "nld_7490.h"
#include "nld_7493.h"
#include "nld_9316.h"
#include "nld_NE555.h"
#include "nld_log.h"
#include "nld_solver.h"
// this is a bad hack
// ----------------------------------------------------------------------------------------
// Special chips
// ----------------------------------------------------------------------------------------
#define NETDEV_LOGIC_INPUT(_name) \
NET_REGISTER_DEV(logic_input, _name)
#define NETDEV_ANALOG_INPUT(_name) \
NET_REGISTER_DEV(analog_input, _name)
#define NETDEV_CALLBACK(_name, _IN) \
NET_REGISTER_DEV(analog_callback, _name) \
NET_CONNECT(_name, IN, _IN)
#define NETDEV_SWITCH2(_name, _i1, _i2) \
NET_REGISTER_DEV(nicMultiSwitch, _name) \
NET_CONNECT(_name, i1, _i1) \
@ -120,26 +118,6 @@
NET_CONNECT(_name, BIQ, _BIQ) \
NET_CONNECT(_name, RBIQ, _RBIQ)
#define TTL_7483(_name, _A1, _A2, _A3, _A4, _B1, _B2, _B3, _B4, _CI) \
NET_REGISTER_DEV(nic7483, _name) \
NET_CONNECT(_name, A1, _A1) \
NET_CONNECT(_name, A2, _A2) \
NET_CONNECT(_name, A3, _A3) \
NET_CONNECT(_name, A4, _A4) \
NET_CONNECT(_name, B1, _B1) \
NET_CONNECT(_name, B2, _B2) \
NET_CONNECT(_name, B3, _B3) \
NET_CONNECT(_name, B4, _B4) \
NET_CONNECT(_name, CI, _CI)
#define TTL_7490(_name, _CLK, _R1, _R2, _R91, _R92) \
NET_REGISTER_DEV(nic7490, _name) \
NET_CONNECT(_name, CLK, _CLK) \
NET_CONNECT(_name, R1, _R1) \
NET_CONNECT(_name, R2, _R2) \
NET_CONNECT(_name, R91, _R91) \
NET_CONNECT(_name, R92, _R92)
#define TTL_74107A(_name, _CLK, _J, _K, _CLRQ) \
NET_REGISTER_DEV(nic74107A, _name) \
NET_CONNECT(_name, CLK, _CLK) \
@ -160,18 +138,6 @@
NET_CONNECT(_name, B, _B) \
NET_CONNECT(_name, GA, _GA)
#define TTL_9316(_name, _CLK, _ENP, _ENT, _CLRQ, _LOADQ, _A, _B, _C, _D) \
NET_REGISTER_DEV(nic9316, _name) \
NET_CONNECT(_name, CLK, _CLK) \
NET_CONNECT(_name, ENP, _ENP) \
NET_CONNECT(_name, ENT, _ENT) \
NET_CONNECT(_name, CLRQ, _CLRQ) \
NET_CONNECT(_name, LOADQ,_LOADQ) \
NET_CONNECT(_name, A, _A) \
NET_CONNECT(_name, B, _B) \
NET_CONNECT(_name, C, _C) \
NET_CONNECT(_name, D, _D)
#define NE555N_MSTABLE(_name, _TRIG, _CV) \
NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \
NET_CONNECT(_name, TRIG, _TRIG) \
@ -183,18 +149,6 @@
NET_CONNECT(_name, I2, _I2) \
NET_CONNECT(_name, I3, _I3)
// ----------------------------------------------------------------------------------------
// Special support devices ...
// ----------------------------------------------------------------------------------------
NETLIB_DEVICE(logic_input,
netlist_ttl_output_t m_Q;
);
NETLIB_DEVICE(analog_input,
netlist_analog_output_t m_Q;
);
// ----------------------------------------------------------------------------------------
// Special devices ...
// ----------------------------------------------------------------------------------------
@ -308,73 +262,9 @@ public:
};
NETLIB_DEVICE(nic7490,
ATTR_HOT void update_outputs();
netlist_ttl_input_t m_R1;
netlist_ttl_input_t m_R2;
netlist_ttl_input_t m_R91;
netlist_ttl_input_t m_R92;
netlist_ttl_input_t m_clk;
UINT8 m_cnt;
netlist_ttl_output_t m_Q[4];
);
/* ripple-carry counter on low-high clock transition */
NETLIB_SUBDEVICE(nic9316_sub,
ATTR_HOT void update_outputs_all();
ATTR_HOT void update_outputs();
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;
netlist_sig_t m_loadq;
netlist_sig_t m_ent;
netlist_ttl_output_t m_QA;
netlist_ttl_output_t m_QB;
netlist_ttl_output_t m_QC;
netlist_ttl_output_t m_QD;
netlist_ttl_output_t m_RC;
);
NETLIB_DEVICE(nic9316,
NETLIB_NAME(nic9316_sub) sub;
netlist_ttl_input_t m_ENP;
netlist_ttl_input_t m_ENT;
netlist_ttl_input_t m_CLRQ;
netlist_ttl_input_t m_LOADQ;
);
NETLIB_DEVICE(nic7483,
netlist_ttl_input_t m_CI;
netlist_ttl_input_t m_A1;
netlist_ttl_input_t m_A2;
netlist_ttl_input_t m_A3;
netlist_ttl_input_t m_A4;
netlist_ttl_input_t m_B1;
netlist_ttl_input_t m_B2;
netlist_ttl_input_t m_B3;
netlist_ttl_input_t m_B4;
netlist_ttl_input_t m_clk;
UINT8 m_lastr;
netlist_ttl_output_t m_SA;
netlist_ttl_output_t m_SB;
netlist_ttl_output_t m_SC;
netlist_ttl_output_t m_SD;
netlist_ttl_output_t m_CO;
);
/* one half of a nic74153 */

View File

@ -0,0 +1,46 @@
/*
* nld_7483.c
*
*/
#include "nld_7483.h"
NETLIB_START(nic7483)
{
m_lastr = 0;
register_input("A1", m_A1);
register_input("A2", m_A2);
register_input("A3", m_A3);
register_input("A4", m_A4);
register_input("B1", m_B1);
register_input("B2", m_B2);
register_input("B3", m_B3);
register_input("B4", m_B4);
register_input("C0", m_C0);
register_output("SA", m_SA);
register_output("SB", m_SB);
register_output("SC", m_SC);
register_output("SD", m_SD);
register_output("C4", m_C4);
}
NETLIB_UPDATE(nic7483)
{
UINT8 a = (INPLOGIC(m_A1) << 0) | (INPLOGIC(m_A2) << 1) | (INPLOGIC(m_A3) << 2) | (INPLOGIC(m_A4) << 3);
UINT8 b = (INPLOGIC(m_B1) << 0) | (INPLOGIC(m_B2) << 1) | (INPLOGIC(m_B3) << 2) | (INPLOGIC(m_B4) << 3);
UINT8 r = a + b + INPLOGIC(m_C0);
if (r != m_lastr)
{
m_lastr = r;
OUTLOGIC(m_SA, (r >> 0) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SB, (r >> 1) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SC, (r >> 2) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_SD, (r >> 3) & 1, NLTIME_FROM_NS(23));
OUTLOGIC(m_C4, (r >> 4) & 1, NLTIME_FROM_NS(23));
}
}

View File

@ -0,0 +1,65 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_7483.h
*
* DM7483: 4-Bit Binary Adder with Fast Carry
*
* +--------------+
* A4 |1 ++ 16| B4
* Ʃ3 |2 15| Ʃ3
* A3 |3 14| C4
* B3 |4 7483 13| C0
* VCC |5 12| GND
* Ʃ3 |6 11| B1
* B2 |7 10| A1
* A2 |8 9| Ʃ3
* +--------------+
*
* Ʃ = (A + B + C) & 0x0f
*
* C4 = (A + B + C) > 15 ? 1 : 0
*
* Naming conventions follow Fairchild Semiconductor datasheet
*
*/
#ifndef NLD_7483_H_
#define NLD_7483_H_
#include "../nl_base.h"
#define TTL_7483(_name, _A1, _A2, _A3, _A4, _B1, _B2, _B3, _B4, _CI) \
NET_REGISTER_DEV(nic7483, _name) \
NET_CONNECT(_name, A1, _A1) \
NET_CONNECT(_name, A2, _A2) \
NET_CONNECT(_name, A3, _A3) \
NET_CONNECT(_name, A4, _A4) \
NET_CONNECT(_name, B1, _B1) \
NET_CONNECT(_name, B2, _B2) \
NET_CONNECT(_name, B3, _B3) \
NET_CONNECT(_name, B4, _B4) \
NET_CONNECT(_name, C0, _CI)
NETLIB_DEVICE(nic7483,
netlist_ttl_input_t m_C0;
netlist_ttl_input_t m_A1;
netlist_ttl_input_t m_A2;
netlist_ttl_input_t m_A3;
netlist_ttl_input_t m_A4;
netlist_ttl_input_t m_B1;
netlist_ttl_input_t m_B2;
netlist_ttl_input_t m_B3;
netlist_ttl_input_t m_B4;
UINT8 m_lastr;
netlist_ttl_output_t m_SA;
netlist_ttl_output_t m_SB;
netlist_ttl_output_t m_SC;
netlist_ttl_output_t m_SD;
netlist_ttl_output_t m_C4;
);
#endif /* NLD_7483_H_ */

View File

@ -0,0 +1,59 @@
/*
* nld_7490.c
*
*/
#include "nld_7490.h"
NETLIB_START(nic7490)
{
m_cnt = 0;
register_input("CLK", m_clk);
register_input("R1", m_R1);
register_input("R2", m_R2);
register_input("R91", m_R91);
register_input("R92", m_R92);
register_output("QA", m_Q[0]);
register_output("QB", m_Q[1]);
register_output("QC", m_Q[2]);
register_output("QD", m_Q[3]);
}
NETLIB_UPDATE(nic7490)
{
if (INPLOGIC(m_R91) & INPLOGIC(m_R92))
{
m_cnt = 9;
update_outputs();
}
else if (INPLOGIC(m_R1) & INPLOGIC(m_R2))
{
m_cnt = 0;
update_outputs();
}
else if (INP_HL(m_clk))
{
m_cnt++;
if (m_cnt >= 10)
m_cnt = 0;
update_outputs();
}
}
#if 0
NETLIB_FUNC_VOID(nic7490, update_outputs)
{
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, NLTIME_FROM_NS(18));
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, NLTIME_FROM_NS(36));
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, NLTIME_FROM_NS(54));
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, NLTIME_FROM_NS(72));
}
#else
NETLIB_FUNC_VOID(nic7490, update_outputs, (void))
{
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++)
OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
}
#endif

View File

@ -0,0 +1,83 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_7490.h
*
* DM7490: Decade Counters
*
* +--------------+
* B |1 ++ 14| A
* R01 |2 13| NC
* R02 |3 12| QA
* NC |4 7490 11| QD
* VCC |5 10| GND
* R91 |6 9| QB
* R92 |7 8| QC
* +--------------+
*
* Counter Sequence
*
* +-------++----+----+----+----+
* | COUNT || QD | QC | QB | QA |
* +=======++====+====+====+====+
* | 0 || 0 | 0 | 0 | 0 |
* | 1 || 0 | 0 | 0 | 1 |
* | 2 || 0 | 0 | 1 | 0 |
* | 3 || 0 | 0 | 1 | 1 |
* | 4 || 0 | 1 | 0 | 0 |
* | 5 || 0 | 1 | 0 | 1 |
* | 6 || 0 | 1 | 1 | 0 |
* | 7 || 0 | 1 | 1 | 1 |
* | 8 || 1 | 0 | 0 | 0 |
* | 9 || 1 | 0 | 0 | 1 |
* +-------++----+----+----+----+
*
* Note A Output QA is connected to input B for BCD count
*
* Reset Count Function table
*
* +-----+-----+-----+-----++----+----+----+----+
* | R01 | R02 | R91 | R92 || QD | QC | QB | QA |
* +=====+=====+=====+=====++====+====+====+====+
* | 1 | 1 | 0 | X || 0 | 0 | 0 | 0 |
* | 1 | 1 | X | 0 || 0 | 0 | 0 | 0 |
* | X | X | 1 | 1 || 1 | 0 | 0 | 1 |
* | X | 0 | X | 0 || COUNT |
* | 0 | X | 0 | X || COUNT |
* | 0 | X | X | 0 || COUNT |
* | X | 0 | 0 | X || COUNT |
* +-----+-----+-----+-----++----+----+----+----+
*
* Naming conventions follow National Semiconductor datasheet
*
*/
#ifndef NLD_7490_H_
#define NLD_7490_H_
#include "../nl_base.h"
#define TTL_7490(_name, _CLK, _R1, _R2, _R91, _R92) \
NET_REGISTER_DEV(nic7490, _name) \
NET_CONNECT(_name, CLK, _CLK) \
NET_CONNECT(_name, R1, _R1) \
NET_CONNECT(_name, R2, _R2) \
NET_CONNECT(_name, R91, _R91) \
NET_CONNECT(_name, R92, _R92)
NETLIB_DEVICE(nic7490,
ATTR_HOT void update_outputs();
netlist_ttl_input_t m_R1;
netlist_ttl_input_t m_R2;
netlist_ttl_input_t m_R91;
netlist_ttl_input_t m_R92;
netlist_ttl_input_t m_clk;
UINT8 m_cnt;
netlist_ttl_output_t m_Q[4];
);
#endif /* NLD_7490_H_ */

View File

@ -3,7 +3,7 @@
/*
* nld_7493.h
*
* DM7493: Quad 2-Input NAND Gates
* DM7493: Binary Counters
*
* +--------------+
* B |1 ++ 14| A
@ -38,10 +38,12 @@
* | 15 || 1 | 1 | 1 | 1 |
* +-------++----+----+----+----+
*
* Note C Output QA is connected to input B
*
* Reset Count Function table
*
* +-----+-----++----+----+----+----+
* | R01 | R01 || QD | QC | QB | QA |
* | R01 | R02 || QD | QC | QB | QA |
* +=====+=====++====+====+====+====+
* | 1 | 1 || 0 | 0 | 0 | 0 |
* | 0 | X || COUNT |

View File

@ -0,0 +1,143 @@
/*
* nld_9316.c
*
*/
#include "nld_9316.h"
NETLIB_START(nic9316)
{
register_sub(sub, "sub");
register_subalias("CLK", sub.m_clk);
register_input("ENP", m_ENP);
register_input("ENT", m_ENT);
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("QA", sub.m_QA);
register_subalias("QB", sub.m_QB);
register_subalias("QC", sub.m_QC);
register_subalias("QD", sub.m_QD);
register_subalias("RC", sub.m_RC);
}
NETLIB_START(nic9316_sub)
{
m_cnt = 0;
m_loadq = 1;
m_ent = 1;
register_input("CLK", m_clk, netlist_input_t::STATE_INP_LH);
register_input("A", m_A, netlist_input_t::STATE_INP_PASSIVE);
register_input("B", m_B, netlist_input_t::STATE_INP_PASSIVE);
register_input("C", m_C, netlist_input_t::STATE_INP_PASSIVE);
register_input("D", m_D, netlist_input_t::STATE_INP_PASSIVE);
register_output("QA", m_QA);
register_output("QB", m_QB);
register_output("QC", m_QC);
register_output("QD", m_QD);
register_output("RC", m_RC);
}
NETLIB_UPDATE(nic9316_sub)
{
if (m_loadq)
{
m_cnt = ( m_cnt + 1) & 0x0f;
update_outputs();
}
else
{
m_cnt = (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
update_outputs_all();
}
OUTLOGIC(m_RC, m_ent & (m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_UPDATE(nic9316)
{
sub.m_loadq = INPLOGIC(m_LOADQ);
sub.m_ent = INPLOGIC(m_ENT);
const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
{
sub.m_clk.activate_lh();
}
else
{
sub.m_clk.inactivate();
if (!clrq & (sub.m_cnt>0))
{
sub.m_cnt = 0;
sub.update_outputs();
OUTLOGIC(sub.m_RC, 0, NLTIME_FROM_NS(20));
return;
}
}
OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == 0x0f), NLTIME_FROM_NS(20));
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs_all, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
}
NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
{
const netlist_time out_delay = NLTIME_FROM_NS(20);
#if 0
OUTLOGIC(m_QA, (m_cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (m_cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (m_cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (m_cnt >> 3) & 1, out_delay);
#else
if ((m_cnt & 1) == 1)
OUTLOGIC(m_QA, 1, out_delay);
else
{
OUTLOGIC(m_QA, 0, out_delay);
switch (m_cnt)
{
case 0x00:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 0, out_delay);
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
OUTLOGIC(m_QB, 1, out_delay);
break;
case 0x04:
case 0x0C:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 1, out_delay);
break;
case 0x08:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 1, out_delay);
break;
}
}
#endif
}

View File

@ -0,0 +1,96 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_9316.h
*
* DM9316: Synchronous 4-Bit Counters
*
* +--------------+
* CLEAR |1 ++ 16| VCC
* CLOCK |2 15| RC (Ripple Carry)
* A |3 14| QA
* B |4 9316 13| QB
* C |5 12| QC
* D |6 11| QD
* Enable P |7 10| Enable T
* GND |8 9| LOAD
* +--------------+
*
* Counter Sequence
*
* +-------++----+----+----+----+----+
* | COUNT || QD | QC | QB | QA | RC |
* +=======++====+====+====+====+====+
* | 0 || 0 | 0 | 0 | 0 | 0 |
* | 1 || 0 | 0 | 0 | 1 | 0 |
* | 2 || 0 | 0 | 1 | 0 | 0 |
* | 3 || 0 | 0 | 1 | 1 | 0 |
* | 4 || 0 | 1 | 0 | 0 | 0 |
* | 5 || 0 | 1 | 0 | 1 | 0 |
* | 6 || 0 | 1 | 1 | 0 | 0 |
* | 7 || 0 | 1 | 1 | 1 | 0 |
* | 8 || 1 | 0 | 0 | 0 | 0 |
* | 9 || 1 | 0 | 0 | 1 | 0 |
* | 10 || 1 | 0 | 1 | 0 | 0 |
* | 11 || 1 | 0 | 1 | 1 | 0 |
* | 12 || 1 | 1 | 0 | 0 | 0 |
* | 13 || 1 | 1 | 0 | 1 | 0 |
* | 14 || 1 | 1 | 1 | 0 | 0 |
* | 15 || 1 | 1 | 1 | 1 | 1 |
* +-------++----+----+----+----+----+
*
* Reset count function: Please refer to
* National Semiconductor datasheet (timing diagramm)
*
* Naming conventions follow National Semiconductor datasheet
*
*/
#ifndef NLD_9316_H_
#define NLD_9316_H_
#include "../nl_base.h"
#define TTL_9316(_name, _CLK, _ENP, _ENT, _CLRQ, _LOADQ, _A, _B, _C, _D) \
NET_REGISTER_DEV(nic9316, _name) \
NET_CONNECT(_name, CLK, _CLK) \
NET_CONNECT(_name, ENP, _ENP) \
NET_CONNECT(_name, ENT, _ENT) \
NET_CONNECT(_name, CLRQ, _CLRQ) \
NET_CONNECT(_name, LOADQ,_LOADQ) \
NET_CONNECT(_name, A, _A) \
NET_CONNECT(_name, B, _B) \
NET_CONNECT(_name, C, _C) \
NET_CONNECT(_name, D, _D)
NETLIB_SUBDEVICE(nic9316_sub,
ATTR_HOT void update_outputs_all();
ATTR_HOT void update_outputs();
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;
netlist_sig_t m_loadq;
netlist_sig_t m_ent;
netlist_ttl_output_t m_QA;
netlist_ttl_output_t m_QB;
netlist_ttl_output_t m_QC;
netlist_ttl_output_t m_QD;
netlist_ttl_output_t m_RC;
);
NETLIB_DEVICE(nic9316,
NETLIB_NAME(nic9316_sub) sub;
netlist_ttl_input_t m_ENP;
netlist_ttl_input_t m_ENT;
netlist_ttl_input_t m_CLRQ;
netlist_ttl_input_t m_LOADQ;
);
#endif /* NLD_9316_H_ */

View File

@ -24,6 +24,17 @@ NETLIB_NAME(log)::~NETLIB_NAME(log)()
fclose(m_file);
}
NETLIB_START(logD)
{
NETLIB_NAME(log)::start();
register_input("I2", m_I2);
}
NETLIB_UPDATE(logD)
{
fprintf(m_file, "%e %e\n", netlist().time().as_double(), INPANALOG(m_I) - INPANALOG(m_I2));
}
// FIXME: Implement wav later, this must be clock triggered device where the input to be written
// is on a subdevice ...
#if 0

View File

@ -27,10 +27,19 @@
NETLIB_DEVICE(log,
~NETLIB_NAME(log)();
netlist_analog_input_t m_I;
private:
protected:
FILE *m_file;
);
#define NETDEV_LOGD(_name, _I, _I2) \
NET_REGISTER_DEV(logD, _name) \
NET_CONNECT(_name, I, _I) \
NET_CONNECT(_name, I2, _I2)
NETLIB_DEVICE_DERIVED(logD, log,
netlist_analog_input_t m_I2;
);
#if 0
NETLIB_DEVICE(wav,
~NETLIB_NAME(wav)();

View File

@ -0,0 +1,333 @@
/*
* nld_solver.c
*
*/
#include "nld_solver.h"
// ----------------------------------------------------------------------------------------
// netlist_matrix_solver
// ----------------------------------------------------------------------------------------
ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets)
{
for (netlist_net_t::list_t::entry_t *pn = nets.first(); pn != NULL; pn = nets.next(pn))
{
NL_VERBOSE_OUT(("setting up net\n"));
m_nets.add(pn->object());
pn->object()->m_solver = this;
for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
{
switch (p->type())
{
case netlist_terminal_t::TERMINAL:
switch (p->netdev().family())
{
case netlist_device_t::CAPACITOR:
if (!m_steps.contains(&p->netdev()))
m_steps.add(&p->netdev());
break;
case netlist_device_t::DIODE:
//case netlist_device_t::VCVS:
//case netlist_device_t::BJT_SWITCH:
if (!m_dynamic.contains(&p->netdev()))
m_dynamic.add(&p->netdev());
break;
default:
break;
}
pn->object()->m_terms.add(static_cast<netlist_terminal_t *>(p));
NL_VERBOSE_OUT(("Added terminal\n"));
break;
case netlist_terminal_t::INPUT:
if (!m_inps.contains(&p->netdev()))
m_inps.add(&p->netdev());
NL_VERBOSE_OUT(("Added input\n"));
break;
default:
fatalerror("unhandled element found\n");
break;
}
}
}
}
ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta)
{
const double dd = delta.as_double();
for (dev_list_t::entry_t *p = m_steps.first(); p != NULL; p = m_steps.next(p))
p->object()->step_time(dd);
}
ATTR_HOT inline void netlist_matrix_solver_t::update_inputs()
{
for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
p->object()->update_dev();
}
ATTR_HOT inline bool netlist_matrix_solver_t::solve()
{
bool resched = false;
/* update all non-linear devices */
for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
p->object()->update_terminals();
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
netlist_net_t *net = pn->object();
double gtot = 0;
double gabs = 0;
double iIdr = 0;
const netlist_net_t::terminal_list_t &terms = net->m_terms;
#if 1
switch (terms.count())
{
case 1:
{
const netlist_terminal_t *pt = terms.first()->object();
gtot = pt->m_gt;
gabs = fabs(pt->m_go);
iIdr = pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
break;
case 2:
{
const netlist_terminal_t *pt1 = terms[0];
const netlist_terminal_t *pt2 = terms[1];
gtot = pt1->m_gt + pt2->m_gt;
gabs = fabs(pt1->m_go) + fabs(pt2->m_go);
iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
+ pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog();
}
break;
case 3:
{
const netlist_terminal_t *pt1 = terms[0];
const netlist_terminal_t *pt2 = terms[1];
const netlist_terminal_t *pt3 = terms[2];
gtot = pt1->m_gt + pt2->m_gt + pt3->m_gt;
gabs = fabs(pt1->m_go) + fabs(pt2->m_go) + fabs(pt3->m_go);
iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
+ pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog()
+ pt3->m_Idr + pt3->m_go * pt3->m_otherterm->net().Q_Analog();
}
break;
default:
for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
{
netlist_terminal_t *pt = e->object();
gtot += pt->m_gt;
gabs += fabs(pt->m_go);
iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
break;
}
#else
for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
{
netlist_terminal_t *pt = e->object();
gtot += pt->m_gt;
gabs += fabs(pt->m_go);
iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
#endif
double new_val;
gabs *= m_convergence_factor;
if (gabs > gtot)
new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs);
else
new_val = iIdr / gtot;
if (fabs(new_val - net->m_cur.Analog) > m_accuracy)
resched = true;
net->m_cur.Analog = net->m_new.Analog = new_val;
NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
}
return resched;
}
// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------
typedef netlist_net_t::list_t *net_groups_t;
static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
{
if (net->isRailNet())
return true;
for (int i = 0; i <= cur_group; i++)
{
if (groups[i].contains(net))
return true;
}
return false;
}
static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
{
/* add the net */
groups[cur_group].add(net);
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
{
if (p->isType(netlist_terminal_t::TERMINAL))
{
netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
netlist_net_t *nnet = &pt->m_otherterm->net();
if (!already_processed(groups, cur_group, nnet))
process_net(groups, cur_group, nnet);
}
}
}
NETLIB_START(solver)
{
register_output("Q_sync", m_Q_sync);
register_output("Q_step", m_Q_step);
//register_input("FB", m_feedback);
register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(10).as_double());
m_nt_sync_delay = m_sync_delay.Value();
register_param("FREQ", m_freq, 48000.0);
m_inc = netlist_time::from_hz(m_freq.Value());
register_param("ACCURACY", m_accuracy, 1e-3);
register_param("CONVERG", m_convergence, 0.3);
register_link_internal(m_fb_sync, m_Q_sync, netlist_input_t::STATE_INP_ACTIVE);
register_link_internal(m_fb_step, m_Q_step, netlist_input_t::STATE_INP_ACTIVE);
m_last_step = netlist_time::zero;
}
NETLIB_UPDATE_PARAM(solver)
{
m_inc = netlist_time::from_hz(m_freq.Value());
}
NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
{
netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first();
while (e != NULL)
{
netlist_matrix_solver_t::list_t::entry_t *en = m_mat_solvers.next(e);
delete e->object();
e = en;
}
netlist_net_t::list_t::entry_t *p = m_nets.first();
while (p != NULL)
{
netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
delete p->object();
p = pn;
}
}
NETLIB_FUNC_VOID(solver, post_start, ())
{
netlist_net_t::list_t groups[100];
int cur_group = -1;
NL_VERBOSE_OUT(("post start solver ...\n"));
// delete empty nets ...
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
if (pn->object()->m_head == NULL)
{
NL_VERBOSE_OUT(("Deleting net ...\n"));
netlist_net_t *to_delete = pn->object();
m_nets.remove(to_delete);
delete to_delete;
pn--;
}
}
printf("Scanning net groups ...\n");
// determine net groups
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
if (!already_processed(groups, cur_group, pn->object()))
{
cur_group++;
process_net(groups, cur_group, pn->object());
}
}
// setup the solvers
printf("Found %d net groups in %d nets\n", cur_group + 1, m_nets.count());
for (int i = 0; i <= cur_group; i++)
{
netlist_matrix_solver_t *ms = new netlist_matrix_solver_t;
ms->m_accuracy = m_accuracy.Value();
ms->m_convergence_factor = m_convergence.Value();
ms->setup(groups[i]);
m_mat_solvers.add(ms);
printf("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr());
printf(" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic");
}
}
NETLIB_UPDATE(solver)
{
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
//OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
bool resched = false;
int resched_cnt = 0;
netlist_time now = netlist().time();
netlist_time delta = now - m_last_step;
if (delta >= m_inc)
{
NL_VERBOSE_OUT(("Step!\n"));
/* update all terminals for new time step */
m_last_step = now;
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
e->object()->step(delta);
}
}
bool global_resched = false;
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
resched_cnt = (e->object()->is_dynamic() ? 0 : 1);
do {
resched = e->object()->solve();
resched_cnt++;
} while ((resched && (resched_cnt < 5)) || (resched_cnt <= 1));
global_resched = global_resched || resched;
}
//if (global_resched)
// printf("rescheduled\n");
if (global_resched)
{
schedule();
}
else
{
/* update all inputs connected */
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
e->object()->update_inputs();
}
/* step circuit */
if (!m_Q_step.net().is_queued())
m_Q_step.net().push_to_queue(m_inc);
}
}

View File

@ -0,0 +1,85 @@
/*
* nld_solver.h
*
*/
#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_
#include "../nl_setup.h"
#include "../nl_base.h"
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
#define NETDEV_SOLVER(_name) \
NET_REGISTER_DEV(solver, _name)
// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------
class netlist_matrix_solver_t
{
public:
typedef netlist_list_t<netlist_matrix_solver_t *> list_t;
typedef netlist_core_device_t::list_t dev_list_t;
ATTR_COLD void setup(netlist_net_t::list_t &nets);
// return true if a reschedule is needed ...
ATTR_HOT bool solve();
ATTR_HOT void step(const netlist_time delta);
ATTR_HOT void update_inputs();
ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; }
double m_accuracy;
double m_convergence_factor;
private:
netlist_net_t::list_t m_nets;
dev_list_t m_dynamic;
dev_list_t m_inps;
dev_list_t m_steps;
};
NETLIB_DEVICE_WITH_PARAMS(solver,
typedef netlist_core_device_t::list_t dev_list_t;
netlist_ttl_input_t m_fb_sync;
netlist_ttl_output_t m_Q_sync;
netlist_ttl_input_t m_fb_step;
netlist_ttl_output_t m_Q_step;
netlist_param_double_t m_freq;
netlist_param_double_t m_sync_delay;
netlist_param_double_t m_accuracy;
netlist_param_double_t m_convergence;
netlist_time m_inc;
netlist_time m_last_step;
netlist_time m_nt_sync_delay;
netlist_matrix_solver_t::list_t m_mat_solvers;
public:
~NETLIB_NAME(solver)();
netlist_net_t::list_t m_nets;
ATTR_HOT inline void schedule();
ATTR_COLD void post_start();
);
inline void NETLIB_NAME(solver)::schedule()
{
// FIXME: time should be parameter;
if (!m_Q_sync.net().is_queued())
m_Q_sync.net().push_to_queue(m_nt_sync_delay);
}
#endif /* NLD_SOLVER_H_ */

View File

@ -78,327 +78,27 @@ NETLIB_UPDATE(clock)
}
// ----------------------------------------------------------------------------------------
// netlist_matrix_solver
// logic_input
// ----------------------------------------------------------------------------------------
ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets)
NETLIB_START(logic_input)
{
for (netlist_net_t::list_t::entry_t *pn = nets.first(); pn != NULL; pn = nets.next(pn))
{
NL_VERBOSE_OUT(("setting up net\n"));
m_nets.add(pn->object());
pn->object()->m_solver = this;
for (netlist_core_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
{
switch (p->type())
{
case netlist_terminal_t::TERMINAL:
switch (p->netdev().family())
{
case netlist_device_t::CAPACITOR:
if (!m_steps.contains(&p->netdev()))
m_steps.add(&p->netdev());
break;
case netlist_device_t::DIODE:
//case netlist_device_t::VCVS:
//case netlist_device_t::BJT_SWITCH:
if (!m_dynamic.contains(&p->netdev()))
m_dynamic.add(&p->netdev());
break;
default:
break;
}
pn->object()->m_terms.add(static_cast<netlist_terminal_t *>(p));
NL_VERBOSE_OUT(("Added terminal\n"));
break;
case netlist_terminal_t::INPUT:
if (!m_inps.contains(&p->netdev()))
m_inps.add(&p->netdev());
NL_VERBOSE_OUT(("Added input\n"));
break;
default:
fatalerror("unhandled element found\n");
break;
}
}
}
register_output("Q", m_Q);
}
ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta)
NETLIB_UPDATE(logic_input)
{
const double dd = delta.as_double();
for (dev_list_t::entry_t *p = m_steps.first(); p != NULL; p = m_steps.next(p))
p->object()->step_time(dd);
}
ATTR_HOT inline void netlist_matrix_solver_t::update_inputs()
{
for (dev_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
p->object()->update_dev();
}
ATTR_HOT inline bool netlist_matrix_solver_t::solve()
{
bool resched = false;
/* update all non-linear devices */
for (dev_list_t::entry_t *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p))
p->object()->update_terminals();
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
netlist_net_t *net = pn->object();
double gtot = 0;
double gabs = 0;
double iIdr = 0;
const netlist_net_t::terminal_list_t &terms = net->m_terms;
#if 1
switch (terms.count())
{
case 1:
{
const netlist_terminal_t *pt = terms.first()->object();
gtot = pt->m_gt;
gabs = fabs(pt->m_go);
iIdr = pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
break;
case 2:
{
const netlist_terminal_t *pt1 = terms.first()->object();
const netlist_terminal_t *pt2 = terms.item(1)->object();
gtot = pt1->m_gt + pt2->m_gt;
gabs = fabs(pt1->m_go) + fabs(pt2->m_go);
iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
+ pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog();
}
break;
case 3:
{
const netlist_terminal_t *pt1 = terms.first()->object();
const netlist_terminal_t *pt2 = terms.item(1)->object();
const netlist_terminal_t *pt3 = terms.item(2)->object();
gtot = pt1->m_gt + pt2->m_gt + pt3->m_gt;
gabs = fabs(pt1->m_go) + fabs(pt2->m_go) + fabs(pt3->m_go);
iIdr = pt1->m_Idr + pt1->m_go * pt1->m_otherterm->net().Q_Analog()
+ pt2->m_Idr + pt2->m_go * pt2->m_otherterm->net().Q_Analog()
+ pt3->m_Idr + pt3->m_go * pt3->m_otherterm->net().Q_Analog();
}
break;
default:
for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
{
netlist_terminal_t *pt = e->object();
gtot += pt->m_gt;
gabs += fabs(pt->m_go);
iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
break;
}
#else
for (netlist_net_t::terminal_list_t::entry_t *e = terms.first(); e != NULL; e = terms.next(e))
{
netlist_terminal_t *pt = e->object();
gtot += pt->m_gt;
gabs += fabs(pt->m_go);
iIdr += pt->m_Idr + pt->m_go * pt->m_otherterm->net().Q_Analog();
}
#endif
double new_val;
gabs *= m_convergence_factor;
if (gabs > gtot)
new_val = (net->m_cur.Analog * gabs + iIdr) / (gtot + gabs);
else
new_val = iIdr / gtot;
if (fabs(new_val - net->m_cur.Analog) > m_accuracy)
resched = true;
net->m_cur.Analog = net->m_new.Analog = new_val;
NL_VERBOSE_OUT(("Info: %d\n", pn->object()->m_num_cons));
NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
}
return resched;
}
// ----------------------------------------------------------------------------------------
// solver
// analog_input
// ----------------------------------------------------------------------------------------
typedef netlist_net_t::list_t *net_groups_t;
static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
NETLIB_START(analog_input)
{
if (net->isRailNet())
return true;
for (int i = 0; i <= cur_group; i++)
{
if (groups[i].contains(net))
return true;
}
return false;
register_output("Q", m_Q);
}
static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
NETLIB_UPDATE(analog_input)
{
/* add the net */
groups[cur_group].add(net);
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
{
if (p->isType(netlist_terminal_t::TERMINAL))
{
netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
netlist_net_t *nnet = &pt->m_otherterm->net();
if (!already_processed(groups, cur_group, nnet))
process_net(groups, cur_group, nnet);
}
}
}
NETLIB_START(solver)
{
register_output("Q_sync", m_Q_sync);
register_output("Q_step", m_Q_step);
//register_input("FB", m_feedback);
register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(10).as_double());
m_nt_sync_delay = m_sync_delay.Value();
register_param("FREQ", m_freq, 48000.0);
m_inc = netlist_time::from_hz(m_freq.Value());
register_param("ACCURACY", m_accuracy, 1e-3);
register_param("CONVERG", m_convergence, 0.3);
register_link_internal(m_fb_sync, m_Q_sync, netlist_input_t::STATE_INP_ACTIVE);
register_link_internal(m_fb_step, m_Q_step, netlist_input_t::STATE_INP_ACTIVE);
m_last_step = netlist_time::zero;
}
NETLIB_UPDATE_PARAM(solver)
{
m_inc = netlist_time::from_hz(m_freq.Value());
}
NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
{
netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first();
while (e != NULL)
{
netlist_matrix_solver_t::list_t::entry_t *en = m_mat_solvers.next(e);
delete e->object();
e = en;
}
netlist_net_t::list_t::entry_t *p = m_nets.first();
while (p != NULL)
{
netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
delete p->object();
p = pn;
}
}
NETLIB_FUNC_VOID(solver, post_start, ())
{
netlist_net_t::list_t groups[100];
int cur_group = -1;
NL_VERBOSE_OUT(("post start solver ...\n"));
// delete empty nets ...
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
if (pn->object()->m_head == NULL)
{
NL_VERBOSE_OUT(("Deleting net ...\n"));
netlist_net_t *to_delete = pn->object();
m_nets.remove(to_delete);
delete to_delete;
pn--;
}
}
printf("Scanning net groups ...\n");
// determine net groups
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
{
if (!already_processed(groups, cur_group, pn->object()))
{
cur_group++;
process_net(groups, cur_group, pn->object());
}
}
// setup the solvers
printf("Found %d net groups in %d nets\n", cur_group + 1, m_nets.count());
for (int i = 0; i <= cur_group; i++)
{
netlist_matrix_solver_t *ms = new netlist_matrix_solver_t;
ms->m_accuracy = m_accuracy.Value();
ms->m_convergence_factor = m_convergence.Value();
ms->setup(groups[i]);
m_mat_solvers.add(ms);
printf("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr());
printf(" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic");
}
}
NETLIB_UPDATE(solver)
{
//m_Q.setToNoCheck(!m_Q.new_Q(), m_inc );
//OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc );
bool resched = false;
int resched_cnt = 0;
netlist_time now = netlist().time();
netlist_time delta = now - m_last_step;
if (delta >= m_inc)
{
NL_VERBOSE_OUT(("Step!\n"));
/* update all terminals for new time step */
m_last_step = now;
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
e->object()->step(delta);
}
}
bool global_resched = false;
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
resched_cnt = (e->object()->is_dynamic() ? 0 : 1);
do {
resched = e->object()->solve();
resched_cnt++;
} while ((resched && (resched_cnt < 5)) || (resched_cnt <= 1));
global_resched = global_resched || resched;
}
//if (global_resched)
// printf("rescheduled\n");
if (global_resched)
{
schedule();
}
else
{
/* update all inputs connected */
for (netlist_matrix_solver_t::list_t::entry_t *e = m_mat_solvers.first(); e != NULL; e = m_mat_solvers.next(e))
{
e->object()->update_inputs();
}
/* step circuit */
if (!m_Q_step.net().is_queued())
m_Q_step.net().push_to_queue(m_inc);
}
}

View File

@ -30,10 +30,15 @@
#define NETDEV_CLOCK(_name) \
NET_REGISTER_DEV(clock, _name)
#define NETDEV_SOLVER(_name) \
NET_REGISTER_DEV(solver, _name)
#define NETDEV_LOGIC_INPUT(_name) \
NET_REGISTER_DEV(logic_input, _name)
// .model 1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)
#define NETDEV_ANALOG_INPUT(_name) \
NET_REGISTER_DEV(analog_input, _name)
#define NETDEV_CALLBACK(_name, _IN) \
NET_REGISTER_DEV(analog_callback, _name) \
NET_CONNECT(_name, IN, _IN)
// ----------------------------------------------------------------------------------------
// netdev_*_const
@ -75,70 +80,6 @@ NETLIB_DEVICE_WITH_PARAMS(clock,
netlist_time m_inc;
);
// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------
class netlist_matrix_solver_t
{
public:
typedef netlist_list_t<netlist_matrix_solver_t *> list_t;
typedef netlist_core_device_t::list_t dev_list_t;
ATTR_COLD void setup(netlist_net_t::list_t &nets);
// return true if a reschedule is needed ...
ATTR_HOT bool solve();
ATTR_HOT void step(const netlist_time delta);
ATTR_HOT void update_inputs();
ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; }
double m_accuracy;
double m_convergence_factor;
private:
netlist_net_t::list_t m_nets;
dev_list_t m_dynamic;
dev_list_t m_inps;
dev_list_t m_steps;
};
NETLIB_DEVICE_WITH_PARAMS(solver,
typedef netlist_core_device_t::list_t dev_list_t;
netlist_ttl_input_t m_fb_sync;
netlist_ttl_output_t m_Q_sync;
netlist_ttl_input_t m_fb_step;
netlist_ttl_output_t m_Q_step;
netlist_param_double_t m_freq;
netlist_param_double_t m_sync_delay;
netlist_param_double_t m_accuracy;
netlist_param_double_t m_convergence;
netlist_time m_inc;
netlist_time m_last_step;
netlist_time m_nt_sync_delay;
netlist_matrix_solver_t::list_t m_mat_solvers;
public:
~NETLIB_NAME(solver)();
netlist_net_t::list_t m_nets;
ATTR_HOT inline void schedule();
ATTR_COLD void post_start();
);
inline void NETLIB_NAME(solver)::schedule()
{
// FIXME: time should be parameter;
if (!m_Q_sync.net().is_queued())
m_Q_sync.net().push_to_queue(m_nt_sync_delay);
}
// ----------------------------------------------------------------------------------------
// netdev_callback
@ -168,6 +109,18 @@ private:
netlist_output_delegate m_callback;
};
// ----------------------------------------------------------------------------------------
// Special support devices ...
// ----------------------------------------------------------------------------------------
NETLIB_DEVICE(logic_input,
netlist_ttl_output_t m_Q;
);
NETLIB_DEVICE(analog_input,
netlist_analog_output_t m_Q;
);
#endif /* NLD_SYSTEM_H_ */

View File

@ -5,6 +5,7 @@
#include "nld_twoterm.h"
#include "nld_system.h"
#include "nld_solver.h"
// ----------------------------------------------------------------------------------------
// nld_twoterm

View File

@ -24,11 +24,15 @@ NETLISTOBJS+= \
$(NETLISTOBJ)/nl_parser.o \
$(NETLISTOBJ)/devices/nld_system.o \
$(NETLISTOBJ)/devices/nld_twoterm.o \
$(NETLISTOBJ)/devices/nld_solver.o \
$(NETLISTOBJ)/devices/net_lib.o \
$(NETLISTOBJ)/devices/nld_7404.o \
$(NETLISTOBJ)/devices/nld_7474.o \
$(NETLISTOBJ)/devices/nld_7483.o \
$(NETLISTOBJ)/devices/nld_7486.o \
$(NETLISTOBJ)/devices/nld_7490.o \
$(NETLISTOBJ)/devices/nld_7493.o \
$(NETLISTOBJ)/devices/nld_9316.o \
$(NETLISTOBJ)/devices/nld_NE555.o \
$(NETLISTOBJ)/devices/nld_log.o \

View File

@ -6,6 +6,7 @@
#include "nl_base.h"
#include "devices/nld_system.h"
#include "pstring.h"
#include "nl_util.h"
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
@ -280,7 +281,7 @@ ATTR_COLD void netlist_device_t::register_sub(netlist_device_t &dev, const pstri
dev.init(*m_setup, this->name() + "." + name);
}
ATTR_COLD void netlist_device_t::register_subalias(const pstring &name, netlist_core_terminal_t &term)
ATTR_COLD void netlist_device_t::register_subalias(const pstring &name, const netlist_core_terminal_t &term)
{
pstring alias = this->name() + "." + name;
@ -330,14 +331,14 @@ static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term,
}
// FIXME: Revise internal links ...
ATTR_COLD void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState)
ATTR_COLD void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState)
{
init_term(dev, in, aState);
init_term(dev, out, aState);
m_setup->connect(in, out);
}
ATTR_COLD void netlist_device_t::register_link_internal(netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState)
ATTR_COLD void netlist_device_t::register_link_internal(netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState)
{
register_link_internal(*this, in, out, aState);
}
@ -422,7 +423,7 @@ ATTR_COLD void netlist_net_t::register_con(netlist_core_terminal_t &terminal)
m_active++;
}
ATTR_HOT inline void netlist_net_t::update_dev(const netlist_core_terminal_t *inp, const UINT32 mask)
ATTR_HOT inline void netlist_net_t::update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const
{
if ((inp->state() & mask) != 0)
{
@ -602,7 +603,6 @@ NETLIB_START(mainclock)
register_param("FREQ", m_freq, 7159000.0 * 5);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_UPDATE_PARAM(mainclock)

View File

@ -243,7 +243,8 @@ class netlist_param_t;
class netlist_setup_t;
class netlist_base_t;
class netlist_matrix_solver_t;
class NETLIB_NAME(solver);
class NETLIB_NAME(mainclock);
// ----------------------------------------------------------------------------------------
// netlist_object_t
@ -339,7 +340,7 @@ public:
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname, const state_e astate);
ATTR_COLD void set_net(netlist_net_t &anet);
ATTR_COLD inline bool has_net() { return (m_net != NULL); }
ATTR_COLD inline bool has_net() const { return (m_net != NULL); }
ATTR_HOT inline const netlist_net_t & RESTRICT net() const { return *m_net;}
ATTR_HOT inline netlist_net_t & RESTRICT net() { return *m_net;}
@ -483,14 +484,9 @@ public:
typedef netlist_list_t<netlist_net_t *> list_t;
friend class NETLIB_NAME(mainclock);
friend class NETLIB_NAME(solver);
friend class netlist_matrix_solver_t;
friend class netlist_output_t;
friend class netlist_input_t;
friend class netlist_logic_output_t;
friend class netlist_analog_output_t;
friend class netlist_logic_input_t;
friend class netlist_analog_input_t;
// FIXME: union does not work
typedef struct
@ -511,9 +507,8 @@ public:
ATTR_HOT inline const netlist_time time() const { return m_time; }
ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; }
ATTR_HOT inline bool isRailNet() { return !(m_railterminal == NULL); }
ATTR_HOT inline bool isRailNet() const { return !(m_railterminal == NULL); }
ATTR_HOT inline const netlist_core_terminal_t & RESTRICT railterminal() const { return *m_railterminal; }
ATTR_HOT inline const netlist_core_terminal_t & RESTRICT railterminal() { return *m_railterminal; }
/* Everything below is used by the logic subsystem */
@ -522,8 +517,23 @@ public:
ATTR_HOT inline const int active_count() const { return m_active; }
ATTR_HOT inline const netlist_sig_t last_Q() const { return m_last.Q; }
ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new.Q; }
ATTR_HOT inline const netlist_sig_t Q() const
{
assert(family() == LOGIC);
return m_cur.Q;
}
ATTR_HOT inline const netlist_sig_t last_Q() const
{
assert(family() == LOGIC);
return m_last.Q;
}
ATTR_HOT inline const netlist_sig_t new_Q() const
{
assert(family() == LOGIC);
return m_new.Q;
}
ATTR_HOT inline const double Q_Analog() const
{
@ -544,15 +554,6 @@ public:
protected:
/* prohibit use in device functions
* current (pending) state can be inquired using new_Q()
*/
ATTR_HOT inline const netlist_sig_t Q() const
{
//assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
assert(family() == LOGIC);
return m_cur.Q;
}
hybrid_t m_last;
hybrid_t m_cur;
@ -561,7 +562,7 @@ protected:
UINT32 m_num_cons;
private:
ATTR_HOT void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask);
ATTR_HOT void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const;
netlist_time m_time;
INT32 m_active;
@ -575,9 +576,6 @@ private:
// net_output_t
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(mainclock);
class NETLIB_NAME(solver);
class netlist_output_t : public netlist_core_terminal_t
{
public:
@ -860,29 +858,29 @@ public:
ATTR_COLD netlist_setup_t *setup() const { return m_setup; }
ATTR_COLD bool variable_input_count() { return m_variable_input_count; }
// FIXME: Legacy ... this needs to disappear
ATTR_COLD bool variable_input_count() const { return m_variable_input_count; }
ATTR_COLD void register_sub(netlist_device_t &dev, const pstring &name);
ATTR_COLD void register_subalias(const pstring &name, netlist_core_terminal_t &term);
ATTR_COLD void register_subalias(const pstring &name, const netlist_core_terminal_t &term);
ATTR_COLD void register_terminal(const pstring &name, netlist_terminal_t &port);
ATTR_COLD void register_output(const pstring &name, netlist_output_t &out);
ATTR_COLD void register_input(const pstring &name, netlist_input_t &in, netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
ATTR_COLD void register_input(const pstring &name, netlist_input_t &in, const netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
ATTR_COLD void register_link_internal(netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState);
ATTR_COLD void register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState);
ATTR_HOT virtual void update_terminals() { }
ATTR_COLD void register_link_internal(netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState);
ATTR_COLD void register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState);
/* driving logic outputs don't count in here */
netlist_list_t<pstring, 20> m_terminals;
protected:
virtual void update() { }
virtual void start() { }
ATTR_HOT virtual void update() { }
ATTR_HOT virtual void start() { }
ATTR_HOT virtual void update_terminals() { }
template <class C, class T>
ATTR_COLD void register_param(const pstring &sname, C &param, const T initialVal)
@ -915,6 +913,7 @@ public:
ATTR_COLD void set_clock_freq(UINT64 clockfreq);
ATTR_HOT inline const queue_t &queue() const { return m_queue; }
ATTR_HOT inline queue_t &queue() { return m_queue; }
ATTR_HOT inline void push_to_queue(netlist_net_t &out, const netlist_time &attime)
@ -922,7 +921,7 @@ public:
m_queue.push(queue_t::entry_t(attime, out));
}
ATTR_HOT NETLIB_NAME(solver) *solver() { return m_solver; }
ATTR_HOT NETLIB_NAME(solver) *solver() const { return m_solver; }
ATTR_HOT void process_queue(INT32 &atime);
@ -961,7 +960,7 @@ private:
class nld_a_to_d_proxy : public netlist_device_t
{
public:
nld_a_to_d_proxy(netlist_input_t &in_proxied)
ATTR_COLD nld_a_to_d_proxy(netlist_input_t &in_proxied)
: netlist_device_t()
{
//assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
@ -970,13 +969,13 @@ public:
m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
}
virtual ~nld_a_to_d_proxy() {}
ATTR_COLD virtual ~nld_a_to_d_proxy() {}
netlist_analog_input_t m_I;
netlist_ttl_output_t m_Q;
protected:
void start()
ATTR_COLD void start()
{
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
@ -1003,7 +1002,7 @@ protected:
class nld_d_to_a_proxy : public netlist_device_t
{
public:
nld_d_to_a_proxy(netlist_output_t &out_proxied)
ATTR_COLD nld_d_to_a_proxy(netlist_output_t &out_proxied)
: netlist_device_t()
{
//assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
@ -1012,13 +1011,13 @@ public:
m_high_V = out_proxied.m_high_V;
}
virtual ~nld_d_to_a_proxy() {}
ATTR_COLD virtual ~nld_d_to_a_proxy() {}
netlist_ttl_input_t m_I;
netlist_analog_output_t m_Q;
protected:
void start()
ATTR_COLD void start()
{
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
m_Q.init_object(*this, "Q");
@ -1158,6 +1157,7 @@ ATTR_HOT inline const double netlist_analog_input_t::Q_Analog() const
return net().Q_Analog();
}
//FIXME: Legacy ... must be removed
ATTR_HOT inline const bool netlist_analog_input_t::is_highz() const
{
return (net().Q_Analog() == NETLIST_HIGHIMP_V);

View File

@ -66,6 +66,12 @@ typedef delegate<void (const double)> netlist_output_delegate;
// MACROS
//============================================================
// prevent implicit copying
#define NETLIST_PREVENT_COPYING(_name) \
private: \
_name(const _name &); \
_name &operator=(const _name &); \
#if NL_KEEP_STATISTICS
#define add_to_stat(v,x) do { v += (x); } while (0)
#define inc_stat(v) add_to_stat(v, 1)

View File

@ -35,6 +35,28 @@ public:
m_ptr = m_list;
m_ptr--;
}
ATTR_COLD netlist_list_t(const netlist_list_t &rhs)
{
m_list = new entry_t[m_num_elements];
m_ptr = m_list;
m_ptr--;
for (int i=0; i<rhs.count(); i++)
{
this->add(rhs[i]);
}
}
ATTR_COLD netlist_list_t &operator=(const netlist_list_t &rhs)
{
for (int i=0; i<rhs.count(); i++)
{
this->add(rhs[i]);
}
return *this;
}
ATTR_COLD ~netlist_list_t()
{
delete[] m_list;
@ -87,10 +109,14 @@ public:
ATTR_HOT inline entry_t *first() const { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
ATTR_HOT inline entry_t *next(entry_t *lc) const { return (lc < last() ? lc + 1 : NULL ); }
ATTR_HOT inline entry_t *last() const { return m_ptr; }
ATTR_HOT inline entry_t *item(int i) const { return &m_list[i]; }
ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }
ATTR_HOT inline bool empty() const { return (m_ptr < m_list); }
ATTR_HOT inline void reset() { m_ptr = m_list - 1; }
//ATTR_HOT inline entry_t *item(int i) const { return &m_list[i]; }
ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index].m_obj; }
ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index].m_obj; }
private:
entry_t * m_ptr;
entry_t * m_list;

View File

@ -8,7 +8,9 @@
#include "nl_base.h"
#include "nl_setup.h"
#include "nl_parser.h"
#include "nl_util.h"
#include "devices/nld_system.h"
#include "devices/nld_solver.h"
static NETLIST_START(base)
NETDEV_TTL_CONST(ttlhigh, 1)
@ -139,7 +141,7 @@ pstring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
fatalerror("Unknown object type %d\n", in.type());
}
void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const pstring &name, netlist_object_t &obj, netlist_input_t::state_e state)
void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const pstring &name, netlist_object_t &obj, const netlist_input_t::state_e state)
{
switch (obj.type())
{
@ -248,7 +250,7 @@ const pstring netlist_setup_t::resolve_alias(const pstring &name) const
if (dev == NULL)
fatalerror("Device for %s not found\n", name.cstr());
int c = atoi(ret.substr(p+2,ret.len()-p-3));
temp = dev->name() + "." + dev->m_terminals.item(c)->object();
temp = dev->name() + "." + dev->m_terminals[c];
// reresolve ....
do {
ret = temp;
@ -517,6 +519,21 @@ void netlist_setup_t::resolve_inputs(void)
void netlist_setup_t::start_devices(void)
{
if (getenv("NL_LOGS"))
{
NL_VERBOSE_OUT(("Creating dynamic logs ...\n"));
nl_util::pstring_list ll = nl_util::split(getenv("NL_LOGS"), ":");
for (int i=0; i < ll.count(); i++)
{
printf("%d: <%s>\n",i, ll[i].cstr());
netlist_device_t *nc = factory().new_device_by_classname("nld_log", *this);
pstring name = "log" + ll[i];
register_dev(nc, name);
register_link(name + ".I", ll[i]);
}
}
NL_VERBOSE_OUT(("Searching for mainclock and solver ...\n"));
/* find the main clock ... */
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))

41
src/emu/netlist/nl_util.h Normal file
View File

@ -0,0 +1,41 @@
/*
* nl_util.h
*
*/
#ifndef NL_UTIL_H_
#define NL_UTIL_H_
#include "pstring.h"
#include "nl_lists.h"
class nl_util
{
// this is purely static
private:
nl_util() {};
public:
typedef netlist_list_t<pstring, 10> pstring_list;
static pstring_list split(const pstring &str, const pstring &onstr)
{
pstring_list temp;
int p = 0;
int pn;
pn = str.find(onstr, p);
while (pn>=0)
{
temp.add(str.substr(p, pn - p));
p = pn + onstr.len();
pn = str.find(onstr, p);
}
if (p<str.len())
temp.add(str.substr(p));
return temp;
}
};
#endif /* NL_UTIL_H_ */