- 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_7430.h svneol=native#text/plain
src/emu/netlist/devices/nld_7474.c 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_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.c svneol=native#text/plain
src/emu/netlist/devices/nld_7486.h 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.c svneol=native#text/plain
src/emu/netlist/devices/nld_7493.h 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.c svneol=native#text/plain
src/emu/netlist/devices/nld_NE555.h 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.c svneol=native#text/plain
src/emu/netlist/devices/nld_log.h 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_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.c svneol=native#text/plain
src/emu/netlist/devices/nld_system.h 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 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.c svneol=native#text/plain
src/emu/netlist/nl_setup.h 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_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.c svneol=native#text/plain
src/emu/netlist/pstring.h svneol=native#text/plain src/emu/netlist/pstring.h svneol=native#text/plain
src/emu/network.c svneol=native#text/plain src/emu/network.c svneol=native#text/plain

View File

@ -50,24 +50,6 @@
#include "net_lib.h" #include "net_lib.h"
#include "nld_system.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) NETLIB_START(nicMultiSwitch)
{ {
static const char *sIN[8] = { "i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8" }; static const char *sIN[8] = { "i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8" };
@ -418,97 +400,8 @@ NETLIB_UPDATE(nic7450)
} }
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) NETLIB_START(nic74107Asub)
{ {
@ -626,141 +519,6 @@ NETLIB_UPDATE(nic74153)
} }
} }
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 xstr(s) # s
#define ENTRY1(_nic, _name) m_list.add(new net_device_t_factory< _nic >( # _name, xstr(_nic) )); #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(logic_input, NETDEV_LOGIC_INPUT)
ENTRY(analog_input, NETDEV_ANALOG_INPUT) ENTRY(analog_input, NETDEV_ANALOG_INPUT)
ENTRY(log, NETDEV_LOG) ENTRY(log, NETDEV_LOG)
ENTRY(logD, NETDEV_LOGD)
ENTRY(clock, NETDEV_CLOCK) ENTRY(clock, NETDEV_CLOCK)
ENTRY(mainclock, NETDEV_MAINCLOCK) ENTRY(mainclock, NETDEV_MAINCLOCK)
ENTRY(solver, NETDEV_SOLVER) ENTRY(solver, NETDEV_SOLVER)

View File

@ -64,26 +64,24 @@
#include "nld_7427.h" #include "nld_7427.h"
#include "nld_7430.h" #include "nld_7430.h"
#include "nld_7474.h" #include "nld_7474.h"
#include "nld_7483.h"
#include "nld_7486.h" #include "nld_7486.h"
#include "nld_7490.h"
#include "nld_7493.h" #include "nld_7493.h"
#include "nld_9316.h"
#include "nld_NE555.h" #include "nld_NE555.h"
#include "nld_log.h" #include "nld_log.h"
#include "nld_solver.h"
// this is a bad hack // this is a bad hack
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Special chips // 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) \ #define NETDEV_SWITCH2(_name, _i1, _i2) \
NET_REGISTER_DEV(nicMultiSwitch, _name) \ NET_REGISTER_DEV(nicMultiSwitch, _name) \
NET_CONNECT(_name, i1, _i1) \ NET_CONNECT(_name, i1, _i1) \
@ -120,26 +118,6 @@
NET_CONNECT(_name, BIQ, _BIQ) \ NET_CONNECT(_name, BIQ, _BIQ) \
NET_CONNECT(_name, RBIQ, _RBIQ) 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) \ #define TTL_74107A(_name, _CLK, _J, _K, _CLRQ) \
NET_REGISTER_DEV(nic74107A, _name) \ NET_REGISTER_DEV(nic74107A, _name) \
NET_CONNECT(_name, CLK, _CLK) \ NET_CONNECT(_name, CLK, _CLK) \
@ -160,18 +138,6 @@
NET_CONNECT(_name, B, _B) \ NET_CONNECT(_name, B, _B) \
NET_CONNECT(_name, GA, _GA) 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) \ #define NE555N_MSTABLE(_name, _TRIG, _CV) \
NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \ NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \
NET_CONNECT(_name, TRIG, _TRIG) \ NET_CONNECT(_name, TRIG, _TRIG) \
@ -183,18 +149,6 @@
NET_CONNECT(_name, I2, _I2) \ NET_CONNECT(_name, I2, _I2) \
NET_CONNECT(_name, I3, _I3) 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 ... // 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 */ /* 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 */ /* 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 * nld_7493.h
* *
* DM7493: Quad 2-Input NAND Gates * DM7493: Binary Counters
* *
* +--------------+ * +--------------+
* B |1 ++ 14| A * B |1 ++ 14| A
@ -38,10 +38,12 @@
* | 15 || 1 | 1 | 1 | 1 | * | 15 || 1 | 1 | 1 | 1 |
* +-------++----+----+----+----+ * +-------++----+----+----+----+
* *
* Note C Output QA is connected to input B
*
* Reset Count Function table * Reset Count Function table
* *
* +-----+-----++----+----+----+----+ * +-----+-----++----+----+----+----+
* | R01 | R01 || QD | QC | QB | QA | * | R01 | R02 || QD | QC | QB | QA |
* +=====+=====++====+====+====+====+ * +=====+=====++====+====+====+====+
* | 1 | 1 || 0 | 0 | 0 | 0 | * | 1 | 1 || 0 | 0 | 0 | 0 |
* | 0 | X || COUNT | * | 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); 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 // FIXME: Implement wav later, this must be clock triggered device where the input to be written
// is on a subdevice ... // is on a subdevice ...
#if 0 #if 0

