mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
Split the netlist code up into functional pieces like parser, setup and execution. This looks a lot more structured now and highlighted some issue already.
This commit is contained in:
parent
39dc549a5f
commit
bf19099323
17
.gitattributes
vendored
17
.gitattributes
vendored
@ -2098,9 +2098,22 @@ src/emu/memarray.c svneol=native#text/plain
|
||||
src/emu/memarray.h svneol=native#text/plain
|
||||
src/emu/memory.c svneol=native#text/plain
|
||||
src/emu/memory.h svneol=native#text/plain
|
||||
src/emu/netlist/net_lib.c svneol=native#text/plain
|
||||
src/emu/netlist/net_lib.h svneol=native#text/plain
|
||||
src/emu/netlist/devices/net_lib.c svneol=native#text/plain
|
||||
src/emu/netlist/devices/net_lib.h svneol=native#text/plain
|
||||
src/emu/netlist/devices/nld_7400.c svneol=native#text/plain
|
||||
src/emu/netlist/devices/nld_7400.h svneol=native#text/plain
|
||||
src/emu/netlist/devices/nld_signal.h svneol=native#text/plain
|
||||
src/emu/netlist/devices/nld_system.h svneol=native#text/plain
|
||||
src/emu/netlist/netlist.mak svneol=native#text/plain
|
||||
src/emu/netlist/nl_base.c svneol=native#text/plain
|
||||
src/emu/netlist/nl_base.h svneol=native#text/plain
|
||||
src/emu/netlist/nl_config.h svneol=native#text/plain
|
||||
src/emu/netlist/nl_lists.h svneol=native#text/plain
|
||||
src/emu/netlist/nl_parser.c svneol=native#text/plain
|
||||
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/network.c svneol=native#text/plain
|
||||
src/emu/network.h svneol=native#text/plain
|
||||
src/emu/output.c svneol=native#text/plain
|
||||
|
@ -60,6 +60,7 @@ OBJDIRS += \
|
||||
$(EMUOBJ)/drivers \
|
||||
$(EMUOBJ)/machine \
|
||||
$(EMUOBJ)/netlist \
|
||||
$(EMUOBJ)/netlist/devices \
|
||||
$(EMUOBJ)/layout \
|
||||
$(EMUOBJ)/imagedev \
|
||||
$(EMUOBJ)/video \
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/***************************************************************************
|
||||
|
||||
netlib.c
|
||||
@ -46,6 +48,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "net_lib.h"
|
||||
#include "nld_system.h"
|
||||
|
||||
NETLIB_START(netdev_logic_input)
|
||||
{
|
||||
@ -219,12 +222,12 @@ NETLIB_START(nicNE555N_MSTABLE)
|
||||
m_last = false;
|
||||
}
|
||||
|
||||
INLINE double nicNE555N_cv(nicNE555N_MSTABLE &dev)
|
||||
INLINE double nicNE555N_cv(NETLIB_NAME(nicNE555N_MSTABLE) &dev)
|
||||
{
|
||||
return (dev.m_CV.is_highz() ? 0.67 * dev.m_VS.Value() : dev.INPANALOG(dev.m_CV));
|
||||
}
|
||||
|
||||
INLINE double nicNE555N_clamp(nicNE555N_MSTABLE &dev, const double v, const double a, const double b)
|
||||
INLINE double nicNE555N_clamp(NETLIB_NAME(nicNE555N_MSTABLE) &dev, const double v, const double a, const double b)
|
||||
{
|
||||
double ret = v;
|
||||
if (ret > dev.m_VS.Value() - a)
|
||||
@ -391,7 +394,7 @@ NETLIB_FUNC_VOID(nic7448_sub, update_outputs, (UINT8 v))
|
||||
}
|
||||
}
|
||||
|
||||
const UINT8 nic7448_sub::tab7448[16][7] =
|
||||
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 */
|
||||
@ -458,7 +461,7 @@ NETLIB_UPDATE(nic7450)
|
||||
#endif
|
||||
}
|
||||
|
||||
ATTR_HOT inline void nic7474sub::newstate(const UINT8 state)
|
||||
ATTR_HOT inline void NETLIB_NAME(nic7474sub)::newstate(const UINT8 state)
|
||||
{
|
||||
static const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
|
||||
//printf("%s %d %d %d\n", "7474", state, Q.Q(), QQ.Q());
|
||||
@ -636,7 +639,7 @@ NETLIB_UPDATE(nic7493ff)
|
||||
|
||||
NETLIB_UPDATE(nic7493)
|
||||
{
|
||||
net_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
|
||||
netlist_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
|
||||
|
||||
if (r)
|
||||
{
|
||||
@ -754,7 +757,7 @@ NETLIB_START(nic74107A)
|
||||
sub.m_QQ.initial(1);
|
||||
}
|
||||
|
||||
ATTR_HOT inline void nic74107Asub::newstate(const net_sig_t state)
|
||||
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) };
|
||||
#if 1
|
||||
@ -772,7 +775,7 @@ ATTR_HOT inline void nic74107Asub::newstate(const net_sig_t state)
|
||||
NETLIB_UPDATE(nic74107Asub)
|
||||
{
|
||||
{
|
||||
net_sig_t t = m_Q.new_Q();
|
||||
netlist_sig_t t = m_Q.new_Q();
|
||||
newstate((!t & m_Q1) | (t & m_Q2) | m_F);
|
||||
if (!m_Q1)
|
||||
m_clk.inactivate();
|
||||
@ -892,7 +895,7 @@ NETLIB_UPDATE(nic9316)
|
||||
{
|
||||
sub.m_loadq = INPLOGIC(m_LOADQ);
|
||||
sub.m_ent = INPLOGIC(m_ENT);
|
||||
const net_sig_t clrq = INPLOGIC(m_CLRQ);
|
||||
const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
|
||||
|
||||
if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
|
||||
{
|
||||
@ -964,7 +967,9 @@ NETLIB_FUNC_VOID(nic9316_sub, update_outputs, (void))
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ENTRY(_nic, _name) new net_device_t_factory< _nic >( # _name, # _nic ),
|
||||
#define xstr(s) # s
|
||||
#define ENTRY1(_nic, _name) new net_device_t_factory< _nic >( # _name, xstr(_nic) ),
|
||||
#define ENTRY(_nic, _name) ENTRY1(NETLIB_NAME(_nic), _name)
|
||||
|
||||
static const net_device_t_base_factory *netregistry[] =
|
||||
{
|
||||
@ -979,7 +984,7 @@ static const net_device_t_base_factory *netregistry[] =
|
||||
ENTRY(nicMultiSwitch, NETDEV_SWITCH2)
|
||||
ENTRY(nicRSFF, NETDEV_RSFF)
|
||||
ENTRY(nicMixer8, NETDEV_MIXER)
|
||||
ENTRY(nic7400, TTL_7400_NAND)
|
||||
ENTRY(7400, TTL_7400_NAND)
|
||||
ENTRY(nic7402, TTL_7402_NOR)
|
||||
ENTRY(nic7404, TTL_7404_INVERT)
|
||||
ENTRY(nic7410, TTL_7410_NAND)
|
||||
@ -1005,7 +1010,7 @@ static const net_device_t_base_factory *netregistry[] =
|
||||
net_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup, const astring &icname)
|
||||
{
|
||||
const net_device_t_base_factory **p = &netregistry[0];
|
||||
while (p != NULL)
|
||||
while (*p != NULL)
|
||||
{
|
||||
if (strcmp((*p)->classname(), classname) == 0)
|
||||
{
|
||||
@ -1022,7 +1027,7 @@ net_device_t *net_create_device_by_classname(const astring &classname, netlist_s
|
||||
net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup, const astring &icname)
|
||||
{
|
||||
const net_device_t_base_factory **p = &netregistry[0];
|
||||
while (p != NULL)
|
||||
while (*p != NULL)
|
||||
{
|
||||
if (strcmp((*p)->name(), name) == 0)
|
||||
{
|
||||
@ -1035,3 +1040,4 @@ net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &se
|
||||
fatalerror("Class %s required for IC %s not found!\n", name.cstr(), icname.cstr());
|
||||
return NULL; // appease code analysis
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/***************************************************************************
|
||||
|
||||
net_lib.h
|
||||
@ -48,7 +50,11 @@
|
||||
#ifndef NET_LIB_H
|
||||
#define NET_LIB_H
|
||||
|
||||
#include "machine/netlist.h"
|
||||
#include "../nl_base.h"
|
||||
#include "nld_signal.h"
|
||||
#include "nld_system.h"
|
||||
|
||||
#include "nld_7400.h"
|
||||
|
||||
// this is a bad hack
|
||||
#define USE_OLD7493 (0)
|
||||
@ -66,7 +72,7 @@
|
||||
#define NETDEV_ANALOG_INPUT(_name) \
|
||||
NET_REGISTER_DEV(netdev_analog_input, _name)
|
||||
#define NETDEV_CALLBACK(_name, _IN) \
|
||||
NET_REGISTER_DEV(netdev_analog_callback, _name) \
|
||||
NET_REGISTER_DEV(netdev_analog_callback, _name) \
|
||||
NET_CONNECT(_name, IN, _IN)
|
||||
#define NETDEV_SWITCH2(_name, _i1, _i2) \
|
||||
NET_REGISTER_DEV(nicMultiSwitch, _name) \
|
||||
@ -90,15 +96,10 @@
|
||||
// TTL Logic chips
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define TTL_7400_NAND(_name, _I1, _I2) \
|
||||
NET_REGISTER_DEV(nic7400, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2)
|
||||
|
||||
#define TTL_7402_NOR(_name, _I1, _I2) \
|
||||
NET_REGISTER_DEV(nic7402, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2)
|
||||
|
||||
#define TTL_7404_INVERT(_name, _I1) \
|
||||
NET_REGISTER_DEV(nic7404, _name) \
|
||||
@ -106,40 +107,40 @@
|
||||
|
||||
#define TTL_7410_NAND(_name, _I1, _I2, _I3) \
|
||||
NET_REGISTER_DEV(nic7410, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2) \
|
||||
NET_CONNECT(_name, C, _I3)
|
||||
|
||||
#define TTL_7420_NAND(_name, _I1, _I2, _I3, _I4) \
|
||||
NET_REGISTER_DEV(nic7420, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3) \
|
||||
NET_CONNECT(_name, I4, _I4)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2) \
|
||||
NET_CONNECT(_name, C, _I3) \
|
||||
NET_CONNECT(_name, D, _I4)
|
||||
|
||||
#define TTL_7425_NOR(_name, _I1, _I2, _I3, _I4) \
|
||||
NET_REGISTER_DEV(nic7425, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3) \
|
||||
NET_CONNECT(_name, I4, _I4)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2) \
|
||||
NET_CONNECT(_name, C, _I3) \
|
||||
NET_CONNECT(_name, D, _I4)
|
||||
|
||||
#define TTL_7427_NOR(_name, _I1, _I2, _I3) \
|
||||
NET_REGISTER_DEV(nic7427, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2) \
|
||||
NET_CONNECT(_name, C, _I3)
|
||||
|
||||
#define TTL_7430_NAND(_name, _I1, _I2, _I3, _I4, _I5, _I6, _I7, _I8) \
|
||||
NET_REGISTER_DEV(nic7430, _name) \
|
||||
NET_CONNECT(_name, I1, _I1) \
|
||||
NET_CONNECT(_name, I2, _I2) \
|
||||
NET_CONNECT(_name, I3, _I3) \
|
||||
NET_CONNECT(_name, I4, _I4) \
|
||||
NET_CONNECT(_name, I5, _I5) \
|
||||
NET_CONNECT(_name, I6, _I6) \
|
||||
NET_CONNECT(_name, I7, _I7) \
|
||||
NET_CONNECT(_name, I8, _I8)
|
||||
NET_CONNECT(_name, A, _I1) \
|
||||
NET_CONNECT(_name, B, _I2) \
|
||||
NET_CONNECT(_name, C, _I3) \
|
||||
NET_CONNECT(_name, D, _I4) \
|
||||
NET_CONNECT(_name, E, _I5) \
|
||||
NET_CONNECT(_name, F, _I6) \
|
||||
NET_CONNECT(_name, G, _I7) \
|
||||
NET_CONNECT(_name, H, _I8)
|
||||
|
||||
#define TTL_7450_ANDORINVERT(_name, _I1, _I2, _I3, _I4) \
|
||||
NET_REGISTER_DEV(nic7450, _name) \
|
||||
@ -324,13 +325,12 @@ NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE,
|
||||
net_param_t m_VL;
|
||||
);
|
||||
|
||||
NETLIB_SIGNAL(nic7400, 2, 0, 0)
|
||||
NETLIB_SIGNAL(nic7402, 2, 1, 0)
|
||||
NETLIB_SIGNAL(nic7410, 3, 0, 0)
|
||||
NETLIB_SIGNAL(nic7420, 4, 0, 0)
|
||||
NETLIB_SIGNAL(nic7425, 4, 1, 0)
|
||||
NETLIB_SIGNAL(nic7427, 3, 1, 0)
|
||||
NETLIB_SIGNAL(nic7430, 8, 0, 0)
|
||||
NETLIB_SIGNAL(nic7402, 2, 1, 0);
|
||||
NETLIB_SIGNAL(nic7410, 3, 0, 0);
|
||||
NETLIB_SIGNAL(nic7420, 4, 0, 0);
|
||||
NETLIB_SIGNAL(nic7425, 4, 1, 0);
|
||||
NETLIB_SIGNAL(nic7427, 3, 1, 0);
|
||||
NETLIB_SIGNAL(nic7430, 8, 0, 0);
|
||||
|
||||
NETLIB_DEVICE(nic7404,
|
||||
ttl_input_t m_I;
|
||||
@ -356,7 +356,7 @@ NETLIB_SUBDEVICE(nic7474sub,
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic7474,
|
||||
nic7474sub sub;
|
||||
NETLIB_NAME(nic7474sub) sub;
|
||||
|
||||
ttl_input_t m_D;
|
||||
ttl_input_t m_clrQ;
|
||||
@ -380,17 +380,16 @@ NETLIB_SUBDEVICE(nic74107Asub,
|
||||
ttl_output_t m_Q;
|
||||
ttl_output_t m_QQ;
|
||||
|
||||
netlist_sig_t m_Q1;
|
||||
netlist_sig_t m_Q2;
|
||||
netlist_sig_t m_F;
|
||||
|
||||
net_sig_t m_Q1;
|
||||
net_sig_t m_Q2;
|
||||
net_sig_t m_F;
|
||||
|
||||
ATTR_HOT void newstate(const net_sig_t state);
|
||||
ATTR_HOT void newstate(const netlist_sig_t state);
|
||||
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic74107A,
|
||||
nic74107Asub sub;
|
||||
NETLIB_NAME(nic74107Asub) sub;
|
||||
|
||||
ttl_input_t m_J;
|
||||
ttl_input_t m_K;
|
||||
@ -398,11 +397,11 @@ NETLIB_DEVICE(nic74107A,
|
||||
|
||||
);
|
||||
|
||||
class nic74107 : public nic74107A
|
||||
class NETLIB_NAME(nic74107) : public NETLIB_NAME(nic74107A)
|
||||
{
|
||||
public:
|
||||
nic74107()
|
||||
: nic74107A() {}
|
||||
NETLIB_NAME(nic74107) ()
|
||||
: NETLIB_NAME(nic74107A) () {}
|
||||
|
||||
};
|
||||
|
||||
@ -419,11 +418,12 @@ NETLIB_DEVICE(nic7493,
|
||||
ttl_input_t m_R1;
|
||||
ttl_input_t m_R2;
|
||||
|
||||
nic7493ff A;
|
||||
nic7493ff B;
|
||||
nic7493ff C;
|
||||
nic7493ff D;
|
||||
NETLIB_NAME(nic7493ff) A;
|
||||
NETLIB_NAME(nic7493ff) B;
|
||||
NETLIB_NAME(nic7493ff) C;
|
||||
NETLIB_NAME(nic7493ff) D;
|
||||
);
|
||||
|
||||
#else
|
||||
NETLIB_DEVICE(nic7493,
|
||||
ttl_input_t m_CLK;
|
||||
@ -469,8 +469,8 @@ NETLIB_SUBDEVICE(nic9316_sub,
|
||||
ttl_input_t m_D;
|
||||
|
||||
UINT8 m_cnt;
|
||||
net_sig_t m_loadq;
|
||||
net_sig_t m_ent;
|
||||
netlist_sig_t m_loadq;
|
||||
netlist_sig_t m_ent;
|
||||
|
||||
ttl_output_t m_QA;
|
||||
ttl_output_t m_QB;
|
||||
@ -480,7 +480,7 @@ NETLIB_SUBDEVICE(nic9316_sub,
|
||||
);
|
||||
|
||||
NETLIB_DEVICE(nic9316,
|
||||
nic9316_sub sub;
|
||||
NETLIB_NAME(nic9316_sub) sub;
|
||||
ttl_input_t m_ENP;
|
||||
ttl_input_t m_ENT;
|
||||
ttl_input_t m_CLRQ;
|
||||
@ -543,7 +543,7 @@ NETLIB_SUBDEVICE(nic7448_sub,
|
||||
|
||||
NETLIB_DEVICE(nic7448,
|
||||
|
||||
nic7448_sub sub;
|
||||
NETLIB_NAME(nic7448_sub) sub;
|
||||
|
||||
ttl_input_t m_LTQ;
|
||||
ttl_input_t m_BIQ;
|
6
src/emu/netlist/devices/nld_7400.c
Normal file
6
src/emu/netlist/devices/nld_7400.c
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
* nld_7400.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
44
src/emu/netlist/devices/nld_7400.h
Normal file
44
src/emu/netlist/devices/nld_7400.h
Normal file
@ -0,0 +1,44 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nld_7400.h
|
||||
*
|
||||
* DM7400: Quad 2-Input NAND Gates
|
||||
*
|
||||
* +--------------+
|
||||
* A1 |1 ++ 14| VCC
|
||||
* B1 |2 13| B4
|
||||
* Y1 |3 12| A4
|
||||
* A2 |4 7400 11| Y4
|
||||
* B2 |5 10| B3
|
||||
* Y2 |6 9| A3
|
||||
* GND |7 8| Y3
|
||||
* +--------------+
|
||||
* __
|
||||
* Y = AB
|
||||
* +---+---++---+
|
||||
* | A | B || Y |
|
||||
* +===+===++===+
|
||||
* | 0 | 0 || 1 |
|
||||
* | 0 | 1 || 1 |
|
||||
* | 1 | 0 || 1 |
|
||||
* | 1 | 1 || 0 |
|
||||
* +---+---++---+
|
||||
*
|
||||
* Naming conventions follow National Semiconductor datasheet
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nld_signal.h"
|
||||
|
||||
#ifndef NLD_7400_H_
|
||||
#define NLD_7400_H_
|
||||
|
||||
#define TTL_7400_NAND(_name, _A, _B) \
|
||||
NET_REGISTER_DEV(7400, _name) \
|
||||
NET_CONNECT(_name, A, _A) \
|
||||
NET_CONNECT(_name, B, _B)
|
||||
|
||||
NETLIB_SIGNAL(7400, 2, 0, 0);
|
||||
|
||||
#endif /* NLD_7400_H_ */
|
296
src/emu/netlist/devices/nld_signal.h
Normal file
296
src/emu/netlist/devices/nld_signal.h
Normal file
@ -0,0 +1,296 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nld_signal.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NLD_SIGNAL_H_
|
||||
#define NLD_SIGNAL_H_
|
||||
|
||||
#include "../nl_base.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// MACROS
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define NETLIB_SIGNAL(_name, _num_input, _check, _invert) \
|
||||
class NETLIB_NAME(_name) : public net_signal_t<_num_input, _check, _invert> \
|
||||
{ \
|
||||
public: \
|
||||
ATTR_COLD NETLIB_NAME(_name) () \
|
||||
: net_signal_t<_num_input, _check, _invert>() { } \
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_signal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <int _numdev>
|
||||
class net_signal_base_t : public net_device_t
|
||||
{
|
||||
public:
|
||||
net_signal_base_t()
|
||||
: net_device_t(), m_active(1) { }
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" };
|
||||
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < _numdev; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
|
||||
}
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT void inc_active()
|
||||
{
|
||||
if (m_active == 0)
|
||||
{
|
||||
update();
|
||||
}
|
||||
m_active++;
|
||||
}
|
||||
|
||||
ATTR_HOT void dec_active()
|
||||
{
|
||||
m_active--;
|
||||
if (m_active == 0)
|
||||
{
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
m_i[i].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
ttl_input_t m_i[_numdev];
|
||||
ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
};
|
||||
|
||||
|
||||
template <int _numdev, int _check, int _invert>
|
||||
class net_signal_t : public net_device_t
|
||||
{
|
||||
public:
|
||||
net_signal_t()
|
||||
: net_device_t(), m_active(1)
|
||||
{
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
const char *sIN[8] = { "A", "B", "C", "D", "E", "F", "G", "H" };
|
||||
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < _numdev; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT void inc_active()
|
||||
{
|
||||
if (m_active == 0)
|
||||
{
|
||||
update();
|
||||
}
|
||||
m_active++;
|
||||
}
|
||||
|
||||
ATTR_HOT void dec_active()
|
||||
{
|
||||
m_active--;
|
||||
if (m_active == 0)
|
||||
{
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
m_i[i].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
static const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
|
||||
int pos = -1;
|
||||
|
||||
for (int i = 0; i< _numdev; i++)
|
||||
{
|
||||
this->m_i[i].activate();
|
||||
if (INPLOGIC(this->m_i[i]) == _check)
|
||||
{
|
||||
OUTLOGIC(this->m_Q, _check ^ (1 ^ _invert), times[_check]);// ? 15000 : 22000);
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos >= 0)
|
||||
{
|
||||
for (int i = 0; i < _numdev; i++)
|
||||
if (i != pos)
|
||||
this->m_i[i].inactivate();
|
||||
} else
|
||||
OUTLOGIC(this->m_Q,_check ^ (_invert), times[1-_check]);// ? 22000 : 15000);
|
||||
}
|
||||
|
||||
public:
|
||||
ttl_input_t m_i[_numdev];
|
||||
ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
};
|
||||
|
||||
#if 1
|
||||
template <int _check, int _invert>
|
||||
class xx_net_signal_t: public net_device_t
|
||||
{
|
||||
public:
|
||||
xx_net_signal_t()
|
||||
: net_device_t(), m_active(1)
|
||||
{
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
const char *sIN[2] = { "A", "B" };
|
||||
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < 2; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
ATTR_HOT void inc_active()
|
||||
{
|
||||
if (m_active == 0)
|
||||
{
|
||||
update();
|
||||
}
|
||||
m_active++;
|
||||
}
|
||||
|
||||
ATTR_HOT void dec_active()
|
||||
{
|
||||
m_active--;
|
||||
if (m_active == 0)
|
||||
{
|
||||
m_i[0].inactivate();
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void update()
|
||||
{
|
||||
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
|
||||
|
||||
int res = _invert ^ 1 ^_check;
|
||||
m_i[0].activate();
|
||||
m_i[1].activate();
|
||||
if (INPLOGIC(m_i[0]) ^ _check)
|
||||
{
|
||||
if (INPLOGIC(m_i[1]) ^ _check)
|
||||
{
|
||||
res = _invert ^ _check;
|
||||
}
|
||||
else
|
||||
m_i[0].inactivate();
|
||||
} else {
|
||||
if (INPLOGIC(m_i[1]) ^ _check)
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
OUTLOGIC(m_Q, res, times[(res & 1) ^ 1]);// ? 22000 : 15000);
|
||||
}
|
||||
|
||||
public:
|
||||
ttl_input_t m_i[2];
|
||||
ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
// The following did not improve performance
|
||||
#if 0
|
||||
|
||||
template <UINT8 _check, UINT8 _invert>
|
||||
class net_signal_t<3, _check, _invert> : public net_device_t
|
||||
{
|
||||
public:
|
||||
net_signal_t() : net_device_t(), m_active(1) { }
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
const char *sIN[3] = { "I1", "I2", "I3" };
|
||||
|
||||
register_output("Q", m_Q);
|
||||
for (int i=0; i < 3; i++)
|
||||
{
|
||||
register_input(sIN[i], m_i[i], net_input_t::INP_STATE_ACTIVE);
|
||||
}
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void update()
|
||||
{
|
||||
const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
|
||||
//const UINT8 res_tab[4] = {1, 1, 1, 0 };
|
||||
//const UINT8 ai1[4] = {0, 1, 0, 0 };
|
||||
//const UINT8 ai2[4] = {1, 0, 1, 0 };
|
||||
|
||||
UINT8 res = _invert ^ 1 ^_check;
|
||||
m_i[0].activate();
|
||||
if (INPLOGIC(m_i[0]) ^ _check)
|
||||
{
|
||||
m_i[1].activate();
|
||||
if (INPLOGIC(m_i[1]) ^ _check)
|
||||
{
|
||||
m_i[2].activate();
|
||||
if (INPLOGIC(m_i[2]) ^ _check)
|
||||
{
|
||||
res = _invert ^ _check;
|
||||
}
|
||||
else
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (INPLOGIC(m_i[2]) ^ _check)
|
||||
m_i[2].inactivate();
|
||||
m_i[0].inactivate();
|
||||
}
|
||||
} else {
|
||||
if (INPLOGIC(m_i[1]) ^ _check)
|
||||
m_i[1].inactivate();
|
||||
}
|
||||
OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
|
||||
}
|
||||
public:
|
||||
ttl_input_t m_i[3];
|
||||
ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template <int _check, int _invert>
|
||||
class net_signal_t<2, _check, _invert> : public xx_net_signal_t<_check, _invert>
|
||||
{
|
||||
public:
|
||||
net_signal_t()
|
||||
: xx_net_signal_t<_check, _invert>() { }
|
||||
};
|
||||
|
||||
|
||||
#endif /* NLD_SIGNAL_H_ */
|
82
src/emu/netlist/devices/nld_system.h
Normal file
82
src/emu/netlist/devices/nld_system.h
Normal file
@ -0,0 +1,82 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nld_system.h
|
||||
*
|
||||
* netlist devices defined in the core
|
||||
*/
|
||||
|
||||
#ifndef NLD_SYSTEM_H_
|
||||
#define NLD_SYSTEM_H_
|
||||
|
||||
#include "../nl_setup.h"
|
||||
#include "../nl_base.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Macros
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define NETDEV_TTL_CONST(_name, _v) \
|
||||
NET_REGISTER_DEV(netdev_ttl_const, _name) \
|
||||
NETDEV_PARAM(_name.CONST, _v)
|
||||
|
||||
#define NETDEV_ANALOG_CONST(_name, _v) \
|
||||
NET_REGISTER_DEV(netdev_analog_const, _name) \
|
||||
NETDEV_PARAM(_name.CONST, _v)
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_*_const
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(netdev_ttl_const,
|
||||
ttl_output_t m_Q;
|
||||
net_param_t m_const;
|
||||
);
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(netdev_analog_const,
|
||||
analog_output_t m_Q;
|
||||
net_param_t m_const;
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_mainclock
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(netdev_mainclock,
|
||||
ttl_output_t m_Q;
|
||||
|
||||
net_param_t m_freq;
|
||||
netlist_time m_inc;
|
||||
|
||||
ATTR_HOT inline static void mc_update(net_output_t &Q, const netlist_time curtime);
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_callback
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class NETLIB_NAME(netdev_analog_callback) : public net_device_t
|
||||
{
|
||||
public:
|
||||
NETLIB_NAME(netdev_analog_callback)()
|
||||
: net_device_t() { }
|
||||
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
register_input("IN", m_in);
|
||||
}
|
||||
|
||||
ATTR_COLD void register_callback(netlist_output_delegate callback)
|
||||
{
|
||||
m_callback = callback;
|
||||
}
|
||||
|
||||
ATTR_HOT void update();
|
||||
|
||||
|
||||
private:
|
||||
analog_input_t m_in;
|
||||
netlist_output_delegate m_callback;
|
||||
};
|
||||
|
||||
#endif /* NLD_SYSTEM_H_ */
|
@ -17,5 +17,9 @@ NETLISTOBJ = $(EMUOBJ)/netlist
|
||||
# Core files
|
||||
#-------------------------------------------------
|
||||
|
||||
NETLISTOBJS+= $(NETLISTOBJ)/net_lib.o
|
||||
|
||||
NETLISTOBJS+= \
|
||||
$(NETLISTOBJ)/nl_setup.o \
|
||||
$(NETLISTOBJ)/nl_base.o \
|
||||
$(NETLISTOBJ)/nl_parser.o \
|
||||
$(NETLISTOBJ)/devices/net_lib.o \
|
||||
|
||||
|
435
src/emu/netlist/nl_base.c
Normal file
435
src/emu/netlist/nl_base.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* nlbase.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nl_base.h"
|
||||
#include "devices/nld_system.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_base_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_base_t::netlist_base_t()
|
||||
: m_mainclock(NULL),
|
||||
m_time_ps(netlist_time::zero),
|
||||
m_rem(0),
|
||||
m_div(NETLIST_DIV)
|
||||
{
|
||||
}
|
||||
|
||||
netlist_base_t::~netlist_base_t()
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_base_t::set_mainclock_dev(NETLIB_NAME(netdev_mainclock) *dev)
|
||||
{
|
||||
m_mainclock = dev;
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_base_t::reset()
|
||||
{
|
||||
m_time_ps = netlist_time::zero;
|
||||
m_rem = 0;
|
||||
m_queue.clear();
|
||||
if (m_mainclock != NULL)
|
||||
m_mainclock->m_Q.set_time(netlist_time::zero);
|
||||
}
|
||||
|
||||
|
||||
void netlist_base_t::set_clock_freq(UINT64 clockfreq)
|
||||
{
|
||||
m_div = netlist_time::from_hz(clockfreq).as_raw();
|
||||
m_rem = 0;
|
||||
assert_always(m_div == NETLIST_DIV, "netlist: illegal clock!");
|
||||
NL_VERBOSE_OUT(("Setting clock %" I64FMT "d and divisor %d\n", clockfreq, m_div));
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN inline void netlist_base_t::update_time(const netlist_time t, INT32 &atime)
|
||||
{
|
||||
if (NETLIST_DIV_BITS == 0)
|
||||
{
|
||||
const netlist_time delta = t - m_time_ps;
|
||||
m_time_ps = t;
|
||||
atime -= delta.as_raw();
|
||||
} else {
|
||||
const netlist_time delta = t - m_time_ps + netlist_time::from_raw(m_rem);
|
||||
m_time_ps = t;
|
||||
m_rem = delta.as_raw() & NETLIST_MASK;
|
||||
atime -= (delta.as_raw() >> NETLIST_DIV_BITS);
|
||||
|
||||
// The folling is suitable for non-power of 2 m_divs ...
|
||||
// atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime)
|
||||
{
|
||||
if (m_mainclock == NULL)
|
||||
{
|
||||
while ( (atime > 0) && (m_queue.is_not_empty()))
|
||||
{
|
||||
const queue_t::entry_t e = m_queue.pop();
|
||||
update_time(e.time(), atime);
|
||||
|
||||
if (FATAL_ERROR_AFTER_NS)
|
||||
printf("%s\n", e.object().netdev()->name().cstr());
|
||||
|
||||
e.object().update_devs();
|
||||
|
||||
add_to_stat(m_perf_out_processed, 1);
|
||||
|
||||
if (FATAL_ERROR_AFTER_NS)
|
||||
if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
|
||||
fatalerror("Stopped");
|
||||
}
|
||||
|
||||
if (atime > 0)
|
||||
{
|
||||
m_time_ps += netlist_time::from_raw(atime * m_div);
|
||||
atime = 0;
|
||||
}
|
||||
} else {
|
||||
net_output_t &mcQ = m_mainclock->m_Q;
|
||||
const netlist_time inc = m_mainclock->m_inc;
|
||||
|
||||
while (atime > 0)
|
||||
{
|
||||
if (m_queue.is_not_empty())
|
||||
{
|
||||
while (m_queue.peek().time() > mcQ.time())
|
||||
{
|
||||
update_time(mcQ.time(), atime);
|
||||
|
||||
NETLIB_NAME(netdev_mainclock)::mc_update(mcQ, time() + inc);
|
||||
|
||||
}
|
||||
const queue_t::entry_t e = m_queue.pop();
|
||||
|
||||
update_time(e.time(), atime);
|
||||
|
||||
e.object().update_devs();
|
||||
|
||||
} else {
|
||||
update_time(mcQ.time(), atime);
|
||||
|
||||
NETLIB_NAME(netdev_mainclock)::mc_update(mcQ, time() + inc);
|
||||
}
|
||||
if (FATAL_ERROR_AFTER_NS)
|
||||
if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS))
|
||||
fatalerror("Stopped");
|
||||
|
||||
add_to_stat(m_perf_out_processed, 1);
|
||||
}
|
||||
|
||||
if (atime > 0)
|
||||
{
|
||||
m_time_ps += netlist_time::from_raw(atime * m_div);
|
||||
atime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Default netlist elements ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_core_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_core_device_t::netlist_core_device_t()
|
||||
: net_object_t(DEVICE)
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const astring &name)
|
||||
{
|
||||
m_netlist = &setup.netlist();
|
||||
m_name = name;
|
||||
|
||||
#if USE_DELEGATES
|
||||
#if USE_PMFDELEGATES
|
||||
void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update;
|
||||
static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
|
||||
#else
|
||||
static_update = net_update_delegate(&netlist_core_device_t::update, "update", this);
|
||||
// get the pointer to the member function
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ATTR_COLD void net_device_t::init(netlist_setup_t &setup, const astring &name)
|
||||
{
|
||||
netlist_core_device_t::init(setup, name);
|
||||
m_setup = &setup;
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
netlist_core_device_t::~netlist_core_device_t()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_HOT ATTR_ALIGN const netlist_sig_t netlist_core_device_t::INPLOGIC_PASSIVE(logic_input_t &inp)
|
||||
{
|
||||
if (inp.state() == net_input_t::INP_STATE_PASSIVE)
|
||||
{
|
||||
inp.activate();
|
||||
const netlist_sig_t ret = inp.Q();
|
||||
inp.inactivate();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return inp.Q();
|
||||
|
||||
}
|
||||
|
||||
net_device_t::net_device_t()
|
||||
: netlist_core_device_t(),
|
||||
m_inputs(20),
|
||||
m_setup(NULL),
|
||||
m_variable_input_count(false)
|
||||
{
|
||||
}
|
||||
|
||||
net_device_t::~net_device_t()
|
||||
{
|
||||
//printf("~net_device_t\n");
|
||||
}
|
||||
|
||||
ATTR_COLD void net_device_t::register_sub(netlist_core_device_t &dev, const astring &name)
|
||||
{
|
||||
dev.init(*m_setup, name);
|
||||
}
|
||||
|
||||
void net_device_t::register_output(netlist_core_device_t &dev, const astring &name, net_output_t &port)
|
||||
{
|
||||
m_setup->register_output(*this, dev, name, port);
|
||||
}
|
||||
|
||||
void net_device_t::register_output(const astring &name, net_output_t &port)
|
||||
{
|
||||
m_setup->register_output(*this,*this,name, port);
|
||||
}
|
||||
|
||||
void net_device_t::register_input(netlist_core_device_t &dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
|
||||
{
|
||||
m_setup->register_input(*this, dev, name, inp, type);
|
||||
}
|
||||
|
||||
void net_device_t::register_input(const astring &name, net_input_t &inp, net_input_t::net_input_state type)
|
||||
{
|
||||
register_input(*this, name, inp, type);
|
||||
}
|
||||
|
||||
void net_device_t::register_link_internal(netlist_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
|
||||
{
|
||||
in.set_output(out);
|
||||
in.init_input(&dev, aState);
|
||||
//if (in.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
out.register_con(in);
|
||||
}
|
||||
|
||||
void net_device_t::register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState)
|
||||
{
|
||||
register_link_internal(*this, in, out, aState);
|
||||
}
|
||||
|
||||
void net_device_t::register_param(netlist_core_device_t &dev, const astring &name, net_param_t ¶m, double initialVal)
|
||||
{
|
||||
param.set_netdev(dev);
|
||||
param.initial(initialVal);
|
||||
m_setup->register_param(name, ¶m);
|
||||
}
|
||||
|
||||
void net_device_t::register_param(const astring &name, net_param_t ¶m, double initialVal)
|
||||
{
|
||||
register_param(*this,name, param, initialVal);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_terminal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD void net_terminal_t::init_terminal(netlist_core_device_t *dev)
|
||||
{
|
||||
m_netdev = dev;
|
||||
m_netlist = dev->netlist();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_input_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD void net_input_t::init_input(netlist_core_device_t *dev, net_input_state astate)
|
||||
{
|
||||
init_terminal(dev);
|
||||
m_state = astate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_output_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
net_output_t::net_output_t(int atype)
|
||||
: net_terminal_t(atype)
|
||||
, m_low_V(0.0)
|
||||
, m_high_V(0.0)
|
||||
, m_last_Q(0)
|
||||
, m_Q(0)
|
||||
, m_new_Q(0)
|
||||
, m_Q_analog(0.0)
|
||||
, m_new_Q_analog(0.0)
|
||||
, m_num_cons(0)
|
||||
, m_time(netlist_time::zero)
|
||||
, m_active(0)
|
||||
, m_in_queue(2)
|
||||
{
|
||||
//m_cons = global_alloc_array(net_input_t *, OUTPUT_MAX_CONNECTIONS);
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_output_t::update_dev(const net_input_t *inp, const UINT32 mask)
|
||||
{
|
||||
if ((inp->state() & mask) != 0)
|
||||
{
|
||||
ATTR_UNUSED netlist_core_device_t *netdev = inp->netdev();
|
||||
begin_timing(netdev->total_time);
|
||||
inc_stat(netdev->stat_count);
|
||||
netdev->update_dev();
|
||||
end_timing(netdev()->total_time);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_output_t::update_devs()
|
||||
{
|
||||
|
||||
assert(m_num_cons != 0);
|
||||
|
||||
const UINT32 masks[4] = { 1, 5, 3, 1 };
|
||||
m_Q = m_new_Q;
|
||||
m_Q_analog = m_new_Q_analog;
|
||||
m_in_queue = 2; /* mark as taken ... */
|
||||
|
||||
const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
|
||||
|
||||
switch (m_num_cons)
|
||||
{
|
||||
case 2:
|
||||
update_dev(m_cons[1], mask);
|
||||
case 1:
|
||||
update_dev(m_cons[0], mask);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
for (int i=0; i < m_num_cons; i++)
|
||||
update_dev(m_cons[i], mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_last_Q = m_Q;
|
||||
}
|
||||
|
||||
ATTR_COLD void net_output_t::register_con(net_input_t &input)
|
||||
{
|
||||
int i;
|
||||
if (m_num_cons >= OUTPUT_MAX_CONNECTIONS)
|
||||
fatalerror("Connections exceeded for %s\n", netdev()->name().cstr());
|
||||
|
||||
/* keep similar devices together */
|
||||
for (i = 0; i < m_num_cons; i++)
|
||||
if (m_cons[i]->netdev() == input.netdev())
|
||||
break;
|
||||
|
||||
for (int j = m_num_cons; j > i; j--)
|
||||
m_cons[j] = m_cons[j - 1];
|
||||
|
||||
m_cons[i] = &input;
|
||||
m_num_cons++;
|
||||
if (input.state() != net_input_t::INP_STATE_PASSIVE)
|
||||
m_active++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_const
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_START(netdev_ttl_const)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
register_param("CONST", m_const, 0.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_ttl_const)
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(netdev_ttl_const)
|
||||
{
|
||||
OUTLOGIC(m_Q, m_const.ValueInt(), NLTIME_IMMEDIATE);
|
||||
}
|
||||
|
||||
NETLIB_START(netdev_analog_const)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
register_param("CONST", m_const, 0.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_analog_const)
|
||||
{
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(netdev_analog_const)
|
||||
{
|
||||
m_Q.initial(m_const.Value());
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(netdev_analog_callback)
|
||||
{
|
||||
// FIXME: Remove after device cleanup
|
||||
if (!m_callback.isnull())
|
||||
m_callback(INPANALOG(m_in));
|
||||
}
|
||||
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_mainclock
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_HOT inline void NETLIB_NAME(netdev_mainclock)::mc_update(net_output_t &Q, const netlist_time curtime)
|
||||
{
|
||||
Q.m_new_Q = !Q.m_new_Q;
|
||||
Q.set_time(curtime);
|
||||
Q.update_devs();
|
||||
}
|
||||
|
||||
ATTR_COLD NETLIB_START(netdev_mainclock)
|
||||
{
|
||||
register_output("Q", m_Q);
|
||||
|
||||
register_param("FREQ", m_freq, 7159000.0 * 5);
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
|
||||
}
|
||||
|
||||
ATTR_HOT NETLIB_UPDATE_PARAM(netdev_mainclock)
|
||||
{
|
||||
m_inc = netlist_time::from_hz(m_freq.Value()*2);
|
||||
}
|
||||
|
||||
ATTR_HOT NETLIB_UPDATE(netdev_mainclock)
|
||||
{
|
||||
// this is only called during setup ...
|
||||
m_Q.m_new_Q = !m_Q.m_new_Q;
|
||||
m_Q.set_time(m_netlist->time() + m_inc);
|
||||
}
|
811
src/emu/netlist/nl_base.h
Normal file
811
src/emu/netlist/nl_base.h
Normal file
@ -0,0 +1,811 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nlbase.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NLBASE_H_
|
||||
#define NLBASE_H_
|
||||
|
||||
#include "nl_config.h"
|
||||
#include "nl_lists.h"
|
||||
#include "nl_time.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_core_device_t;
|
||||
|
||||
#if USE_DELEGATES
|
||||
#if USE_PMFDELEGATES
|
||||
typedef void (*net_update_delegate)(netlist_core_device_t *);
|
||||
#else
|
||||
typedef delegate<void ()> net_update_delegate;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//============================================================
|
||||
// MACROS / netlist devices
|
||||
//============================================================
|
||||
|
||||
#define NETLIB_NAME(_chip) nld_ ## _chip
|
||||
|
||||
#define NETLIB_NAME_STR_S(_s) # _s
|
||||
#define NETLIB_NAME_STR(_chip) NETLIB_NAME_STR_S(nld_ ## _chip)
|
||||
|
||||
#define NETLIB_UPDATE(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update(void)
|
||||
#define NETLIB_START(_chip) ATTR_COLD void NETLIB_NAME(_chip) :: start(void)
|
||||
//#define NETLIB_CONSTRUCTOR(_chip) ATTR_COLD _chip :: _chip (netlist_setup_t &setup, const char *name)
|
||||
// : net_device_t(setup, name)
|
||||
|
||||
#define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void)
|
||||
#define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN inline void NETLIB_NAME(_chip) :: _name _params
|
||||
|
||||
#define NETLIB_DEVICE(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public net_device_t \
|
||||
{ \
|
||||
public: \
|
||||
NETLIB_NAME(_name) () \
|
||||
: net_device_t() { } \
|
||||
protected: \
|
||||
ATTR_HOT void update(); \
|
||||
ATTR_HOT void start(); \
|
||||
_priv \
|
||||
}
|
||||
|
||||
#define NETLIB_SUBDEVICE(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public netlist_core_device_t \
|
||||
{ \
|
||||
public: \
|
||||
NETLIB_NAME(_name) () \
|
||||
: netlist_core_device_t() \
|
||||
{ } \
|
||||
/*protected:*/ \
|
||||
ATTR_HOT void update(); \
|
||||
_priv \
|
||||
}
|
||||
|
||||
#define NETLIB_DEVICE_WITH_PARAMS(_name, _priv) \
|
||||
class NETLIB_NAME(_name) : public net_device_t \
|
||||
{ \
|
||||
public: \
|
||||
NETLIB_NAME(_name) () \
|
||||
: net_device_t() { } \
|
||||
ATTR_HOT void update_param(); \
|
||||
ATTR_HOT void update(); \
|
||||
ATTR_HOT void start(); \
|
||||
/* protected: */ \
|
||||
_priv \
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// forward definitions
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class net_output_t;
|
||||
class net_param_t;
|
||||
class netlist_setup_t;
|
||||
class netlist_base_t;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_object_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class net_object_t
|
||||
{
|
||||
public:
|
||||
enum type_t {
|
||||
INPUT = 0,
|
||||
OUTPUT = 1,
|
||||
DEVICE = 2,
|
||||
PARAM = 3,
|
||||
TERMINAL = 4,
|
||||
NET_ANALOG = 5,
|
||||
NET_DIGITAL = 6,
|
||||
TYPE_MASK = 0x0f,
|
||||
SIGNAL_DIGITAL = 0x00,
|
||||
SIGNAL_ANALOG = 0x10,
|
||||
SIGNAL_MASK = 0x10,
|
||||
};
|
||||
|
||||
net_object_t(int atype)
|
||||
: m_objtype(atype) {}
|
||||
|
||||
virtual ~net_object_t() {}
|
||||
|
||||
ATTR_HOT inline int object_type() const { return m_objtype; }
|
||||
ATTR_HOT inline int object_type(const UINT32 mask) const { return m_objtype & mask; }
|
||||
|
||||
private:
|
||||
int m_objtype;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_terminal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class net_terminal_t : public net_object_t
|
||||
{
|
||||
public:
|
||||
|
||||
net_terminal_t(const int atype)
|
||||
: net_object_t(atype)
|
||||
, m_netdev(NULL)
|
||||
, m_netlist(NULL)
|
||||
{}
|
||||
|
||||
ATTR_COLD void init_terminal(netlist_core_device_t *dev);
|
||||
ATTR_HOT inline netlist_core_device_t * RESTRICT netdev() const { return m_netdev; }
|
||||
ATTR_HOT inline netlist_base_t * RESTRICT netlist() const { return m_netlist; }
|
||||
|
||||
private:
|
||||
netlist_core_device_t * RESTRICT m_netdev;
|
||||
netlist_base_t * RESTRICT m_netlist;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_input_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class net_input_t : public net_terminal_t
|
||||
{
|
||||
public:
|
||||
|
||||
enum net_input_state {
|
||||
INP_STATE_PASSIVE = 0,
|
||||
INP_STATE_ACTIVE = 1,
|
||||
INP_STATE_HL = 2,
|
||||
INP_STATE_LH = 4,
|
||||
};
|
||||
|
||||
ATTR_COLD net_input_t(const int atype)
|
||||
: net_terminal_t(atype)
|
||||
, m_low_thresh_V(0)
|
||||
, m_high_thresh_V(0)
|
||||
, m_state(INP_STATE_ACTIVE)
|
||||
, m_output(NULL)
|
||||
{}
|
||||
|
||||
ATTR_COLD void init_input(netlist_core_device_t *dev, net_input_state astate = INP_STATE_ACTIVE);
|
||||
|
||||
ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; }
|
||||
ATTR_HOT inline const bool is_state(const net_input_state astate) const { return (m_state == astate); }
|
||||
ATTR_HOT inline const net_input_state state() const { return m_state; }
|
||||
|
||||
ATTR_COLD void set_output(net_output_t &aout) { m_output = &aout; }
|
||||
ATTR_HOT inline void inactivate();
|
||||
ATTR_HOT inline void activate();
|
||||
ATTR_HOT inline void activate_hl();
|
||||
ATTR_HOT inline void activate_lh();
|
||||
|
||||
double m_low_thresh_V;
|
||||
double m_high_thresh_V;
|
||||
|
||||
private:
|
||||
net_input_state m_state;
|
||||
net_output_t * RESTRICT m_output;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// logic_input_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class logic_input_t : public net_input_t
|
||||
{
|
||||
public:
|
||||
logic_input_t()
|
||||
: net_input_t(INPUT | SIGNAL_DIGITAL)
|
||||
{
|
||||
// default to TTL
|
||||
m_low_thresh_V = 0.8;
|
||||
m_high_thresh_V = 2.0;
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_sig_t Q() const;
|
||||
ATTR_HOT inline const netlist_sig_t last_Q() const;
|
||||
|
||||
ATTR_COLD inline void set_thresholds(const double low, const double high)
|
||||
{
|
||||
m_low_thresh_V = low;
|
||||
m_high_thresh_V = high;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ttl_input_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class ttl_input_t : public logic_input_t
|
||||
{
|
||||
public:
|
||||
ttl_input_t()
|
||||
: logic_input_t() { set_thresholds(0.8 , 2.0); }
|
||||
};
|
||||
|
||||
class analog_input_t : public net_input_t
|
||||
{
|
||||
public:
|
||||
analog_input_t()
|
||||
: net_input_t(INPUT | SIGNAL_ANALOG) { }
|
||||
|
||||
ATTR_HOT inline const bool is_highz() const;
|
||||
ATTR_HOT inline const double Q_Analog() const;
|
||||
};
|
||||
|
||||
//#define INPVAL(_x) (_x).Q()
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_output_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class NETLIB_NAME(netdev_mainclock);
|
||||
|
||||
class net_output_t : public net_terminal_t
|
||||
{
|
||||
public:
|
||||
|
||||
net_output_t(int atype);
|
||||
|
||||
friend const netlist_sig_t logic_input_t::Q() const;
|
||||
friend const double analog_input_t::Q_Analog() const;
|
||||
friend const bool analog_input_t::is_highz() const;
|
||||
friend class NETLIB_NAME(netdev_mainclock);
|
||||
|
||||
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_COLD void register_con(net_input_t &inp);
|
||||
|
||||
ATTR_HOT inline void update_devs();
|
||||
|
||||
ATTR_HOT inline void inc_active();
|
||||
ATTR_HOT inline void dec_active();
|
||||
|
||||
ATTR_HOT inline const int active_count() const { return m_active; }
|
||||
ATTR_HOT inline const netlist_time time() const { return m_time; }
|
||||
ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; }
|
||||
|
||||
double m_low_V;
|
||||
double m_high_V;
|
||||
|
||||
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);
|
||||
return m_Q;
|
||||
}
|
||||
ATTR_HOT inline const double Q_Analog() const
|
||||
{
|
||||
assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG);
|
||||
return m_Q_analog;
|
||||
}
|
||||
|
||||
ATTR_HOT inline void push_to_queue(const netlist_time &delay);
|
||||
|
||||
netlist_sig_t m_last_Q;
|
||||
netlist_sig_t m_Q;
|
||||
netlist_sig_t m_new_Q;
|
||||
|
||||
double m_Q_analog;
|
||||
double m_new_Q_analog;
|
||||
|
||||
UINT32 m_num_cons;
|
||||
private:
|
||||
ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask);
|
||||
|
||||
netlist_time m_time;
|
||||
|
||||
INT32 m_active;
|
||||
|
||||
UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
|
||||
|
||||
net_input_t * RESTRICT m_cons[OUTPUT_MAX_CONNECTIONS];
|
||||
};
|
||||
|
||||
|
||||
class logic_output_t : public net_output_t
|
||||
{
|
||||
public:
|
||||
|
||||
logic_output_t()
|
||||
: net_output_t(OUTPUT | SIGNAL_DIGITAL)
|
||||
{
|
||||
// Default to TTL
|
||||
m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications.
|
||||
m_high_V = 4.8;
|
||||
}
|
||||
|
||||
ATTR_COLD void initial(const netlist_sig_t val) { m_Q = val; m_new_Q = val; m_last_Q = !val; }
|
||||
|
||||
ATTR_HOT inline void set_Q(const netlist_sig_t newQ, const netlist_time &delay)
|
||||
{
|
||||
if (EXPECTED(newQ != m_new_Q))
|
||||
{
|
||||
m_new_Q = newQ;
|
||||
if (m_num_cons)
|
||||
push_to_queue(delay);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_COLD inline void set_levels(const double low, const double high)
|
||||
{
|
||||
m_low_V = low;
|
||||
m_high_V = high;
|
||||
}
|
||||
};
|
||||
|
||||
class ttl_output_t : public logic_output_t
|
||||
{
|
||||
public:
|
||||
|
||||
ttl_output_t()
|
||||
: logic_output_t()
|
||||
{ set_levels(0.3, 3.4); }
|
||||
|
||||
};
|
||||
|
||||
class analog_output_t : public net_output_t
|
||||
{
|
||||
public:
|
||||
|
||||
analog_output_t()
|
||||
: net_output_t(OUTPUT | SIGNAL_ANALOG) { }
|
||||
|
||||
ATTR_COLD void initial(const double val) { m_Q_analog = val; m_new_Q_analog = val; }
|
||||
|
||||
ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay)
|
||||
{
|
||||
if (newQ != m_new_Q_analog)
|
||||
{
|
||||
m_new_Q_analog = newQ;
|
||||
push_to_queue(delay);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_core_device_t : public net_object_t
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_core_device_t();
|
||||
|
||||
virtual ~netlist_core_device_t();
|
||||
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
|
||||
|
||||
ATTR_COLD const astring &name() const { return m_name; }
|
||||
|
||||
ATTR_HOT virtual void update_param() {}
|
||||
|
||||
ATTR_HOT const netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
|
||||
|
||||
ATTR_HOT inline void update_dev()
|
||||
{
|
||||
#if USE_DELEGATES
|
||||
#if USE_PMFDELEGATES
|
||||
static_update(this);
|
||||
#else
|
||||
static_update();
|
||||
#endif
|
||||
#else
|
||||
update();
|
||||
#endif
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_sig_t INPLOGIC(const logic_input_t &inp) const
|
||||
{
|
||||
assert(inp.state() != net_input_t::INP_STATE_PASSIVE);
|
||||
return inp.Q();
|
||||
}
|
||||
|
||||
ATTR_HOT inline void OUTLOGIC(logic_output_t &out, const netlist_sig_t val, const netlist_time &delay)
|
||||
{
|
||||
out.set_Q(val, delay);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool INP_HL(const logic_input_t &inp) const
|
||||
{
|
||||
return ((inp.last_Q() & !inp.Q()) == 1);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool INP_LH(const logic_input_t &inp) const
|
||||
{
|
||||
return ((!inp.last_Q() & inp.Q()) == 1);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const double INPANALOG(const analog_input_t &inp) const { return inp.Q_Analog(); }
|
||||
|
||||
ATTR_HOT inline void OUTANALOG(analog_output_t &out, const double val, const netlist_time &delay)
|
||||
{
|
||||
out.set_Q(val, delay);
|
||||
}
|
||||
|
||||
ATTR_HOT inline netlist_base_t *netlist() const { return m_netlist; }
|
||||
|
||||
ATTR_HOT virtual void inc_active() { }
|
||||
|
||||
ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ }
|
||||
|
||||
/* stats */
|
||||
osd_ticks_t total_time;
|
||||
INT32 stat_count;
|
||||
|
||||
#if USE_DELEGATES
|
||||
net_update_delegate static_update;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_HOT virtual void update() { }
|
||||
ATTR_HOT virtual void start() { }
|
||||
|
||||
netlist_base_t * RESTRICT m_netlist;
|
||||
|
||||
private:
|
||||
|
||||
astring m_name;
|
||||
};
|
||||
|
||||
|
||||
class net_device_t : public netlist_core_device_t
|
||||
{
|
||||
public:
|
||||
|
||||
net_device_t();
|
||||
|
||||
virtual ~net_device_t();
|
||||
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
|
||||
|
||||
ATTR_COLD const netlist_setup_t *setup() const { return m_setup; }
|
||||
|
||||
ATTR_COLD bool variable_input_count() { return m_variable_input_count; }
|
||||
|
||||
ATTR_COLD void register_sub(netlist_core_device_t &dev, const astring &name);
|
||||
|
||||
ATTR_COLD void register_output(const astring &name, net_output_t &out);
|
||||
ATTR_COLD void register_output(netlist_core_device_t &dev, const astring &name, net_output_t &out);
|
||||
|
||||
ATTR_COLD void register_input(const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
|
||||
ATTR_COLD void register_input(netlist_core_device_t &dev, const astring &name, net_input_t &in, net_input_t::net_input_state state = net_input_t::INP_STATE_ACTIVE);
|
||||
|
||||
ATTR_COLD void register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
|
||||
ATTR_COLD void register_link_internal(netlist_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState);
|
||||
|
||||
netlist_list_t<astring> m_inputs;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void update() { }
|
||||
ATTR_HOT virtual void start() { }
|
||||
|
||||
ATTR_COLD void register_param(const astring &sname, net_param_t ¶m, const double initialVal = 0.0);
|
||||
ATTR_COLD void register_param(netlist_core_device_t &dev, const astring &sname, net_param_t ¶m, const double initialVal = 0.0);
|
||||
|
||||
netlist_setup_t *m_setup;
|
||||
bool m_variable_input_count;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class net_param_t
|
||||
{
|
||||
public:
|
||||
net_param_t()
|
||||
: m_param(0.0)
|
||||
, m_netdev(NULL)
|
||||
{ }
|
||||
|
||||
inline void setTo(const double param) { m_param = param; m_netdev->update_param(); }
|
||||
inline void setTo(const int param) { m_param = param; m_netdev->update_param(); }
|
||||
inline void initial(const double val) { m_param = val; }
|
||||
inline void initial(const int val) { m_param = val; }
|
||||
|
||||
ATTR_HOT inline double Value() const { return m_param; }
|
||||
ATTR_HOT inline int ValueInt() const { return (int) m_param; }
|
||||
|
||||
ATTR_HOT inline netlist_core_device_t &netdev() const { return *m_netdev; }
|
||||
void set_netdev(netlist_core_device_t &dev) { m_netdev = &dev; }
|
||||
|
||||
private:
|
||||
|
||||
double m_param;
|
||||
netlist_core_device_t *m_netdev;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class netdev_mainclock;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_base_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_base_t
|
||||
{
|
||||
public:
|
||||
|
||||
typedef netlist_timed_queue1<net_output_t, netlist_time, 512> queue_t;
|
||||
|
||||
netlist_base_t();
|
||||
virtual ~netlist_base_t();
|
||||
|
||||
void set_clock_freq(UINT64 clockfreq);
|
||||
|
||||
ATTR_HOT inline void push_to_queue(net_output_t &out, const netlist_time &attime)
|
||||
{
|
||||
m_queue.push(queue_t::entry_t(attime, out));
|
||||
}
|
||||
|
||||
ATTR_HOT void process_queue(INT32 &atime);
|
||||
|
||||
ATTR_HOT inline const netlist_time &time() const { return m_time_ps; }
|
||||
|
||||
ATTR_COLD void set_mainclock_dev(NETLIB_NAME(netdev_mainclock) *dev);
|
||||
|
||||
ATTR_COLD void reset();
|
||||
|
||||
// FIXME: should'nt be public
|
||||
queue_t m_queue;
|
||||
|
||||
protected:
|
||||
// performance
|
||||
int m_perf_out_processed;
|
||||
int m_perf_inp_processed;
|
||||
int m_perf_inp_active;
|
||||
|
||||
private:
|
||||
NETLIB_NAME(netdev_mainclock) *m_mainclock;
|
||||
netlist_time m_time_ps;
|
||||
UINT32 m_rem;
|
||||
UINT32 m_div;
|
||||
|
||||
|
||||
ATTR_HOT void update_time(const netlist_time t, INT32 &atime);
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_a_to_d
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netdev_a_to_d_proxy : public net_device_t
|
||||
{
|
||||
public:
|
||||
netdev_a_to_d_proxy(net_input_t &in_proxied)
|
||||
: net_device_t()
|
||||
{
|
||||
assert(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
|
||||
m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
|
||||
m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
|
||||
}
|
||||
|
||||
virtual ~netdev_a_to_d_proxy() {}
|
||||
|
||||
analog_input_t m_I;
|
||||
ttl_output_t m_Q;
|
||||
|
||||
protected:
|
||||
void start()
|
||||
{
|
||||
m_I.init_input(this);
|
||||
|
||||
m_Q.init_terminal(this);
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void update()
|
||||
{
|
||||
if (m_I.Q_Analog() > m_I.m_high_thresh_V)
|
||||
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
|
||||
else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
|
||||
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netdev_d_to_a
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netdev_d_to_a_proxy : public net_device_t
|
||||
{
|
||||
public:
|
||||
netdev_d_to_a_proxy(net_output_t &out_proxied)
|
||||
: net_device_t()
|
||||
{
|
||||
assert(out_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL);
|
||||
m_low_V = out_proxied.m_low_V;
|
||||
m_high_V = out_proxied.m_high_V;
|
||||
}
|
||||
|
||||
virtual ~netdev_d_to_a_proxy() {}
|
||||
|
||||
ttl_input_t m_I;
|
||||
analog_output_t m_Q;
|
||||
|
||||
protected:
|
||||
void start()
|
||||
{
|
||||
m_I.init_input(this);
|
||||
m_Q.init_terminal(this);
|
||||
m_Q.initial(0);
|
||||
}
|
||||
|
||||
ATTR_HOT ATTR_ALIGN void update()
|
||||
{
|
||||
OUTANALOG(m_Q, INPLOGIC(m_I) ? m_high_V : m_low_V, NLTIME_FROM_NS(1));
|
||||
}
|
||||
|
||||
private:
|
||||
double m_low_V;
|
||||
double m_high_V;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Inline implementations
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_HOT inline void net_input_t::inactivate()
|
||||
{
|
||||
if (m_state != INP_STATE_PASSIVE)
|
||||
{
|
||||
m_state = INP_STATE_PASSIVE;
|
||||
m_output->dec_active();
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_input_t::activate()
|
||||
{
|
||||
if (m_state == INP_STATE_PASSIVE)
|
||||
{
|
||||
m_output->inc_active();
|
||||
m_state = INP_STATE_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_input_t::activate_hl()
|
||||
{
|
||||
if (m_state == INP_STATE_PASSIVE)
|
||||
{
|
||||
m_output->inc_active();
|
||||
m_state = INP_STATE_HL;
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_input_t::activate_lh()
|
||||
{
|
||||
if (m_state == INP_STATE_PASSIVE)
|
||||
{
|
||||
m_output->inc_active();
|
||||
m_state = INP_STATE_LH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay)
|
||||
{
|
||||
// if (m_in_queue == 1) return; FIXME: check this at some time
|
||||
m_time = netlist()->time() + delay;
|
||||
m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
|
||||
if (m_in_queue)
|
||||
{
|
||||
//m_in_queue = 1; /* pending */
|
||||
netlist()->push_to_queue(*this, m_time);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_output_t::inc_active()
|
||||
{
|
||||
m_active++;
|
||||
|
||||
#if USE_DEACTIVE_DEVICE
|
||||
if (m_active == 1 && m_in_queue > 0)
|
||||
{
|
||||
m_last_Q = m_Q;
|
||||
netdev()->inc_active();
|
||||
m_Q = m_new_Q;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (EXPECTED(m_active == 1 && m_in_queue == 0))
|
||||
{
|
||||
if (EXPECTED(m_time > netlist()->time()))
|
||||
{
|
||||
m_in_queue = 1; /* pending */
|
||||
netlist()->push_to_queue(*this, m_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Q = m_last_Q = m_new_Q;
|
||||
m_Q_analog = m_new_Q_analog;
|
||||
m_in_queue = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_HOT inline void net_output_t::dec_active()
|
||||
{
|
||||
m_active--;
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
if (m_active == 0)
|
||||
netdev()->dec_active();
|
||||
#endif
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_sig_t logic_input_t::Q() const
|
||||
{
|
||||
return output()->Q();
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_sig_t logic_input_t::last_Q() const
|
||||
{
|
||||
return output()->last_Q();
|
||||
}
|
||||
|
||||
ATTR_HOT inline const double analog_input_t::Q_Analog() const
|
||||
{
|
||||
return output()->Q_Analog();
|
||||
}
|
||||
|
||||
ATTR_HOT inline const bool analog_input_t::is_highz() const
|
||||
{
|
||||
return (output()->Q_Analog() == NETLIST_HIGHIMP_V);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_dev class factory
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class net_device_t_base_factory
|
||||
{
|
||||
public:
|
||||
net_device_t_base_factory(const astring &name, const astring &classname)
|
||||
: m_name(name), m_classname(classname)
|
||||
{}
|
||||
|
||||
virtual ~net_device_t_base_factory() {}
|
||||
|
||||
virtual net_device_t *Create() const = 0;
|
||||
|
||||
const astring &name() const { return m_name; }
|
||||
const astring &classname() const { return m_classname; }
|
||||
protected:
|
||||
astring m_name; /* device name */
|
||||
astring m_classname; /* device class name */
|
||||
};
|
||||
|
||||
template <class C>
|
||||
class net_device_t_factory : public net_device_t_base_factory
|
||||
{
|
||||
public:
|
||||
net_device_t_factory(const astring &name, const astring &classname)
|
||||
: net_device_t_base_factory(name, classname) { }
|
||||
|
||||
net_device_t *Create() const
|
||||
{
|
||||
net_device_t *r = new C();
|
||||
//r->init(setup, name);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
net_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup, const astring &icname);
|
||||
net_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup, const astring &icname);
|
||||
|
||||
|
||||
#endif /* NLBASE_H_ */
|
103
src/emu/netlist/nl_config.h
Normal file
103
src/emu/netlist/nl_config.h
Normal file
@ -0,0 +1,103 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nlconfig.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NLCONFIG_H_
|
||||
#define NLCONFIG_H_
|
||||
|
||||
/* FIXME: at some time, make it compile on it's own */
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
//============================================================
|
||||
// SETUP
|
||||
//============================================================
|
||||
|
||||
#define USE_DELEGATES (0)
|
||||
/*
|
||||
* The next options needs -Wno-pmf-conversions to compile and gcc
|
||||
* This is intended for non-mame usage.
|
||||
*
|
||||
*/
|
||||
#define USE_PMFDELEGATES (0)
|
||||
|
||||
// Next if enabled adds 20% performance ... but is not guaranteed to be absolutely timing correct.
|
||||
#define USE_DEACTIVE_DEVICE (0)
|
||||
|
||||
#define OUTPUT_MAX_CONNECTIONS (48)
|
||||
|
||||
// Use nano-second resolution - Sufficient for now
|
||||
#define NETLIST_INTERNAL_RES (U64(1000000000))
|
||||
#define NETLIST_DIV_BITS (0)
|
||||
//#define NETLIST_INTERNAL_RES (U64(1000000000000))
|
||||
//#define NETLIST_DIV_BITS (10)
|
||||
#define NETLIST_DIV (U64(1) << NETLIST_DIV_BITS)
|
||||
#define NETLIST_MASK (NETLIST_DIV-1)
|
||||
#define NETLIST_CLOCK (NETLIST_INTERNAL_RES / NETLIST_DIV)
|
||||
|
||||
#define NETLIST_HIGHIMP_V (1.23456e20) /* some voltage we should never see */
|
||||
|
||||
typedef UINT8 netlist_sig_t;
|
||||
|
||||
/* FIXME: We need a different solution to output delegates !
|
||||
* More something like a callback object
|
||||
*/
|
||||
|
||||
typedef delegate<void (const double)> netlist_output_delegate;
|
||||
|
||||
//============================================================
|
||||
// DEBUGGING
|
||||
//============================================================
|
||||
|
||||
#define NL_VERBOSE (0)
|
||||
#define NL_KEEP_STATISTICS (0)
|
||||
#define FATAL_ERROR_AFTER_NS (0) //(1000)
|
||||
|
||||
#if (NL_VERBOSE)
|
||||
#define NL_VERBOSE_OUT(x) printf x
|
||||
#else
|
||||
#define NL_VERBOSE_OUT(x)
|
||||
#endif
|
||||
|
||||
//============================================================
|
||||
// MACROS
|
||||
//============================================================
|
||||
|
||||
#if NL_KEEP_STATISTICS
|
||||
#define add_to_stat(v,x) do { v += (x); } while (0)
|
||||
#define inc_stat(v) add_to_stat(v, 1)
|
||||
#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
|
||||
#define end_timing(v) do { (v) += get_profile_ticks(); } while (0)
|
||||
#else
|
||||
#define add_to_stat(v,x) do { } while (0)
|
||||
#define inc_stat(v) add_to_stat(v, 1)
|
||||
#define begin_timing(v) do { } while (0)
|
||||
#define end_timing(v) do { } while (0)
|
||||
#endif
|
||||
|
||||
// Compiling without mame ?
|
||||
|
||||
#ifndef ATTR_HOT
|
||||
#warning ATTR_HOT not defined
|
||||
#define ATTR_HOT
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_COLD
|
||||
#define ATTR_COLD
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
|
||||
#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
|
||||
#define ATTR_ALIGN __attribute__ ((aligned(128)))
|
||||
#else
|
||||
#define ATTR_ALIGN
|
||||
#endif
|
||||
#else
|
||||
#define ATTR_ALIGN
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* NLCONFIG_H_ */
|
134
src/emu/netlist/nl_lists.h
Normal file
134
src/emu/netlist/nl_lists.h
Normal file
@ -0,0 +1,134 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nllists.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NLLISTS_H_
|
||||
#define NLLISTS_H_
|
||||
|
||||
#include "nl_config.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_list_t: a simple list
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class _ListClass>
|
||||
struct netlist_list_t
|
||||
{
|
||||
public:
|
||||
ATTR_COLD netlist_list_t(int numElements)
|
||||
{
|
||||
m_num_elements = numElements;
|
||||
m_list = new _ListClass[m_num_elements];
|
||||
m_ptr = m_list;
|
||||
m_ptr--;
|
||||
}
|
||||
ATTR_COLD ~netlist_list_t()
|
||||
{
|
||||
delete[] m_list;
|
||||
}
|
||||
ATTR_HOT inline void add(const _ListClass elem)
|
||||
{
|
||||
assert(m_ptr-m_list <= m_num_elements - 1);
|
||||
|
||||
*(++m_ptr) = elem;
|
||||
}
|
||||
ATTR_HOT inline _ListClass *first() { return &m_list[0]; }
|
||||
ATTR_HOT inline _ListClass *last() { return m_ptr; }
|
||||
ATTR_HOT inline _ListClass *item(int i) { return &m_list[i]; }
|
||||
ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }
|
||||
ATTR_HOT inline bool empty() { return (m_ptr < m_list); }
|
||||
ATTR_HOT inline void clear() { m_ptr = m_list - 1; }
|
||||
private:
|
||||
_ListClass * m_ptr;
|
||||
_ListClass * m_list;
|
||||
int m_num_elements;
|
||||
//_ListClass m_list[_NumElements];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// timed queue
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <class _Element, class _Time, int _Size>
|
||||
class netlist_timed_queue1
|
||||
{
|
||||
public:
|
||||
|
||||
struct entry_t
|
||||
{
|
||||
public:
|
||||
inline entry_t()
|
||||
: m_time(), m_object(NULL) {}
|
||||
inline entry_t(const _Time atime, _Element &elem) : m_time(atime), m_object(&elem) {}
|
||||
ATTR_HOT inline const _Time &time() const { return m_time; }
|
||||
ATTR_HOT inline _Element & object() const { return *m_object; }
|
||||
private:
|
||||
_Time m_time;
|
||||
_Element *m_object;
|
||||
};
|
||||
|
||||
netlist_timed_queue1()
|
||||
{
|
||||
//m_list = global_alloc_array(entry_t, SIZE);
|
||||
clear();
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); }
|
||||
ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); }
|
||||
|
||||
ATTR_HOT ATTR_ALIGN inline void push(const entry_t &e)
|
||||
{
|
||||
if (is_empty() || (e.time() <= (m_end - 1)->time()))
|
||||
{
|
||||
*m_end++ = e;
|
||||
//inc_stat(m_prof_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_t * RESTRICT i = m_end++;
|
||||
while ((i>&m_list[0]) && (e.time() > (i-1)->time()) )
|
||||
{
|
||||
i--;
|
||||
*(i+1) = *i;
|
||||
//inc_stat(m_prof_sortmove);
|
||||
}
|
||||
*i = e;
|
||||
//inc_stat(m_prof_sort);
|
||||
}
|
||||
assert(m_end - m_list < _Size);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const entry_t pop()
|
||||
{
|
||||
return *--m_end;
|
||||
}
|
||||
|
||||
ATTR_HOT inline const entry_t peek() const
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
|
||||
ATTR_COLD void clear()
|
||||
{
|
||||
m_end = &m_list[0];
|
||||
}
|
||||
// profiling
|
||||
|
||||
INT32 m_prof_start;
|
||||
INT32 m_prof_end;
|
||||
INT32 m_prof_sortmove;
|
||||
INT32 m_prof_sort;
|
||||
private:
|
||||
|
||||
entry_t * RESTRICT m_end;
|
||||
//entry_t *m_list;
|
||||
entry_t m_list[_Size];
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* NLLISTS_H_ */
|
207
src/emu/netlist/nl_parser.c
Normal file
207
src/emu/netlist/nl_parser.c
Normal file
@ -0,0 +1,207 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nl_parser.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nl_parser.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// A netlist parser
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void netlist_parser::parse(char *buf)
|
||||
{
|
||||
m_p = buf;
|
||||
while (*m_p)
|
||||
{
|
||||
astring n;
|
||||
skipws();
|
||||
if (!*m_p) break;
|
||||
n = getname('(');
|
||||
NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr()));
|
||||
if (n == "NET_ALIAS")
|
||||
net_alias();
|
||||
else if (n == "NETDEV_PARAM")
|
||||
netdev_param();
|
||||
else if ((n == "NETDEV_TTL_CONST") || (n == "NETDEV_ANALOG_CONST"))
|
||||
netdev_const(n);
|
||||
else
|
||||
netdev_device(n);
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_parser::net_alias()
|
||||
{
|
||||
astring alias;
|
||||
astring out;
|
||||
skipws();
|
||||
alias = getname(',');
|
||||
skipws();
|
||||
out = getname(')');
|
||||
NL_VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr()));
|
||||
m_setup.register_alias(alias, out);
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_param()
|
||||
{
|
||||
astring param;
|
||||
double val;
|
||||
skipws();
|
||||
param = getname(',');
|
||||
skipws();
|
||||
val = eval_param();
|
||||
NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val));
|
||||
m_setup.find_param(param).initial(val);
|
||||
check_char(')');
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_const(const astring &dev_name)
|
||||
{
|
||||
astring name;
|
||||
net_device_t *dev;
|
||||
astring paramfq;
|
||||
double val;
|
||||
|
||||
skipws();
|
||||
name = getname(',');
|
||||
dev = net_create_device_by_name(dev_name, m_setup, name);
|
||||
m_setup.register_dev(dev);
|
||||
skipws();
|
||||
val = eval_param();
|
||||
check_char(')');
|
||||
paramfq = name;
|
||||
paramfq.cat(".CONST");
|
||||
NL_VERBOSE_OUT(("Parser: Const: %s %f\n", name.cstr(), val));
|
||||
m_setup.find_param(paramfq).initial(val);
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_device(const astring &dev_type)
|
||||
{
|
||||
astring devname;
|
||||
net_device_t *dev;
|
||||
int cnt;
|
||||
|
||||
skipws();
|
||||
devname = getname2(',', ')');
|
||||
dev = net_create_device_by_name(dev_type, m_setup, devname);
|
||||
m_setup.register_dev(dev);
|
||||
skipws();
|
||||
NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr()));
|
||||
cnt = 0;
|
||||
while (*m_p != ')')
|
||||
{
|
||||
m_p++;
|
||||
skipws();
|
||||
astring output_name = getname2(',', ')');
|
||||
NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_inputs.item(cnt)->cstr()));
|
||||
m_setup.register_link(*dev->m_inputs.item(cnt), output_name);
|
||||
skipws();
|
||||
cnt++;
|
||||
}
|
||||
if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
|
||||
fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), dev->m_inputs.count(), cnt);
|
||||
if (dev->variable_input_count())
|
||||
{
|
||||
NL_VERBOSE_OUT(("variable inputs %s: %d\n", dev->name().cstr(), cnt));
|
||||
}
|
||||
check_char(')');
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// private
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void netlist_parser::skipeol()
|
||||
{
|
||||
while (*m_p)
|
||||
{
|
||||
if (*m_p == 10)
|
||||
{
|
||||
m_p++;
|
||||
if (*m_p && *m_p == 13)
|
||||
m_p++;
|
||||
return;
|
||||
}
|
||||
m_p++;
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_parser::skipws()
|
||||
{
|
||||
while (*m_p)
|
||||
{
|
||||
switch (*m_p)
|
||||
{
|
||||
case ' ':
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
m_p++;
|
||||
break;
|
||||
case '/':
|
||||
if (*(m_p+1) == '/')
|
||||
skipeol();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
astring netlist_parser::getname(char sep)
|
||||
{
|
||||
char buf[300];
|
||||
char *p1 = buf;
|
||||
|
||||
while (*m_p != sep)
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
m_p++;
|
||||
return astring(buf);
|
||||
}
|
||||
|
||||
astring netlist_parser::getname2(char sep1, char sep2)
|
||||
{
|
||||
char buf[300];
|
||||
char *p1 = buf;
|
||||
|
||||
while ((*m_p != sep1) && (*m_p != sep2))
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
return astring(buf);
|
||||
}
|
||||
|
||||
void netlist_parser::check_char(char ctocheck)
|
||||
{
|
||||
skipws();
|
||||
if (*m_p == ctocheck)
|
||||
{
|
||||
m_p++;
|
||||
return;
|
||||
}
|
||||
fatalerror("Parser: expected '%c' found '%c'\n", ctocheck, *m_p);
|
||||
}
|
||||
|
||||
double netlist_parser::eval_param()
|
||||
{
|
||||
static const char *macs[6] = {"", "RES_K(", "RES_M(", "CAP_U(", "CAP_N(", "CAP_P("};
|
||||
static double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
|
||||
int i;
|
||||
int f=0;
|
||||
char *e;
|
||||
double ret;
|
||||
char *s = m_p;
|
||||
|
||||
for (i=1; i<6;i++)
|
||||
if (strncmp(s, macs[i], strlen(macs[i])) == 0)
|
||||
f = i;
|
||||
ret = strtod(s+strlen(macs[f]), &e);
|
||||
if ((f>0) && (*e != ')'))
|
||||
fatalerror("Parser: Error with parameter ...\n");
|
||||
if (f>0)
|
||||
e++;
|
||||
m_p = e;
|
||||
return ret * facs[f];
|
||||
}
|
39
src/emu/netlist/nl_parser.h
Normal file
39
src/emu/netlist/nl_parser.h
Normal file
@ -0,0 +1,39 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nl_parser.c
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NL_PARSER_H_
|
||||
#define NL_PARSER_H_
|
||||
|
||||
#include "nl_setup.h"
|
||||
|
||||
class netlist_parser
|
||||
{
|
||||
public:
|
||||
netlist_parser(netlist_setup_t &setup)
|
||||
: m_setup(setup) {}
|
||||
|
||||
void parse(char *buf);
|
||||
void net_alias();
|
||||
void netdev_param();
|
||||
void netdev_const(const astring &dev_name);
|
||||
void netdev_device(const astring &dev_type);
|
||||
|
||||
private:
|
||||
|
||||
void skipeol();
|
||||
void skipws();
|
||||
astring getname(char sep);
|
||||
astring getname2(char sep1, char sep2);
|
||||
void check_char(char ctocheck);
|
||||
double eval_param();
|
||||
|
||||
char * m_p;
|
||||
netlist_setup_t &m_setup;
|
||||
};
|
||||
|
||||
|
||||
#endif /* NL_PARSER_H_ */
|
318
src/emu/netlist/nl_setup.c
Normal file
318
src/emu/netlist/nl_setup.c
Normal file
@ -0,0 +1,318 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nlsetup.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nl_base.h"
|
||||
#include "nl_setup.h"
|
||||
#include "nl_parser.h"
|
||||
#include "devices/nld_system.h"
|
||||
|
||||
static NETLIST_START(base)
|
||||
NETDEV_TTL_CONST(ttlhigh, 1)
|
||||
NETDEV_TTL_CONST(ttllow, 0)
|
||||
NETDEV_ANALOG_CONST(NC, NETLIST_HIGHIMP_V)
|
||||
NETLIST_END
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_setup_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
|
||||
: m_netlist(netlist)
|
||||
{
|
||||
NETLIST_NAME(base)(*this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void tagmap_free_entries(T &tm)
|
||||
{
|
||||
for (typename T::entry_t *entry = tm.first(); entry != NULL; entry = tm.next(entry))
|
||||
{
|
||||
delete entry->object();
|
||||
}
|
||||
tm.reset();
|
||||
}
|
||||
|
||||
netlist_setup_t::~netlist_setup_t()
|
||||
{
|
||||
tagmap_free_entries<tagmap_devices_t>(m_devices);
|
||||
tagmap_free_entries<tagmap_astring_t>(m_links);
|
||||
tagmap_free_entries<tagmap_astring_t>(m_alias);
|
||||
m_params.reset();
|
||||
m_terminals.reset();
|
||||
}
|
||||
|
||||
net_device_t *netlist_setup_t::register_dev(net_device_t *dev)
|
||||
{
|
||||
if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE))
|
||||
fatalerror("Error adding %s to device list\n", dev->name().cstr());
|
||||
return dev;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void remove_start_with(T &hm, astring &sw)
|
||||
{
|
||||
typename T::entry_t *entry = hm.first();
|
||||
while (entry != NULL)
|
||||
{
|
||||
typename T::entry_t *next = hm.next(entry);
|
||||
if (sw.cmpsubstr(entry->tag(), 0, sw.len()) == 0)
|
||||
{
|
||||
NL_VERBOSE_OUT(("removing %s\n", entry->tag().cstr()));
|
||||
hm.remove(entry->object());
|
||||
}
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_setup_t::remove_dev(const astring &name)
|
||||
{
|
||||
net_device_t *dev = m_devices.find(name);
|
||||
astring temp = name;
|
||||
if (dev == NULL)
|
||||
fatalerror("Device %s does not exist\n", name.cstr());
|
||||
|
||||
temp.cat(".");
|
||||
|
||||
//remove_start_with<tagmap_input_t>(m_inputs, temp);
|
||||
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
|
||||
remove_start_with<tagmap_param_t>(m_params, temp);
|
||||
remove_start_with<tagmap_astring_t>(m_links, temp);
|
||||
m_devices.remove(name);
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_callback(const astring &devname, netlist_output_delegate delegate)
|
||||
{
|
||||
NETLIB_NAME(netdev_analog_callback) *dev = (NETLIB_NAME(netdev_analog_callback) *) m_devices.find(devname);
|
||||
if (dev == NULL)
|
||||
fatalerror("did not find device %s\n", devname.cstr());
|
||||
dev->register_callback(delegate);
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_alias(const astring &alias, const astring &out)
|
||||
{
|
||||
if (!(m_alias.add(alias, new astring(out), false)==TMERR_NONE))
|
||||
fatalerror("Error adding alias %s to alias list\n", alias.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_output_t &out)
|
||||
{
|
||||
NL_VERBOSE_OUT(("out %s\n", name.cstr()));
|
||||
astring temp = dev.name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
out.init_terminal(&upd_dev);
|
||||
if (!(m_terminals.add(temp, &out, false)==TMERR_NONE))
|
||||
fatalerror("Error adding output %s to output list\n", name.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_input(net_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type)
|
||||
{
|
||||
NL_VERBOSE_OUT(("input %s\n", name.cstr()));
|
||||
astring temp = dev.name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
inp.init_input(&upd_dev, type);
|
||||
dev.m_inputs.add(temp);
|
||||
if (!(m_terminals.add(temp, &inp, false) == TMERR_NONE))
|
||||
fatalerror("Error adding input %s to input list\n", name.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_link(const astring &sin, const astring &sout)
|
||||
{
|
||||
const astring *temp = new astring(sout);
|
||||
NL_VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr()));
|
||||
if (!(m_links.add(sin, temp, false)==TMERR_NONE))
|
||||
fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
|
||||
}
|
||||
|
||||
|
||||
void netlist_setup_t::register_param(const astring &name, net_param_t *param)
|
||||
{
|
||||
astring temp = param->netdev().name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
if (!(m_params.add(temp, param, false)==TMERR_NONE))
|
||||
fatalerror("Error adding parameter %s to parameter list\n", name.cstr());
|
||||
}
|
||||
|
||||
|
||||
const astring &netlist_setup_t::resolve_alias(const astring &name) const
|
||||
{
|
||||
const astring *ret = m_alias.find(name);
|
||||
if (ret != NULL)
|
||||
return *ret;
|
||||
return name;
|
||||
}
|
||||
|
||||
net_output_t *netlist_setup_t::find_output_exact(const astring &outname_in)
|
||||
{
|
||||
net_terminal_t *term = m_terminals.find(outname_in);
|
||||
return dynamic_cast<net_output_t *>(term);
|
||||
}
|
||||
|
||||
net_output_t &netlist_setup_t::find_output(const astring &outname_in)
|
||||
{
|
||||
const astring &outname = resolve_alias(outname_in);
|
||||
net_output_t *ret;
|
||||
|
||||
ret = find_output_exact(outname);
|
||||
/* look for default */
|
||||
if (ret == NULL)
|
||||
{
|
||||
/* look for ".Q" std output */
|
||||
astring s = outname;
|
||||
s.cat(".Q");
|
||||
ret = find_output_exact(s);
|
||||
}
|
||||
if (ret == NULL)
|
||||
fatalerror("output %s(%s) not found!\n", outname_in.cstr(), outname.cstr());
|
||||
NL_VERBOSE_OUT(("Found input %s\n", outname.cstr()));
|
||||
return *ret;
|
||||
}
|
||||
|
||||
net_param_t &netlist_setup_t::find_param(const astring ¶m_in)
|
||||
{
|
||||
const astring &outname = resolve_alias(param_in);
|
||||
net_param_t *ret;
|
||||
|
||||
ret = m_params.find(outname);
|
||||
if (ret == NULL)
|
||||
fatalerror("parameter %s(%s) not found!\n", param_in.cstr(), outname.cstr());
|
||||
NL_VERBOSE_OUT(("Found parameter %s\n", outname.cstr()));
|
||||
return *ret;
|
||||
}
|
||||
|
||||
void netlist_setup_t::resolve_inputs(void)
|
||||
{
|
||||
NL_VERBOSE_OUT(("Resolving ...\n"));
|
||||
int proxy_cnt = 0;
|
||||
for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
|
||||
{
|
||||
const astring *sout = entry->object();
|
||||
astring sin = entry->tag();
|
||||
net_input_t *in = dynamic_cast<net_input_t *>(m_terminals.find(sin));
|
||||
|
||||
if (in == NULL)
|
||||
fatalerror("Unable to find %s\n", sin.cstr());
|
||||
|
||||
net_output_t &out = find_output(sout->cstr());
|
||||
if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG
|
||||
&& in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL)
|
||||
{
|
||||
netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in);
|
||||
astring x = "";
|
||||
x.printf("proxy_ad_%d", proxy_cnt++);
|
||||
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
in->set_output(proxy->m_Q);
|
||||
proxy->m_Q.register_con(*in);
|
||||
proxy->m_I.set_output(out);
|
||||
out.register_con(proxy->m_I);
|
||||
|
||||
}
|
||||
else if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL
|
||||
&& in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG)
|
||||
{
|
||||
//printf("here 1\n");
|
||||
netdev_d_to_a_proxy *proxy = new netdev_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
register_dev(proxy);
|
||||
|
||||
in->set_output(proxy->m_Q);
|
||||
proxy->m_Q.register_con(*in);
|
||||
proxy->m_I.set_output(out);
|
||||
out.register_con(proxy->m_I);
|
||||
//printf("here 2\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
in->set_output(out);
|
||||
out.register_con(*in);
|
||||
}
|
||||
}
|
||||
|
||||
/* find the main clock ... */
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
net_device_t *dev = entry->object();
|
||||
if (dynamic_cast<NETLIB_NAME(netdev_mainclock)*>(dev) != NULL)
|
||||
{
|
||||
m_netlist.set_mainclock_dev(dynamic_cast<NETLIB_NAME(netdev_mainclock)*>(dev));
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
#else
|
||||
/* make sure all outputs are triggered once */
|
||||
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
|
||||
{
|
||||
net_output_t *out = entry->object();
|
||||
//if (dynamic_cast<const netdev_clock *>(out->netdev()) == NULL )
|
||||
{
|
||||
out->update_devs_force();
|
||||
INT32 time = 10000;
|
||||
m_netlist.process_list(time);
|
||||
}
|
||||
}
|
||||
//m_netlist.m_queue.clear();
|
||||
#endif
|
||||
|
||||
/* print all outputs */
|
||||
for (tagmap_terminal_t::entry_t *entry = m_terminals.first(); entry != NULL; entry = m_terminals.next(entry))
|
||||
{
|
||||
ATTR_UNUSED net_output_t *out = dynamic_cast<net_output_t *>(entry->object());
|
||||
//if (out != NULL)
|
||||
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void netlist_setup_t::step_devices_once(void)
|
||||
{
|
||||
/* make sure params are set now .. */
|
||||
for (tagmap_param_t::entry_t *entry = m_params.first(); entry != NULL; entry = m_params.next(entry))
|
||||
{
|
||||
entry->object()->netdev().update_param();
|
||||
}
|
||||
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
net_device_t *dev = entry->object();
|
||||
dev->update_dev();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void netlist_setup_t::parse(char *buf)
|
||||
{
|
||||
netlist_parser parser(*this);
|
||||
parser.parse(buf);
|
||||
}
|
||||
|
||||
void netlist_setup_t::print_stats()
|
||||
{
|
||||
if (NL_KEEP_STATISTICS)
|
||||
{
|
||||
for (netlist_setup_t::tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
//entry->object()->s
|
||||
printf("Device %20s : %12d %15ld\n", entry->object()->name().cstr(), entry->object()->stat_count, (long int) entry->object()->total_time / (entry->object()->stat_count + 1));
|
||||
}
|
||||
printf("Queue Start %15d\n", m_netlist.m_queue.m_prof_start);
|
||||
printf("Queue End %15d\n", m_netlist.m_queue.m_prof_end);
|
||||
printf("Queue Sort %15d\n", m_netlist.m_queue.m_prof_sort);
|
||||
printf("Queue Move %15d\n", m_netlist.m_queue.m_prof_sortmove);
|
||||
}
|
||||
}
|
||||
|
113
src/emu/netlist/nl_setup.h
Normal file
113
src/emu/netlist/nl_setup.h
Normal file
@ -0,0 +1,113 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nlsetup.h
|
||||
*
|
||||
* Created on: 3 Nov 2013
|
||||
* Author: andre
|
||||
*/
|
||||
|
||||
#ifndef NLSETUP_H_
|
||||
#define NLSETUP_H_
|
||||
|
||||
#include "nl_base.h"
|
||||
|
||||
//============================================================
|
||||
// MACROS / inline netlist definitions
|
||||
//============================================================
|
||||
|
||||
#define NET_ALIAS(_alias, _name) \
|
||||
netlist.register_alias(# _alias, # _name);
|
||||
#define NET_NEW(_type , _name) net_create_device_by_classname(NETLIB_NAME_STR(_type), netlist, # _name)
|
||||
|
||||
#define NET_REGISTER_DEV(_type, _name) \
|
||||
netlist.register_dev(NET_NEW(_type, _name));
|
||||
#define NET_REMOVE_DEV(_name) \
|
||||
netlist.remove_dev(# _name);
|
||||
#define NET_REGISTER_SIGNAL(_type, _name) \
|
||||
NET_REGISTER_DEV(_type ## _ ## sig, _name)
|
||||
#define NET_CONNECT(_name, _input, _output) \
|
||||
netlist.register_link(# _name "." # _input, # _output);
|
||||
#define NETDEV_PARAM(_name, _val) \
|
||||
netlist.find_param(# _name).initial(_val);
|
||||
|
||||
#define NETLIST_NAME(_name) netlist ## _ ## _name
|
||||
|
||||
#define NETLIST_START(_name) \
|
||||
ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \
|
||||
{
|
||||
|
||||
#define NETLIST_END }
|
||||
|
||||
#define NETLIST_INCLUDE(_name) \
|
||||
NETLIST_NAME(_name)(netlist);
|
||||
|
||||
#define NETLIST_MEMREGION(_name) \
|
||||
netlist.parse((char *)downcast<netlist_t &>(netlist.netlist()).machine().root_device().memregion(_name)->base());
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// FIXME: Clean this up
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class NETLIB_NAME(netdev_analog_callback);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_setup_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_setup_t
|
||||
{
|
||||
public:
|
||||
|
||||
typedef tagmap_t<net_device_t *, 393> tagmap_devices_t;
|
||||
typedef tagmap_t<const astring *, 393> tagmap_astring_t;
|
||||
typedef tagmap_t<net_param_t *, 393> tagmap_param_t;
|
||||
typedef tagmap_t<net_terminal_t *, 393> tagmap_terminal_t;
|
||||
|
||||
netlist_setup_t(netlist_base_t &netlist);
|
||||
~netlist_setup_t();
|
||||
|
||||
netlist_base_t &netlist() { return m_netlist; }
|
||||
|
||||
net_device_t *register_dev(net_device_t *dev);
|
||||
void remove_dev(const astring &name);
|
||||
|
||||
void register_output(netlist_core_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_output_t &out);
|
||||
void register_input(net_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, net_input_t &inp, net_input_t::net_input_state type);
|
||||
void register_alias(const astring &alias, const astring &out);
|
||||
void register_param(const astring &sname, net_param_t *param);
|
||||
|
||||
void register_link(const astring &sin, const astring &sout);
|
||||
|
||||
net_output_t &find_output(const astring &outname_in);
|
||||
net_param_t &find_param(const astring ¶m_in);
|
||||
|
||||
void register_callback(const astring &devname, netlist_output_delegate delegate);
|
||||
|
||||
void parse(char *buf);
|
||||
|
||||
void resolve_inputs(void);
|
||||
void step_devices_once(void);
|
||||
|
||||
/* not ideal, but needed for save_state */
|
||||
tagmap_terminal_t m_terminals;
|
||||
|
||||
void print_stats();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
netlist_base_t &m_netlist;
|
||||
|
||||
tagmap_devices_t m_devices;
|
||||
tagmap_astring_t m_alias;
|
||||
//tagmap_input_t m_inputs;
|
||||
tagmap_param_t m_params;
|
||||
tagmap_astring_t m_links;
|
||||
|
||||
net_output_t *find_output_exact(const astring &outname_in);
|
||||
const astring &resolve_alias(const astring &name) const;
|
||||
};
|
||||
|
||||
#endif /* NLSETUP_H_ */
|
99
src/emu/netlist/nl_time.h
Normal file
99
src/emu/netlist/nl_time.h
Normal file
@ -0,0 +1,99 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* nltime.h
|
||||
*/
|
||||
|
||||
#ifndef NLTIME_H_
|
||||
#define NLTIME_H_
|
||||
|
||||
#include "nl_config.h"
|
||||
|
||||
//============================================================
|
||||
// MACROS
|
||||
//============================================================
|
||||
|
||||
#define NLTIME_FROM_NS(_t) netlist_time::from_nsec(_t)
|
||||
#define NLTIME_FROM_US(_t) netlist_time::from_usec(_t)
|
||||
#define NLTIME_FROM_MS(_t) netlist_time::from_msec(_t)
|
||||
#define NLTIME_IMMEDIATE netlist_time::from_nsec(0)
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// net_list_time
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
struct netlist_time
|
||||
{
|
||||
public:
|
||||
|
||||
typedef UINT64 INTERNALTYPE;
|
||||
|
||||
static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
|
||||
|
||||
ATTR_HOT inline netlist_time() : m_time(0) {}
|
||||
|
||||
ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
|
||||
ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
|
||||
|
||||
ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
|
||||
ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
|
||||
|
||||
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
|
||||
|
||||
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
|
||||
ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
|
||||
ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
|
||||
|
||||
static const netlist_time zero;
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
|
||||
|
||||
INTERNALTYPE m_time;
|
||||
};
|
||||
|
||||
ATTR_HOT inline const netlist_time operator-(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time - right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_time operator*(const netlist_time &left, const UINT32 factor)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time * factor);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_time operator+(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time + right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time < right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time > right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time <= right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time >= right.m_time);
|
||||
}
|
||||
|
||||
|
||||
#endif /* NLTIME_H_ */
|
@ -18,7 +18,7 @@ TODO:
|
||||
|
||||
#include "machine/rescap.h"
|
||||
#include "machine/netlist.h"
|
||||
#include "netlist/net_lib.h"
|
||||
#include "netlist/devices/net_lib.h"
|
||||
#include "sound/dac.h"
|
||||
#include "video/fixfreq.h"
|
||||
#include "astring.h"
|
||||
@ -562,8 +562,8 @@ void pong_state::machine_reset()
|
||||
|
||||
void pong_state::video_start()
|
||||
{
|
||||
m_maincpu->setup().register_callback("sound_cb", net_output_delegate(&pong_state::sound_cb, "pong_state::sound_cb", this));
|
||||
m_maincpu->setup().register_callback("video_cb", net_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
|
||||
m_maincpu->setup().register_callback("sound_cb", netlist_output_delegate(&pong_state::sound_cb, "pong_state::sound_cb", this));
|
||||
m_maincpu->setup().register_callback("video_cb", netlist_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user