View File

@ -27,10 +27,19 @@
NETLIB_DEVICE(log, NETLIB_DEVICE(log,
~NETLIB_NAME(log)(); ~NETLIB_NAME(log)();
netlist_analog_input_t m_I; netlist_analog_input_t m_I;
private: protected:
FILE *m_file; 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 #if 0
NETLIB_DEVICE(wav, NETLIB_DEVICE(wav,
~NETLIB_NAME(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
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
NETLIB_START(logic_input)
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)) register_output("Q", m_Q);
{
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) 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; NETLIB_START(analog_input)
static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net)
{ {
if (net->isRailNet()) register_output("Q", m_Q);
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) 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) \ #define NETDEV_CLOCK(_name) \
NET_REGISTER_DEV(clock, _name) NET_REGISTER_DEV(clock, _name)
#define NETDEV_SOLVER(_name) \ #define NETDEV_LOGIC_INPUT(_name) \
NET_REGISTER_DEV(solver, _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 // netdev_*_const
@ -75,70 +80,6 @@ NETLIB_DEVICE_WITH_PARAMS(clock,
netlist_time m_inc; 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 // netdev_callback
@ -168,6 +109,18 @@ private:
netlist_output_delegate m_callback; 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_ */ #endif /* NLD_SYSTEM_H_ */

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include "nl_base.h" #include "nl_base.h"
#include "devices/nld_system.h" #include "devices/nld_system.h"
#include "pstring.h" #include "pstring.h"
#include "nl_util.h"
const netlist_time netlist_time::zero = netlist_time::from_raw(0); 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); 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; 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 ... // 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, in, aState);
init_term(dev, out, aState); init_term(dev, out, aState);
m_setup->connect(in, out); 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); 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++; 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) if ((inp->state() & mask) != 0)
{ {
@ -602,7 +603,6 @@ NETLIB_START(mainclock)
register_param("FREQ", m_freq, 7159000.0 * 5); register_param("FREQ", m_freq, 7159000.0 * 5);
m_inc = netlist_time::from_hz(m_freq.Value()*2); m_inc = netlist_time::from_hz(m_freq.Value()*2);
} }
NETLIB_UPDATE_PARAM(mainclock) NETLIB_UPDATE_PARAM(mainclock)

View File

@ -243,7 +243,8 @@ class netlist_param_t;
class netlist_setup_t; class netlist_setup_t;
class netlist_base_t; class netlist_base_t;
class netlist_matrix_solver_t; class netlist_matrix_solver_t;
class NETLIB_NAME(solver);
class NETLIB_NAME(mainclock);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// netlist_object_t // 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 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 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 const netlist_net_t & RESTRICT net() const { return *m_net;}
ATTR_HOT inline netlist_net_t & RESTRICT net() { 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; typedef netlist_list_t<netlist_net_t *> list_t;
friend class NETLIB_NAME(mainclock); friend class NETLIB_NAME(mainclock);
friend class NETLIB_NAME(solver);
friend class netlist_matrix_solver_t; 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_logic_output_t;
friend class netlist_analog_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 // FIXME: union does not work
typedef struct typedef struct
@ -511,9 +507,8 @@ public:
ATTR_HOT inline const netlist_time time() const { return m_time; } 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 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() 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 */ /* 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 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 Q() const
ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new.Q; } {
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 ATTR_HOT inline const double Q_Analog() const
{ {
@ -544,15 +554,6 @@ public:
protected: 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_last;
hybrid_t m_cur; hybrid_t m_cur;
@ -561,7 +562,7 @@ protected:
UINT32 m_num_cons; UINT32 m_num_cons;
private: 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; netlist_time m_time;
INT32 m_active; INT32 m_active;
@ -575,9 +576,6 @@ private:
// net_output_t // net_output_t
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
class NETLIB_NAME(mainclock);
class NETLIB_NAME(solver);
class netlist_output_t : public netlist_core_terminal_t class netlist_output_t : public netlist_core_terminal_t
{ {
public: public:
@ -860,29 +858,29 @@ public:
ATTR_COLD netlist_setup_t *setup() const { return m_setup; } 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_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_terminal(const pstring &name, netlist_terminal_t &port);
ATTR_COLD void register_output(const pstring &name, netlist_output_t &out); 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_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, 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);
ATTR_HOT virtual void update_terminals() { }
/* driving logic outputs don't count in here */ /* driving logic outputs don't count in here */
netlist_list_t<pstring, 20> m_terminals; netlist_list_t<pstring, 20> m_terminals;
protected: protected:
virtual void update() { } ATTR_HOT virtual void update() { }
virtual void start() { } ATTR_HOT virtual void start() { }
ATTR_HOT virtual void update_terminals() { }
template <class C, class T> template <class C, class T>
ATTR_COLD void register_param(const pstring &sname, C &param, const T initialVal) 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_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 queue_t &queue() { return m_queue; }
ATTR_HOT inline void push_to_queue(netlist_net_t &out, const netlist_time &attime) 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)); 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); ATTR_HOT void process_queue(INT32 &atime);
@ -961,7 +960,7 @@ private:
class nld_a_to_d_proxy : public netlist_device_t class nld_a_to_d_proxy : public netlist_device_t
{ {
public: 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() : netlist_device_t()
{ {
//assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL); //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; 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_analog_input_t m_I;
netlist_ttl_output_t m_Q; netlist_ttl_output_t m_Q;
protected: protected:
void start() ATTR_COLD void start()
{ {
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE); 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 class nld_d_to_a_proxy : public netlist_device_t
{ {
public: 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() : netlist_device_t()
{ {
//assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL); //assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
@ -1012,13 +1011,13 @@ public:
m_high_V = out_proxied.m_high_V; 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_ttl_input_t m_I;
netlist_analog_output_t m_Q; netlist_analog_output_t m_Q;
protected: protected:
void start() ATTR_COLD void start()
{ {
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE); m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
m_Q.init_object(*this, "Q"); 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(); return net().Q_Analog();
} }
//FIXME: Legacy ... must be removed
ATTR_HOT inline const bool netlist_analog_input_t::is_highz() const ATTR_HOT inline const bool netlist_analog_input_t::is_highz() const
{ {
return (net().Q_Analog() == NETLIST_HIGHIMP_V); return (net().Q_Analog() == NETLIST_HIGHIMP_V);

View File

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

View File

@ -35,6 +35,28 @@ public:
m_ptr = m_list; m_ptr = m_list;
m_ptr--; 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() ATTR_COLD ~netlist_list_t()
{ {
delete[] m_list; 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 *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 *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 *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 int count() const { return m_ptr - m_list + 1; }
ATTR_HOT inline bool empty() const { return (m_ptr < m_list); } ATTR_HOT inline bool empty() const { return (m_ptr < m_list); }
ATTR_HOT inline void reset() { m_ptr = m_list - 1; } 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: private:
entry_t * m_ptr; entry_t * m_ptr;
entry_t * m_list; entry_t * m_list;

View File

@ -8,7 +8,9 @@
#include "nl_base.h" #include "nl_base.h"
#include "nl_setup.h" #include "nl_setup.h"
#include "nl_parser.h" #include "nl_parser.h"
#include "nl_util.h"
#include "devices/nld_system.h" #include "devices/nld_system.h"
#include "devices/nld_solver.h"
static NETLIST_START(base) static NETLIST_START(base)
NETDEV_TTL_CONST(ttlhigh, 1) 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()); 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()) switch (obj.type())
{ {
@ -248,7 +250,7 @@ const pstring netlist_setup_t::resolve_alias(const pstring &name) const
if (dev == NULL) if (dev == NULL)
fatalerror("Device for %s not found\n", name.cstr()); fatalerror("Device for %s not found\n", name.cstr());
int c = atoi(ret.substr(p+2,ret.len()-p-3)); 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 .... // reresolve ....
do { do {
ret = temp; ret = temp;
@ -517,6 +519,21 @@ void netlist_setup_t::resolve_inputs(void)
void netlist_setup_t::start_devices(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")); NL_VERBOSE_OUT(("Searching for mainclock and solver ...\n"));
/* find the main clock ... */ /* find the main clock ... */
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) 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_ */