Updated netlist implementation:

- Now supports any resolution fitting reasonably into a UINT64
- Execution now uses a list sorted by execution time
- Implementation now supports analog and digital inputs / outputs
  - First step in a move to "terminals" being both input / output
- Improved object model

Pong:
- Rewrote video code, now emulates a monitor by analyzing the analog
  video signal and identifying vsync and hysnc pulses.
- Removed all hacks.

Overall performance increase of about 10% over the previous "pongf" implementation.
This commit is contained in:
Couriersud 2012-08-20 19:17:31 +00:00
parent 4a73f8bcfb
commit 5280005bfa
5 changed files with 2045 additions and 1134 deletions

File diff suppressed because it is too large Load Diff

View File

@ -54,12 +54,14 @@
// Special chips // Special chips
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
#define NETDEV_CONST(_name, _v) \ #define NETDEV_CLOCK(_name) \
NET_REGISTER_DEV(netdev_const, _name) \ NET_REGISTER_DEV(netdev_clock, _name) \
NETDEV_PARAM(_name.CONST, _v) \
#define NETDEV_INPUT(_name) \ #define NETDEV_LOGIC_INPUT(_name) \
NET_REGISTER_DEV(netdev_input, _name) \ NET_REGISTER_DEV(netdev_logic_input, _name) \
#define NETDEV_ANALOG_INPUT(_name) \
NET_REGISTER_DEV(netdev_analog_input, _name) \
#define NETDEV_CALLBACK(_name, _IN) \ #define NETDEV_CALLBACK(_name, _IN) \
NET_REGISTER_DEV(netdev_callback, _name) \ NET_REGISTER_DEV(netdev_callback, _name) \
@ -92,7 +94,7 @@
#define TTL_7402_NOR(_name, _I1, _I2) \ #define TTL_7402_NOR(_name, _I1, _I2) \
NET_REGISTER_DEV(nic7402, _name) \ NET_REGISTER_DEV(nic7402, _name) \
NET_CONNECT(_name, I1, _I1) \ NET_CONNECT(_name, I1, _I1) \
NET_CONNECT(_name, I2, _I2) \ NET_CONNECT(_name, I2, _I2) \
#define TTL_7404_INVERT(_name, _I1) \ #define TTL_7404_INVERT(_name, _I1) \
@ -145,7 +147,7 @@
#define TTL_7486_XOR(_name, _I1, _I2) \ #define TTL_7486_XOR(_name, _I1, _I2) \
NET_REGISTER_DEV(nic7486, _name) \ NET_REGISTER_DEV(nic7486, _name) \
NET_CONNECT(_name, I1, _I1) \ NET_CONNECT(_name, I1, _I1) \
NET_CONNECT(_name, I2, _I2) \ NET_CONNECT(_name, I2, _I2) \
#define TTL_7448(_name, _A0, _A1, _A2, _A3, _LTQ, _BIQ, _RBIQ) \ #define TTL_7448(_name, _A0, _A1, _A2, _A3, _LTQ, _BIQ, _RBIQ) \
@ -185,9 +187,10 @@
NET_CONNECT(_name, R91, _R91) \ NET_CONNECT(_name, R91, _R91) \
NET_CONNECT(_name, R92, _R92) \ NET_CONNECT(_name, R92, _R92) \
#define TTL_7493(_name, _CLK, _R1, _R2) \ #define TTL_7493(_name, _CLKA, _CLKB, _R1, _R2) \
NET_REGISTER_DEV(nic7493, _name) \ NET_REGISTER_DEV(nic7493, _name) \
NET_CONNECT(_name, CLK, _CLK) \ NET_CONNECT(_name, CLKA, _CLKA) \
NET_CONNECT(_name, CLKB, _CLKB) \
NET_CONNECT(_name, R1, _R1) \ NET_CONNECT(_name, R1, _R1) \
NET_CONNECT(_name, R2, _R2) \ NET_CONNECT(_name, R2, _R2) \
@ -198,7 +201,7 @@
NET_CONNECT(_name, K, _K) \ NET_CONNECT(_name, K, _K) \
NET_CONNECT(_name, CLRQ, _CLRQ) \ NET_CONNECT(_name, CLRQ, _CLRQ) \
#define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \ #define TTL_74107(_name, _CLK, _J, _K, _CLRQ) \
TTL_74107A(_name, _CLK, _J, _K, _CLRQ) TTL_74107A(_name, _CLK, _J, _K, _CLRQ)
#define TTL_74153(_name, _A1, _A2, _A3, _A4, _A, _B, _GA) \ #define TTL_74153(_name, _A1, _A2, _A3, _A4, _A, _B, _GA) \
@ -224,46 +227,50 @@
NET_CONNECT(_name, D, _D) \ NET_CONNECT(_name, D, _D) \
#define NE555N_MSTABLE(_name, _TRIG) \ #define NE555N_MSTABLE(_name, _TRIG, _CV) \
NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \ NET_REGISTER_DEV(nicNE555N_MSTABLE, _name) \
NET_CONNECT(_name, TRIG, _TRIG) \ NET_CONNECT(_name, TRIG, _TRIG) \
NET_CONNECT(_name, CV, _CV) \
#define NETDEV_MIXER3(_name, _I1, _I2, _I3) \
NET_REGISTER_DEV(nicMixer8, _name) \
NET_CONNECT(_name, I1, _I1) \
NET_CONNECT(_name, I2, _I2) \
NET_CONNECT(_name, I3, _I3) \
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Special support devices ... // Special support devices ...
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
NETLIB_DEVICE_WITH_PARAMS(netdev_const, NETLIB_DEVICE(netdev_logic_input,
net_output_t m_Q; ttl_output_t m_Q;
net_param_t m_const;
); );
NETLIB_DEVICE(netdev_input, NETLIB_DEVICE(netdev_analog_input,
net_output_t m_Q; analog_output_t m_Q;
); );
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Special devices ... // Special devices ...
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
/* This class is an artificial delay circuit delaying a signal until the next low to high transition
* this is needed by pong to model delays in the hblank circuit
*/
NETLIB_DEVICE(netdev_delay_lh, NETLIB_DEVICE_WITH_PARAMS(netdev_clock,
net_input_t m_clk; ttl_input_t m_feedback;
net_input_t m_D; ttl_output_t m_Q;
net_sig_t m_lastclk; net_param_t m_freq;
netlist_time m_inc;
net_output_t m_Q;
); );
NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch, NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch,
net_input_t m_I[8]; analog_input_t m_I[8];
net_output_t m_Q; analog_output_t m_Q;
net_output_t m_low; analog_output_t m_low;
net_param_t m_POS; net_param_t m_POS;
@ -271,11 +278,22 @@ NETLIB_DEVICE_WITH_PARAMS(nicMultiSwitch,
); );
NETLIB_DEVICE(nicRSFF, NETLIB_DEVICE(nicRSFF,
net_input_t m_S; ttl_input_t m_S;
net_input_t m_R; ttl_input_t m_R;
net_output_t m_Q; ttl_output_t m_Q;
net_output_t m_QQ; ttl_output_t m_QQ;
);
NETLIB_DEVICE_WITH_PARAMS(nicMixer8,
analog_input_t m_I[8];
analog_output_t m_Q;
analog_output_t m_low;
net_param_t m_R[8];
double m_w[8];
); );
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -284,186 +302,252 @@ NETLIB_DEVICE(nicRSFF,
NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE, NETLIB_DEVICE_WITH_PARAMS(nicNE555N_MSTABLE,
ATTR_HOT void timer_cb(INT32 timer_id); //ATTR_HOT void timer_cb(INT32 timer_id);
net_input_t m_trigger; analog_input_t m_trigger;
analog_input_t m_CV;
analog_input_t m_THRESHOLD; /* internal */
UINT8 m_last; bool m_last;
UINT8 m_fired;
double m_time;
net_output_t m_Q; analog_output_t m_Q;
analog_output_t m_THRESHOLD_OUT; /* internal */
netlist_base_timer_t *m_timer; //netlist_base_timer_t *m_timer;
net_param_t m_R; net_param_t m_R;
net_param_t m_C; net_param_t m_C;
net_param_t m_VS; net_param_t m_VS;
net_param_t m_VL; net_param_t m_VL;
net_param_t m_VT;
); );
NETLIB_SIGNAL(nic7400, 2) NETLIB_SIGNAL(nic7400, 2, 0)
NETLIB_SIGNAL(nic7402, 2) NETLIB_SIGNAL(nic7402, 2, 1)
NETLIB_SIGNAL(nic7404, 1) NETLIB_SIGNAL(nic7410, 3, 0)
NETLIB_SIGNAL(nic7410, 3) NETLIB_SIGNAL(nic7420, 4, 0)
NETLIB_SIGNAL(nic7420, 4) NETLIB_SIGNAL(nic7425, 4, 1)
NETLIB_SIGNAL(nic7425, 4) NETLIB_SIGNAL(nic7427, 3, 1)
NETLIB_SIGNAL(nic7427, 3) NETLIB_SIGNAL(nic7430, 8, 0)
NETLIB_SIGNAL(nic7430, 8)
NETLIB_SIGNAL(nic7450, 4)
NETLIB_DEVICE(nic7404,
ttl_input_t m_I;
ttl_output_t m_Q;
);
NETLIB_DEVICE(nic7450,
ttl_input_t m_I0;
ttl_input_t m_I1;
ttl_input_t m_I2;
ttl_input_t m_I3;
ttl_output_t m_Q;
);
#if 0
NETLIB_DEVICE(nic7474, NETLIB_DEVICE(nic7474,
net_input_t m_clk; ttl_input_t m_clk;
net_input_t m_D; ttl_input_t m_D;
net_input_t m_clrQ; ttl_input_t m_clrQ;
net_input_t m_preQ; ttl_input_t m_preQ;
net_sig_t m_lastclk; net_sig_t m_lastclk;
net_output_t m_Q; ttl_output_t m_Q;
net_output_t m_QQ; ttl_output_t m_QQ;
); );
NETLIB_SIGNAL(nic7486, 2) #else
NETLIB_SUBDEVICE(nic7474sub,
ttl_input_t m_clk;
UINT8 m_nextD;
ttl_output_t m_Q;
ttl_output_t m_QQ;
);
NETLIB_DEVICE(nic7474,
nic7474sub sub;
ttl_input_t m_D;
ttl_input_t m_clrQ;
ttl_input_t m_preQ;
);
#endif
NETLIB_DEVICE(nic7486,
ttl_input_t m_I0;
ttl_input_t m_I1;
ttl_output_t m_Q;
);
/* 74107 does latch data during high ! /* 74107 does latch data during high !
* For modelling purposes, we assume 74107 and 74107A are the same * For modelling purposes, we assume 74107 and 74107A are the same
*/ */
NETLIB_SUBDEVICE(nic74107Asub,
ttl_input_t m_clk;
UINT8 m_Q1;
UINT8 m_Q2;
UINT8 m_F;
ttl_output_t m_Q;
ttl_output_t m_QQ;
);
NETLIB_DEVICE(nic74107A, NETLIB_DEVICE(nic74107A,
net_input_t m_clk; nic74107Asub sub;
net_input_t m_J;
net_input_t m_K;
net_input_t m_clrQ;
net_sig_t m_lastclk; ttl_input_t m_J;
ttl_input_t m_K;
ttl_input_t m_clrQ;
net_output_t m_Q;
net_output_t m_QQ;
); );
class nic74107 : public nic74107A class nic74107 : public nic74107A
{ {
public: public:
nic74107(netlist_setup_t *parent, const char *name) nic74107()
: nic74107A(parent, name) {} : nic74107A() {}
}; };
NETLIB_SUBDEVICE(nic7493ff,
ttl_input_t m_I;
ttl_output_t m_Q;
UINT8 m_active;
);
#if 1
NETLIB_DEVICE(nic7493,
ttl_input_t m_R1;
ttl_input_t m_R2;
nic7493ff A;
nic7493ff B;
nic7493ff C;
nic7493ff D;
);
#else
NETLIB_DEVICE(nic7493, NETLIB_DEVICE(nic7493,
ATTR_HOT void update_outputs(); ATTR_HOT void update_outputs();
net_input_t m_R1; ttl_input_t m_clk;
net_input_t m_R2; ttl_input_t m_R1;
net_input_t m_clk; ttl_input_t m_R2;
ttl_output_t m_QA;
ttl_output_t m_QB;
ttl_output_t m_QC;
ttl_output_t m_QD;
UINT8 m_lastclk;
UINT8 m_cnt; UINT8 m_cnt;
net_output_t m_QA;
net_output_t m_QB;
net_output_t m_QC;
net_output_t m_QD;
); );
#endif
NETLIB_DEVICE(nic7490, NETLIB_DEVICE(nic7490,
ATTR_HOT void update_outputs(); ATTR_HOT void update_outputs();
net_input_t m_R1; ttl_input_t m_R1;
net_input_t m_R2; ttl_input_t m_R2;
net_input_t m_R91; ttl_input_t m_R91;
net_input_t m_R92; ttl_input_t m_R92;
net_input_t m_clk; ttl_input_t m_clk;
net_sig_t m_lastclk;
UINT8 m_cnt; UINT8 m_cnt;
net_output_t m_QA; ttl_output_t m_QA;
net_output_t m_QB; ttl_output_t m_QB;
net_output_t m_QC; ttl_output_t m_QC;
net_output_t m_QD; ttl_output_t m_QD;
); );
/* ripple-carry counter on low-high clock transition */ /* ripple-carry counter on low-high clock transition */
NETLIB_DEVICE(nic9316,
NETLIB_SUBDEVICE(nic9316sub,
ATTR_HOT void update_outputs_all(); ATTR_HOT void update_outputs_all();
ATTR_HOT void update_outputs(); ATTR_HOT void update_outputs();
net_input_t m_clk; ttl_input_t m_clk;
net_input_t m_ENP;
net_input_t m_ENT; ttl_input_t m_LOADQ;
net_input_t m_CLRQ; ttl_input_t m_ENT;
net_input_t m_LOADQ; ttl_input_t m_A;
net_input_t m_A; ttl_input_t m_B;
net_input_t m_B; ttl_input_t m_C;
net_input_t m_C; ttl_input_t m_D;
net_input_t m_D;
UINT8 m_lastclk;
UINT8 m_cnt; UINT8 m_cnt;
net_output_t m_QA; ttl_output_t m_QA;
net_output_t m_QB; ttl_output_t m_QB;
net_output_t m_QC; ttl_output_t m_QC;
net_output_t m_QD; ttl_output_t m_QD;
net_output_t m_RC; ttl_output_t m_RC;
);
NETLIB_DEVICE(nic9316,
nic9316sub sub;
ttl_input_t m_ENP;
ttl_input_t m_CLRQ;
); );
NETLIB_DEVICE(nic7483, NETLIB_DEVICE(nic7483,
net_input_t m_CI; ttl_input_t m_CI;
net_input_t m_A1; ttl_input_t m_A1;
net_input_t m_A2; ttl_input_t m_A2;
net_input_t m_A3; ttl_input_t m_A3;
net_input_t m_A4; ttl_input_t m_A4;
net_input_t m_B1; ttl_input_t m_B1;
net_input_t m_B2; ttl_input_t m_B2;
net_input_t m_B3; ttl_input_t m_B3;
net_input_t m_B4; ttl_input_t m_B4;
net_input_t m_clk; ttl_input_t m_clk;
UINT8 m_lastr; UINT8 m_lastr;
net_output_t m_SA; ttl_output_t m_SA;
net_output_t m_SB; ttl_output_t m_SB;
net_output_t m_SC; ttl_output_t m_SC;
net_output_t m_SD; ttl_output_t m_SD;
net_output_t m_CO; ttl_output_t m_CO;
); );
/* one half of a nic74153 */ /* one half of a nic74153 */
NETLIB_DEVICE(nic74153, NETLIB_DEVICE(nic74153,
net_input_t m_I[4]; ttl_input_t m_I[4];
net_input_t m_A; ttl_input_t m_A;
net_input_t m_B; ttl_input_t m_B;
net_input_t m_GA; ttl_input_t m_GA;
net_output_t m_AY; ttl_output_t m_AY;
); );
NETLIB_DEVICE(nic7448, NETLIB_DEVICE(nic7448,
static const UINT8 tab7448[16][7]; static const UINT8 tab7448[16][7];
net_input_t m_A0; ttl_input_t m_A0;
net_input_t m_A1; ttl_input_t m_A1;
net_input_t m_A2; ttl_input_t m_A2;
net_input_t m_A3; ttl_input_t m_A3;
net_input_t m_LTQ; ttl_input_t m_LTQ;
net_input_t m_RBIQ; ttl_input_t m_RBIQ;
net_input_t m_BIQ; ttl_input_t m_BIQ;
UINT8 m_state; UINT8 m_state;
net_output_t m_a; ttl_output_t m_a;
net_output_t m_b; ttl_output_t m_b;
net_output_t m_c; ttl_output_t m_c;
net_output_t m_d; ttl_output_t m_d;
net_output_t m_e; ttl_output_t m_e;
net_output_t m_f; ttl_output_t m_f;
net_output_t m_g; ttl_output_t m_g;
); );

View File

@ -42,10 +42,10 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
****************************************************************************/ ****************************************************************************/
#include "netlist.h" #include "netlist.h"
#include "net_lib.h"
//============================================================ //============================================================
// DEBUGGING // DEBUGGING
@ -54,11 +54,6 @@
#define VERBOSE (0) #define VERBOSE (0)
#define KEEP_STATISTICS (0) #define KEEP_STATISTICS (0)
#if KEEP_STATISTICS && USE_DELEGATES
#error "Statistics only work without delegates!"
#endif
#if (VERBOSE) #if (VERBOSE)
#define VERBOSE_OUT(x) printf x #define VERBOSE_OUT(x) printf x
@ -71,9 +66,9 @@
//============================================================ //============================================================
#if KEEP_STATISTICS #if KEEP_STATISTICS
#define add_to_stat(v,x) do { atomic_add32((v), (x)); } while (0) #define add_to_stat(v,x) do { v += (x); } while (0)
#define inc_stat(v) add_to_stat(v, 1) #define inc_stat(v) add_to_stat(v, 1)
#define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0) #define begin_timing(v) do { (v) -= get_profile_ticks(); } while (0)
#define end_timing(v) do { (v) += get_profile_ticks(); } while (0) #define end_timing(v) do { (v) += get_profile_ticks(); } while (0)
#else #else
#define add_to_stat(v,x) do { } while (0) #define add_to_stat(v,x) do { } while (0)
@ -82,6 +77,9 @@
#define end_timing(v) do { } while (0) #define end_timing(v) do { } while (0)
#endif #endif
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// A netlist parser // A netlist parser
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -103,86 +101,96 @@ public:
n = getname('('); n = getname('(');
VERBOSE_OUT(("Parser: Device: %s\n", n)); VERBOSE_OUT(("Parser: Device: %s\n", n));
if (strcmp(n,"NET_ALIAS") == 0) if (strcmp(n,"NET_ALIAS") == 0)
{ net_alias();
char *alias;
char *out;
m_p++;
skipws();
alias = getname(',');
m_p++;
skipws();
out = getname(')');
m_p++;
VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out));
m_setup.register_alias(alias, out);
}
else if (strcmp(n,"NETDEV_PARAM") == 0) else if (strcmp(n,"NETDEV_PARAM") == 0)
{ netdev_param();
char *param; else if ((strcmp(n,"NETDEV_TTL_CONST") == 0) || (strcmp(n,"NETDEV_ANALOG_CONST") == 0))
double val; netdev_const(n);
m_p++;
skipws();
param = getname(',');
m_p++;
skipws();
val = eval_param();
m_p++;
VERBOSE_OUT(("Parser: Param: %s %f\n", param, val));
m_setup.find_param(param)->setTo(val);
}
else if (strcmp(n,"NETDEV_CONST") == 0)
{
char *devname;
net_dev_t *dev;
char paramfq[30];
double val;
m_p++;
skipws();
devname = getname(',');
dev = net_create_device_by_name(n, &m_setup, devname);
m_setup.register_dev(dev);
m_p++;
skipws();
val = eval_param();
m_p++;
strcpy(paramfq, devname);
strcat(paramfq, ".CONST");
VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val));
m_setup.find_param(paramfq)->setTo(val);
}
else else
{ netdev_device(n);
char *devname;
net_dev_t *dev;
int cnt;
m_p++;
skipws();
devname = getname2(',', ')');
dev = net_create_device_by_name(n, &m_setup, devname);
m_setup.register_dev(dev);
skipws();
VERBOSE_OUT(("Parser: IC: %s\n", n));
cnt = 0;
while (*m_p != ')')
{
m_p++;
skipws();
n = getname2(',', ')');
VERBOSE_OUT(("Parser: ID: %s %s\n", n, dev->m_inputs.item(cnt)));
m_setup.register_link(dev->m_inputs.item(cnt), n);
skipws();
cnt++;
//return 0;
}
if (cnt != dev->m_inputs.count() && !dev->variable_input_count())
fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname, dev->m_inputs.count(), cnt);
m_p++;
}
} }
} }
void net_alias()
{
char *alias;
char *out;
skipws();
alias = getname(',');
skipws();
out = getname(')');
VERBOSE_OUT(("Parser: Alias: %s %s\n", alias, out));
m_setup.register_alias(alias, out);
}
void netdev_param()
{
char *param;
double val;
skipws();
param = getname(',');
skipws();
val = eval_param();
VERBOSE_OUT(("Parser: Param: %s %f\n", param, val));
m_setup.find_param(param).initial(val);
check_char(')');
}
void netdev_const(const char *dev_name)
{
char *devname;
net_device_t *dev;
char paramfq[30];
double val;
skipws();
devname = getname(',');
dev = net_create_device_by_name(dev_name, &m_setup, devname);
m_setup.register_dev(dev);
skipws();
val = eval_param();
check_char(')');
strcpy(paramfq, devname);
strcat(paramfq, ".CONST");
VERBOSE_OUT(("Parser: Const: %s %f\n", devname, val));
m_setup.find_param(paramfq).setTo(val);
}
void netdev_device(const char *dev_type)
{
char *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();
VERBOSE_OUT(("Parser: IC: %s\n", n));
cnt = 0;
while (*m_p != ')')
{
m_p++;
skipws();
char *output_name = getname2(',', ')');
VERBOSE_OUT(("Parser: ID: %s %s\n", output_name, dev->m_inputs.item(cnt)));
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, dev->m_inputs.count(), cnt);
check_char(')');
}
private: private:
char *cdup(const char *s)
{
return core_strdup(s);
}
void skipeol() void skipeol()
{ {
while (*m_p) while (*m_p)
@ -190,6 +198,8 @@ private:
if (*m_p == 10) if (*m_p == 10)
{ {
m_p++; m_p++;
if (*m_p && *m_p == 13)
m_p++;
return; return;
} }
m_p++; m_p++;
@ -226,7 +236,8 @@ private:
while (*m_p != sep) while (*m_p != sep)
*p1++ = *m_p++; *p1++ = *m_p++;
*p1 = 0; *p1 = 0;
return core_strdup(buf); m_p++;
return cdup(buf);
} }
char *getname2(char sep1, char sep2) char *getname2(char sep1, char sep2)
@ -237,7 +248,18 @@ private:
while ((*m_p != sep1) && (*m_p != sep2)) while ((*m_p != sep1) && (*m_p != sep2))
*p1++ = *m_p++; *p1++ = *m_p++;
*p1 = 0; *p1 = 0;
return core_strdup(buf); return cdup(buf);
}
void check_char(char ctocheck)
{
skipws();
if (*m_p == ctocheck)
{
m_p++;
return;
}
fatalerror("Parser: expected '%c' found '%c'", ctocheck, *m_p);
} }
double eval_param() double eval_param()
@ -255,7 +277,7 @@ private:
f = i; f = i;
ret = strtod(s+strlen(macs[f]), &e); ret = strtod(s+strlen(macs[f]), &e);
if ((f>0) && (*e != ')')) if ((f>0) && (*e != ')'))
exit(0); fatalerror("Parser: Error with parameter ...");
if (f>0) if (f>0)
e++; e++;
m_p = e; m_p = e;
@ -268,83 +290,142 @@ private:
}; };
// ----------------------------------------------------------------------------------------
// 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_always(in_proxied.object_type(SIGNAL_MASK) == SIGNAL_DIGITAL, "Digital signal expected");
m_I.m_high_thresh_V = in_proxied.m_high_thresh_V;
m_I.m_low_thresh_V = in_proxied.m_low_thresh_V;
}
ATTR_HOT void update()
{
if (m_I.Q_Analog() > m_I.m_high_thresh_V)
m_Q.setToPS(1, NLTIME_FROM_NS(1));
else if (m_I.Q_Analog() < m_I.m_low_thresh_V)
m_Q.setToPS(0, NLTIME_FROM_NS(1));
}
ATTR_COLD void start()
{
m_I.init(this);
m_Q.set_netdev(this);
m_Q.initial(1);
}
analog_input_t m_I;
ttl_output_t m_Q;
};
// ----------------------------------------------------------------------------------------
// 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)
{
m_Q.setToPS(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());
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// netlist_base_t // netlist_base_t
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
netlist_base_t::netlist_base_t(bool sub_cycle_exact) netlist_base_t::netlist_base_t()
//m_output_list(ttl_list_t<output_t *>(2048)), //m_output_list(ttl_list_t<output_t *>(2048)),
: m_current(0), m_divisor(32), m_sub_cycle_exact(sub_cycle_exact), m_gatedelay(100), m_clockfreq(1000000) //: m_divisor(32), m_gatedelay(100), m_clockfreq(1000000)
: m_div(1024)
{ {
m_netlist_mask = NET_LIST_MASK;
reset_lists();
} }
netlist_base_t::~netlist_base_t() netlist_base_t::~netlist_base_t()
{ {
} }
void netlist_base_t::set_clock_freq(int clockfreq) void netlist_base_t::set_clock_freq(UINT64 clockfreq)
{ {
m_clockfreq = clockfreq; m_div = netlist_time::from_hz(clockfreq).as_raw();
m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay; VERBOSE_OUT(("Setting clock %lld and divisor %d\n", clockfreq, m_div));
VERBOSE_OUT(("Divisor %d\n", m_divisor));
} }
void netlist_base_t::set_gatedelay(int gatedelay) ATTR_HOT ATTR_ALIGN void netlist_base_t::process_list(INT32 &atime)
{ {
m_gatedelay = gatedelay;
m_divisor = U64(100000000000) / m_clockfreq / m_gatedelay;
VERBOSE_OUT(("Divisor %d\n", m_divisor));
}
ATTR_HOT inline void netlist_base_t::process_list(void) while ( (atime > 0) && (m_queue.is_not_empty()))
{
net_list_t<net_output_t *, 512> &list = m_output_list[m_sub_cycle_exact ? m_current : 0];
#if 0
net_output_t * RESTRICT * RESTRICT first;
net_output_t * RESTRICT * RESTRICT last;
first = list.first();
last = list.last();
while (first <= last)
{ {
net_output_t * RESTRICT * RESTRICT out = first; queue_t::entry_t e = m_queue.pop();
while (out <= last) netlist_time delta = e.time() - m_time_ps + netlist_time::from_raw(m_rem);
{
(*out)->update_out();
(*out)->update_devs();
out++;
}
first = last + 1;
last = list.last();
}
#else
net_output_t * RESTRICT * RESTRICT out;
out = list.first(); atime -= divu_64x32_rem(delta.as_raw(), m_div, &m_rem);
while (out <= list.last()) m_time_ps = e.time();
e.object()->update_devs();
add_to_stat(m_perf_out_processed, 1);
add_to_stat(m_perf_list_len, m_end);
}
if (atime > 0)
{ {
(*out)->update_out(); m_time_ps += netlist_time::from_raw(atime * m_div);
(*out)->update_devs(); atime = 0;
out++;
} }
#endif
reset_list();
if (m_sub_cycle_exact) if (KEEP_STATISTICS)
m_current = (m_current + 1) & m_netlist_mask; printf("%f\n", (double) m_perf_list_len / (double) m_perf_out_processed);
} }
// ----------------------------------------------------------------------------------------
// Default netlist elements ...
// ----------------------------------------------------------------------------------------
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_setup_t(netlist_base_t &netlist) netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
//m_output_list(ttl_list_t<output_t *>(2048)),
: m_netlist(netlist) : m_netlist(netlist)
{ {
NETLIST_NAME(base)(*this);
} }
netlist_setup_t::~netlist_setup_t() netlist_setup_t::~netlist_setup_t()
@ -352,7 +433,7 @@ netlist_setup_t::~netlist_setup_t()
} }
net_dev_t *netlist_setup_t::register_dev(net_dev_t *dev) net_device_t *netlist_setup_t::register_dev(net_device_t *dev)
{ {
if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE)) if (!(m_devices.add(dev->name(), dev, false)==TMERR_NONE))
fatalerror("Error adding %s to device list\n", dev->name()); fatalerror("Error adding %s to device list\n", dev->name());
@ -378,7 +459,7 @@ static void remove_start_with(T &hm, astring &sw)
void netlist_setup_t::remove_dev(const char *name) void netlist_setup_t::remove_dev(const char *name)
{ {
net_dev_t *dev = m_devices.find(name); net_device_t *dev = m_devices.find(name);
astring temp = name; astring temp = name;
if (dev == NULL) if (dev == NULL)
fatalerror("Device %s does not exist\n", name); fatalerror("Device %s does not exist\n", name);
@ -413,11 +494,10 @@ void netlist_setup_t::register_output(const char *name, net_output_t *out)
fatalerror("Error adding output %s to output list\n", name); fatalerror("Error adding output %s to output list\n", name);
} }
void netlist_setup_t::register_input(const char *name, net_input_t *inp, net_input_type type) void netlist_setup_t::register_input(const char *name, net_input_t *inp)
{ {
net_input_setup_t *setup_inp = new net_input_setup_t(inp, type);
VERBOSE_OUT(("input %s\n", name)); VERBOSE_OUT(("input %s\n", name));
if (!(m_inputs.add(name, setup_inp, false) == TMERR_NONE)) if (!(m_inputs.add(name, inp, false) == TMERR_NONE))
fatalerror("Error adding input %s to input list\n", name); fatalerror("Error adding input %s to input list\n", name);
} }
@ -431,7 +511,7 @@ void netlist_setup_t::register_link(const char *sin, const char *sout)
void netlist_setup_t::register_param(const char *sname, net_param_t *param) void netlist_setup_t::register_param(const char *sname, net_param_t *param)
{ {
astring temp = param->ttl_dev()->name(); astring temp = param->netdev().name();
temp.cat("."); temp.cat(".");
temp.cat(sname); temp.cat(sname);
if (!(m_params.add(temp, param, false)==TMERR_NONE)) if (!(m_params.add(temp, param, false)==TMERR_NONE))
@ -454,7 +534,7 @@ net_output_t *netlist_setup_t::find_output_exact(const char *outname_in)
return ret; return ret;
} }
net_output_t *netlist_setup_t::find_output(const char *outname_in) net_output_t &netlist_setup_t::find_output(const char *outname_in)
{ {
const char *outname = resolve_alias(outname_in); const char *outname = resolve_alias(outname_in);
net_output_t *ret; net_output_t *ret;
@ -471,10 +551,10 @@ net_output_t *netlist_setup_t::find_output(const char *outname_in)
if (ret == NULL) if (ret == NULL)
fatalerror("output %s(%s) not found!", outname_in, outname); fatalerror("output %s(%s) not found!", outname_in, outname);
VERBOSE_OUT(("Found input %s\n", outname)); VERBOSE_OUT(("Found input %s\n", outname));
return ret; return *ret;
} }
net_param_t *netlist_setup_t::find_param(const char *param_in) net_param_t &netlist_setup_t::find_param(const char *param_in)
{ {
const char *outname = resolve_alias(param_in); const char *outname = resolve_alias(param_in);
net_param_t *ret; net_param_t *ret;
@ -483,7 +563,7 @@ net_param_t *netlist_setup_t::find_param(const char *param_in)
if (ret == NULL) if (ret == NULL)
fatalerror("parameter %s(%s) not found!", param_in, outname); fatalerror("parameter %s(%s) not found!", param_in, outname);
VERBOSE_OUT(("Found parameter %s\n", outname)); VERBOSE_OUT(("Found parameter %s\n", outname));
return ret; return *ret;
} }
void netlist_setup_t::resolve_inputs(void) void netlist_setup_t::resolve_inputs(void)
@ -493,39 +573,47 @@ void netlist_setup_t::resolve_inputs(void)
{ {
const astring *sout = entry->object(); const astring *sout = entry->object();
astring sin = entry->tag(); astring sin = entry->tag();
net_input_setup_t *in = m_inputs.find(sin); net_input_t *in = m_inputs.find(sin);
int p = sin.find(".");
const char *devname = sin.substr(0, p);
net_dev_t *dev = m_devices.find(devname);
net_output_t *out = find_output(sout->cstr() );
(*in->inp()).o = GETINPPTR(*out); net_output_t &out = find_output(sout->cstr());
//in->inp()->v = out->Q_ptr(); if (out.object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_ANALOG
if (in->type() == NET_INP_TYPE_ACTIVE) && in->object_type(net_output_t::SIGNAL_MASK) == net_output_t::SIGNAL_DIGITAL)
out->register_con(dev); {
// fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name());
// fatalerror("connecting analog output %s with %s\n", out.netdev()->name(), in->netdev()->name());
netdev_a_to_d_proxy *proxy = new netdev_a_to_d_proxy(*in);
proxy->init(this, "abc");
proxy->start();
in->set_output(proxy->GETINPPTR(proxy->m_Q));
//Next check would not work with dynamic activation
//if (in->state() != net_input_t::INP_STATE_PASSIVE)
proxy->m_Q.register_con(*in);
proxy->m_I.set_output(&out);
//if (proxy->m_I.state() != net_input_t::INP_STATE_PASSIVE)
out.register_con(proxy->m_I);
}
else
{
in->set_output(out.netdev()->GETINPPTR(out));
//Next check would not work with dynamic activation
//if (in->state() != net_input_t::INP_STATE_PASSIVE)
out.register_con(*in);
}
}
/* 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();
} }
step_all_devices(); /* make sure all outputs are triggered once */
//reset_list(); for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
//process_list();
}
void netlist_setup_t::step_all_devices()
{
m_netlist.reset_list();
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
{ {
net_dev_t &dev = *entry->object(); net_output_t *out = entry->object();
dev.update_param(); out->update_devs_force();
dev.update(); INT32 time = 1000;
m_netlist.process_list(time);
for (tagmap_output_t::entry_t *entry = m_outputs.first(); entry != NULL; entry = m_outputs.next(entry))
{
net_output_t &out = *entry->object();
out.update_out();
}
m_netlist.reset_lists();
} }
} }
@ -547,119 +635,238 @@ void netlist_setup_t::print_stats()
} }
// ----------------------------------------------------------------------------------------
// net_core_device_t
// ----------------------------------------------------------------------------------------
net_core_device_t::net_core_device_t()
: net_object_t(DEVICE)
{
}
net_core_device_t::~net_core_device_t()
{
}
ATTR_COLD void net_core_device_t::init_core(netlist_base_t *anetlist, const char *name)
{
m_netlist = anetlist;
m_name = name;
#if USE_DELEGATES_A
h = net_update_delegate(&net_core_device_t::update, "update", this);
#endif
}
ATTR_COLD void net_core_device_t::register_subdevice(net_core_device_t &subdev)
{
m_subdevs.add(&subdev);
subdev.init_core(m_netlist, this->name());
//subdev.start();
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// net_dev_t // net_dev_t
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
net_dev_t::~net_dev_t()
net_device_t::net_device_t()
: net_core_device_t(), m_variable_input_count(false)
{ {
} }
ATTR_HOT void net_dev_t::update_timed() net_device_t::~net_device_t()
{ {
inc_stat(&stat_count);
begin_timing(total_time);
update();
end_timing(total_time);
} }
void net_dev_t::register_output(const char *name, net_output_t *port) ATTR_COLD void net_device_t::init(netlist_setup_t *setup, const char *name)
{ {
astring temp = this->name(); m_setup = setup;
init_core(&setup->netlist(), name);
}
void net_device_t::register_output(const net_core_device_t &dev, const char *name, net_output_t &port)
{
astring temp = dev.name();
temp.cat("."); temp.cat(".");
temp.cat(name); temp.cat(name);
port->set_ttl_dev(this); port.set_netdev(&dev);
m_setup->register_output(temp, port); m_setup->register_output(temp, &port);
} }
void net_dev_t::register_input(const char *name, net_input_t *inp, net_input_type type) void net_device_t::register_output(const char *name, net_output_t &port)
{ {
astring temp = this->name(); register_output(*this, name, port);
}
void net_device_t::register_input(net_core_device_t &dev, const char *name, net_input_t &inp, int type)
{
astring temp = dev.name();
temp.cat("."); temp.cat(".");
temp.cat(name); temp.cat(name);
inp.init(&dev, type);
m_inputs.add(core_strdup(temp.cstr())); m_inputs.add(core_strdup(temp.cstr()));
m_setup->register_input(temp, inp, type); m_setup->register_input(temp, &inp);
} }
void net_dev_t::register_param(const char *name, net_param_t *param, double initialVal) void net_device_t::register_input(const char *name, net_input_t &inp, int type)
{ {
param->set_ttl_dev(this); register_input(*this, name, inp, type);
param->initial(initialVal); }
m_setup->register_param(name, param);
void net_device_t::register_link_internal(net_core_device_t &dev, net_input_t &in, net_output_t &out)
{
in.set_output(GETINPPTR(out));
in.init(&dev);
//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)
{
register_link_internal(*this, in, out);
}
void net_device_t::register_param(net_core_device_t &dev, const char *name, net_param_t &param, double initialVal)
{
param.set_netdev(dev);
param.initial(initialVal);
m_setup->register_param(name, &param);
}
void net_device_t::register_param(const char *name, net_param_t &param, double initialVal)
{
register_param(*this,name, param, initialVal);
}
// ----------------------------------------------------------------------------------------
// net_input_t
// ----------------------------------------------------------------------------------------
ATTR_COLD void net_input_t::init(net_core_device_t *dev, int astate)
{
m_netdev = dev;
m_state = astate;
#if USE_DELEGATES
h = net_update_delegate(&net_core_device_t::update, "update", dev);
#endif
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// net_output_t // net_output_t
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
net_output_t::net_output_t() net_output_t::net_output_t(int atype)
: net_object_t(atype)
{ {
#if USE_DELEGATES m_last_Q = 1;
//m_cons = global_alloc_array_clear(net_update_delegate, 32);
#else
// m_cons = global_alloc_array_clear(net_dev_t *, 32);
#endif
//m_Q = parent.alloc_sig();
//m_new_Q = parent.alloc_sig();
m_num_cons = 0;
m_Q = 0; m_Q = 0;
m_new_Q = m_Q; m_new_Q = m_Q;
m_active = 0;
m_in_queue = 2;
} }
ATTR_COLD void net_output_t::set_ttl_dev(net_dev_t *dev) ATTR_COLD void net_output_t::set_netdev(const net_core_device_t *dev)
{ {
m_ttldev = dev; m_netdev = dev;
m_netlist = &dev->setup()->netlist(); m_netlist = dev->netlist();
} }
static inline void update_dev(const net_input_t *inp, const UINT32 mask)
ATTR_COLD void net_output_t::register_con(net_dev_t *dev)
{ {
assert(m_num_cons<32); if ((inp->state() & mask) != 0)
{
begin_timing(inp->netdev()->total_time);
inc_stat(inp->netdev()->stat_count);
#if USE_DELEGATES #if USE_DELEGATES
net_update_delegate aDelegate = net_update_delegate(&net_dev_t::update, "update", dev); inp->h();
for (int i=0; i < m_num_cons; i++)
if (m_cons[i] == aDelegate)
return;
m_cons[m_num_cons++] = aDelegate;
#else #else
for (int i=0; i < m_num_cons; i++) inp->netdev()->update_device();
if (m_cons[i] == dev)
return;
m_cons[m_num_cons++] = dev;
#endif #endif
end_timing(inp->netdev()->total_time);
}
} }
ATTR_HOT inline void net_output_t::update_devs() ATTR_HOT inline void net_output_t::update_devs()
{ {
#if USE_DELEGATES
net_update_delegate *s = m_cons; const UINT32 masks[4] = { 1, 5, 3, 1 };
net_update_delegate *e = s + m_num_cons; m_Q = m_new_Q;
m_Q_analog = m_new_Q_analog;
while (s<e) //UINT32 mask = 1 | ((m_last_Q & (m_Q ^ 1)) << 1) | (((m_last_Q ^ 1) & m_Q) << 2);
const UINT32 mask = masks[ (m_last_Q << 1) | m_Q ];
switch (m_num_cons)
{ {
(*s++)(); 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);
}
case 0:
break;
} }
#else
net_dev_t **s = m_cons;
net_dev_t **e = s + m_num_cons;
#if KEEP_STATISTICS m_in_queue = 2; /* mark as taken ... */
while (s<e) m_last_Q = m_Q;
(*s++)->update_timed(); }
ATTR_COLD void net_output_t::update_devs_force()
{
net_input_t **s = m_cons;
int i = m_num_cons;
m_Q = m_new_Q;
m_Q_analog = m_new_Q_analog;
while (i-- > 0)
{
if (((*s)->state() & net_input_t::INP_STATE_ACTIVE) != 0)
#if USE_DELEGATES
(*s)->h();
#else #else
while (s<e) (*s)->netdev()->update_device();
(*s++)->update();
#endif #endif
s++;
}
m_last_Q = m_Q;
}
ATTR_COLD void net_output_t::register_con(net_input_t &input)
{
int i;
if (m_num_cons >= ARRAY_LENGTH(m_cons))
fatalerror("Connections exceeded for %s\n", m_netdev->name());
/* keep similar devices together */
for (i = 0; i < m_num_cons; i++)
#if USE_DELEGATES
if (m_cons[i]->h == input.h)
break;
#else
if (m_cons[i]->netdev() == input.netdev())
break;
#endif #endif
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++;
} }
NETLIB_UPDATE(netdev_callback) NETLIB_UPDATE(netdev_callback)
{ {
// FIXME: Remove after device cleanup // FIXME: Remove after device cleanup
if (!m_callback.isnull()) if (!m_callback.isnull())
m_callback(INPVAL(m_in)); m_callback(INPANALOG(m_in));
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -674,17 +881,6 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const ch
: device_t(mconfig, NETLIST, "netlist", tag, owner, clock), : device_t(mconfig, NETLIST, "netlist", tag, owner, clock),
device_execute_interface(mconfig, *this) device_execute_interface(mconfig, *this)
{ {
m_clock = clock;
}
void netlist_mame_device::static_set_subcycles(device_t &device, int subcycles)
{
netlist_mame_device &netlist = downcast<netlist_mame_device &>(device);
assert((subcycles & 1) == 0);
assert( subcycles > 0);
netlist.m_subcycles = subcycles;
} }
void netlist_mame_device::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &)) void netlist_mame_device::static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &))
@ -701,8 +897,8 @@ void netlist_mame_device::device_start()
{ {
//double dt = clocks_to_attotime(1).as_double(); //double dt = clocks_to_attotime(1).as_double();
m_netlist = global_alloc_clear(netlist_t(*this, m_subcycles > 2)); m_netlist = global_alloc_clear(netlist_t(*this));
m_netlist->set_clock_freq(m_clock * m_subcycles); m_netlist->set_clock_freq(this->clock());
m_setup = global_alloc_clear(netlist_setup_t(*m_netlist)); m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
@ -717,18 +913,12 @@ void netlist_mame_device::device_start()
m_setup->resolve_inputs(); m_setup->resolve_inputs();
//m_clockcnt = 0;
m_clock_input = m_setup->find_output("clk");
//save_item(NAME(m_clockcnt)); //save_item(NAME(m_clockcnt));
save_state(); save_state();
/* TODO: we have to save the round robin queue as well */ /* TODO: we have to save the round robin queue as well */
// set our instruction counter // set our instruction counter
m_icountptr = &m_icount; m_icountptr = &m_icount;
m_ss = SubCycles() / 2;
m_clk = 0;
} }
void netlist_mame_device::device_reset() void netlist_mame_device::device_reset()
@ -761,37 +951,25 @@ void netlist_mame_device::save_state()
UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
{ {
return clocks * SubCycles(); return clocks;
} }
UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
{ {
return cycles / SubCycles(); return cycles;
} }
ATTR_HOT void netlist_mame_device::execute_run() ATTR_HOT void netlist_mame_device::execute_run()
{ {
//bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); //bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
osd_ticks_t a = -osd_ticks();
UINT8 ssdiv2 = (SubCycles() / 2); // debugging
//int p = m_icount; //m_ppc = m_pc; // copy PC to previous PC
do //if (check_debugger)
{ // debugger_instruction_hook(this, 0); //m_pc);
// debugging
//m_ppc = m_pc; // copy PC to previous PC m_netlist->process_list(m_icount);
//if (check_debugger)
// debugger_instruction_hook(this, 0); //m_pc);
if (--m_ss == 0)
{
m_ss = ssdiv2;
m_clk = !m_clk;
m_clock_input->setTo(m_clk);
}
m_netlist->process_list();
m_icount--;
} while (m_icount > 0);
a+=osd_ticks();
//printf("%ld %d %ld\n", (long) a, p, (long) (a * 1000 / p));
} }

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ TODO:
* http://www.youtube.com/watch?v=pDrRnJOCKZc * http://www.youtube.com/watch?v=pDrRnJOCKZc
*/ */
#define MASTER_CLOCK 7139000 #define MASTER_CLOCK 7159000
#define V_TOTAL (0x105+1) #define V_TOTAL (0x105+1)
#define H_TOTAL (0x1C6+1) // 454 #define H_TOTAL (0x1C6+1) // 454
@ -55,7 +55,7 @@ TODO:
#define VBSTART (V_TOTAL) #define VBSTART (V_TOTAL)
#define VBEND (16) #define VBEND (16)
#define HRES_MULT (2) #define HRES_MULT (1)
enum input_changed_enum enum input_changed_enum
{ {
@ -64,15 +64,17 @@ enum input_changed_enum
IC_COIN, IC_COIN,
IC_SWITCH, IC_SWITCH,
IC_VR1, IC_VR1,
IC_VR2, IC_VR2
IC_GATEDELAY
}; };
static NETLIST_START(pong_schematics) static NETLIST_START(pong_schematics)
NETDEV_CONST(high, 1) NETDEV_TTL_CONST(high, 1)
NETDEV_CONST(low, 0) NETDEV_TTL_CONST(low, 0)
NETDEV_INPUT(clk) NETDEV_CLOCK(clk)
NETDEV_INPUT(SRST) NETDEV_PARAM(clk.FREQ, 7159000.0)
NETDEV_LOGIC_INPUT(SRST)
NETDEV_ANALOG_INPUT(P1)
NETDEV_ANALOG_INPUT(P2)
TTL_7404_INVERT(hitQ, hit) TTL_7404_INVERT(hitQ, hit)
TTL_7400_NAND(hit, hit1Q, hit2Q) TTL_7400_NAND(hit, hit1Q, hit2Q)
@ -111,9 +113,9 @@ static NETLIST_START(pong_schematics)
TTL_7427_NOR(ic_g2a, ic_g3c.Q, 256HQ, vpad2Q) TTL_7427_NOR(ic_g2a, ic_g3c.Q, 256HQ, vpad2Q)
NET_ALIAS(pad2, ic_g2a.Q) NET_ALIAS(pad2, ic_g2a.Q)
/* horizontal counter */ // horizontal counter
TTL_7493(ic_f8, clk, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */ TTL_7493(ic_f8, clk, ic_f8.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b
TTL_7493(ic_f9, ic_f8.QD, ic_e7b.QQ, ic_e7b.QQ) /* f8, f9, f6b */ TTL_7493(ic_f9, ic_f8.QD, ic_f9.QA, ic_e7b.QQ, ic_e7b.QQ) // f8, f9, f6b
TTL_74107(ic_f6b, ic_f9.QD, high, high, ic_e7b.Q) TTL_74107(ic_f6b, ic_f9.QD, high, high, ic_e7b.Q)
TTL_7430_NAND(ic_f7, ic_f8.QB, ic_f8.QC, ic_f9.QC, ic_f9.QD, ic_f6b.Q, high, high, high) TTL_7430_NAND(ic_f7, ic_f8.QB, ic_f8.QC, ic_f9.QC, ic_f9.QD, ic_f6b.Q, high, high, high)
TTL_7474(ic_e7b, clk, ic_f7, high, high) TTL_7474(ic_e7b, clk, ic_f7, high, high)
@ -129,9 +131,9 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(256H, ic_f6b.Q) NET_ALIAS(256H, ic_f6b.Q)
NET_ALIAS(256HQ, ic_f6b.QQ) NET_ALIAS(256HQ, ic_f6b.QQ)
/* vertical counter */ // vertical counter
TTL_7493(ic_e8, hreset, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */ TTL_7493(ic_e8, hreset, ic_e8.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b
TTL_7493(ic_e9, ic_e8.QD, ic_e7a.QQ, ic_e7a.QQ) /* e8, e9, d9b */ TTL_7493(ic_e9, ic_e8.QD,ic_e9.QA, ic_e7a.QQ, ic_e7a.QQ) // e8, e9, d9b
TTL_74107(ic_d9b, ic_e9.QD, high, high, ic_e7a.Q) TTL_74107(ic_d9b, ic_e9.QD, high, high, ic_e7a.Q)
TTL_7474(ic_e7a, hreset, e7a_data, high, high) TTL_7474(ic_e7a, hreset, e7a_data, high, high)
TTL_7410_NAND(e7a_data, ic_e8.QA, ic_e8.QC, ic_d9b.Q) TTL_7410_NAND(e7a_data, ic_e8.QA, ic_e8.QC, ic_d9b.Q)
@ -147,11 +149,11 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(256VQ, ic_d9b.QQ) NET_ALIAS(256VQ, ic_d9b.QQ)
/* hblank flip flop */ // hblank flip flop
TTL_7400_NAND(ic_g5b, 16H, 64H) TTL_7400_NAND(ic_g5b, 16H, 64H)
/* the time critical one */ // the time critical one
TTL_7400_NAND(ic_h5c, ic_h5b.Q, hresetQ) TTL_7400_NAND(ic_h5c, ic_h5b.Q, hresetQ)
TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b.Q) TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b.Q)
@ -159,7 +161,7 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(hblankQ, ic_h5b.Q) NET_ALIAS(hblankQ, ic_h5b.Q)
TTL_7400_NAND(hsyncQ, hblank, 32H) TTL_7400_NAND(hsyncQ, hblank, 32H)
/* vblank flip flop */ // vblank flip flop
TTL_7402_NOR(ic_f5c, ic_f5d.Q, vreset) TTL_7402_NOR(ic_f5c, ic_f5d.Q, vreset)
TTL_7402_NOR(ic_f5d, ic_f5c.Q, 16V) TTL_7402_NOR(ic_f5d, ic_f5c.Q, 16V)
@ -170,11 +172,11 @@ static NETLIST_START(pong_schematics)
TTL_7410_NAND(ic_g5a, vblank, 4V, ic_h5a.Q) TTL_7410_NAND(ic_g5a, vblank, 4V, ic_h5a.Q)
NET_ALIAS(vsyncQ, ic_g5a.Q) NET_ALIAS(vsyncQ, ic_g5a.Q)
/* move logic */ // move logic
TTL_7400_NAND(ic_e1d, hit_sound, ic_e1c.Q) TTL_7400_NAND(ic_e1d, hit_sound, ic_e1c.Q)
TTL_7400_NAND(ic_e1c, ic_f1.QC, ic_f1.QD) TTL_7400_NAND(ic_e1c, ic_f1.QC, ic_f1.QD)
TTL_7493(ic_f1, ic_e1d.Q, rstspeed, rstspeed) TTL_7493(ic_f1, ic_e1d.Q, ic_f1.QA, rstspeed, rstspeed)
TTL_7402_NOR(ic_g1d, ic_f1.QC, ic_f1.QD) TTL_7402_NOR(ic_g1d, ic_f1.QC, ic_f1.QD)
TTL_7400_NAND(ic_h1a, ic_g1d.Q, ic_g1d.Q) TTL_7400_NAND(ic_h1a, ic_g1d.Q, ic_g1d.Q)
@ -199,7 +201,7 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(Aa, ic_h4c.Q) NET_ALIAS(Aa, ic_h4c.Q)
NET_ALIAS(Ba, ic_h4b.Q) NET_ALIAS(Ba, ic_h4b.Q)
/* hvid circuit */ // hvid circuit
TTL_7400_NAND(hball_resetQ, Serve, attractQ) TTL_7400_NAND(hball_resetQ, Serve, attractQ)
@ -210,19 +212,19 @@ static NETLIST_START(pong_schematics)
TTL_7420_NAND(ic_h6b, ic_g6b.Q, ic_h7.RC, ic_g7.QC, ic_g7.QD) TTL_7420_NAND(ic_h6b, ic_g6b.Q, ic_h7.RC, ic_g7.QC, ic_g7.QD)
NET_ALIAS(hvidQ, ic_h6b.Q) NET_ALIAS(hvidQ, ic_h6b.Q)
/* vvid circuit */ // vvid circuit
TTL_9316(ic_b3, hsyncQ, high, vblankQ, high, ic_b2b.Q, a6, b6, c6, d6) TTL_9316(ic_b3, hsyncQ, high, vblankQ, high, ic_b2b.Q, a6, b6, c6, d6)
TTL_9316(ic_a3, hsyncQ, ic_b3.RC, high, high, ic_b2b.Q, low, low, low, low) TTL_9316(ic_a3, hsyncQ, ic_b3.RC, high, high, ic_b2b.Q, low, low, low, low)
TTL_7400_NAND(ic_b2b, ic_a3.RC, ic_b3.RC) TTL_7400_NAND(ic_b2b, ic_a3.RC, ic_b3.RC)
TTL_7410_NAND(ic_e2b, ic_a3.RC, ic_b3.QC, ic_b3.QD) TTL_7410_NAND(ic_e2b, ic_a3.RC, ic_b3.QC, ic_b3.QD)
NET_ALIAS(vvidQ, ic_e2b.Q) NET_ALIAS(vvidQ, ic_e2b.Q)
TTL_7404_INVERT(vvid, vvidQ) /* D2D */ TTL_7404_INVERT(vvid, vvidQ) // D2D
NET_ALIAS(vpos256, ic_a3.RC) NET_ALIAS(vpos256, ic_a3.RC)
NET_ALIAS(vpos32, ic_a3.QB) NET_ALIAS(vpos32, ic_a3.QB)
NET_ALIAS(vpos16, ic_a3.QA) NET_ALIAS(vpos16, ic_a3.QA)
/* vball ctrl circuit */ // vball ctrl circuit
TTL_7450_ANDORINVERT(ic_a6a, b1, 256HQ, b2, 256H) TTL_7450_ANDORINVERT(ic_a6a, b1, 256HQ, b2, 256H)
TTL_7450_ANDORINVERT(ic_a6b, c1, 256HQ, c2, 256H) TTL_7450_ANDORINVERT(ic_a6b, c1, 256HQ, c2, 256H)
@ -231,7 +233,7 @@ static NETLIST_START(pong_schematics)
TTL_7474(ic_a5b, hit, ic_a6a, attractQ, high) TTL_7474(ic_a5b, hit, ic_a6a, attractQ, high)
TTL_7474(ic_a5a, hit, ic_a6b, attractQ, high) TTL_7474(ic_a5a, hit, ic_a6b, attractQ, high)
TTL_7474(ic_b5a, hit, ic_b6b, attractQ, high) TTL_7474(ic_b5a, hit, ic_b6b, attractQ, high)
TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) /* two marked at position h2a ==> this h2x */ TTL_74107(ic_h2x, vblank, vvid, vvid, hitQ) // two marked at position h2a ==> this h2x
TTL_7486_XOR(ic_a4c, ic_a5b.Q, ic_h2x.Q) TTL_7486_XOR(ic_a4c, ic_a5b.Q, ic_h2x.Q)
TTL_7486_XOR(ic_a4b, ic_a5a.Q, ic_h2x.Q) TTL_7486_XOR(ic_a4b, ic_a5a.Q, ic_h2x.Q)
@ -246,9 +248,9 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(c6, ic_b4.SC) NET_ALIAS(c6, ic_b4.SC)
NET_ALIAS(d6, ic_b4.SD) NET_ALIAS(d6, ic_b4.SD)
/* serve monoflop */ // serve monoflop
TTL_7404_INVERT(f4_trig, rstspeed) TTL_7404_INVERT(f4_trig, rstspeed)
NE555N_MSTABLE(ic_f4_serve, f4_trig) NE555N_MSTABLE(ic_f4_serve, f4_trig, NC)
NETDEV_PARAM(ic_f4_serve.R, RES_K(330)) NETDEV_PARAM(ic_f4_serve.R, RES_K(330))
NETDEV_PARAM(ic_f4_serve.C, CAP_U(4.7)) NETDEV_PARAM(ic_f4_serve.C, CAP_U(4.7))
@ -258,15 +260,15 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(Serve, ic_b5b_serve.QQ) NET_ALIAS(Serve, ic_b5b_serve.QQ)
NET_ALIAS(ServeQ, ic_b5b_serve.Q) NET_ALIAS(ServeQ, ic_b5b_serve.Q)
/* score logic */ // score logic
TTL_7474(ic_h3a, 4H, 128H, high, attractQ) TTL_7474(ic_h3a, 4H, 128H, high, attractQ)
/* sound logic */ // sound logic
TTL_7474(ic_c2a, vpos256, high, hitQ, high) TTL_7474(ic_c2a, vpos256, high, hitQ, high)
TTL_74107(ic_f3_topbot, vblank, vvid, vvidQ, ServeQ) TTL_74107(ic_f3_topbot, vblank, vvid, vvidQ, ServeQ)
NE555N_MSTABLE(ic_g4_sc, MissQ) NE555N_MSTABLE(ic_g4_sc, MissQ, NC)
NET_ALIAS(SC, ic_g4_sc.Q) /* monoflop with NE555 determines score sound */ NET_ALIAS(SC, ic_g4_sc.Q) // monoflop with NE555 determines score sound
NETDEV_PARAM(ic_g4_sc.R, RES_K(220)) NETDEV_PARAM(ic_g4_sc.R, RES_K(220))
NETDEV_PARAM(ic_g4_sc.C, CAP_U(1)) NETDEV_PARAM(ic_g4_sc.C, CAP_U(1))
@ -280,15 +282,15 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(sound, ic_c1b.Q) NET_ALIAS(sound, ic_c1b.Q)
/* paddle1 logic 1 */ // paddle1 logic 1
NE555N_MSTABLE(ic_b9, 256VQ) NE555N_MSTABLE(ic_b9, 256VQ, P1)
NETDEV_PARAM(ic_b9.R, RES_K(90)) NETDEV_PARAM(ic_b9.R, RES_K(90))
NETDEV_PARAM(ic_b9.C, CAP_U(.1)) NETDEV_PARAM(ic_b9.C, CAP_U(.1))
NETDEV_PARAM(ic_b9.VL, 0.7) NETDEV_PARAM(ic_b9.VL, 0.7)
TTL_7404_INVERT(ic_c9b, ic_b9.Q) TTL_7404_INVERT(ic_c9b, ic_b9.Q)
TTL_7400_NAND(ic_b7b, ic_a7b.Q, hsyncQ) TTL_7400_NAND(ic_b7b, ic_a7b.Q, hsyncQ)
TTL_7493(ic_b8, ic_b7b.Q, ic_b9.Q, ic_b9.Q) TTL_7493(ic_b8, ic_b7b.Q, ic_b8.QA, ic_b9.Q, ic_b9.Q)
TTL_7400_NAND(ic_b7a, ic_c9b.Q, ic_a7b.Q) TTL_7400_NAND(ic_b7a, ic_c9b.Q, ic_a7b.Q)
TTL_7420_NAND(ic_a7b, ic_b8.QA, ic_b8.QB, ic_b8.QC, ic_b8.QD) TTL_7420_NAND(ic_a7b, ic_b8.QA, ic_b8.QB, ic_b8.QC, ic_b8.QD)
NET_ALIAS(vpad1Q, ic_b7a.Q) NET_ALIAS(vpad1Q, ic_b7a.Q)
@ -297,15 +299,15 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(c1, ic_b8.QC) NET_ALIAS(c1, ic_b8.QC)
NET_ALIAS(d1, ic_b8.QD) NET_ALIAS(d1, ic_b8.QD)
/* paddle1 logic 2 */ // paddle1 logic 2
NE555N_MSTABLE(ic_a9, 256VQ) NE555N_MSTABLE(ic_a9, 256VQ, P2)
NETDEV_PARAM(ic_a9.R, RES_K(90)) NETDEV_PARAM(ic_a9.R, RES_K(90))
NETDEV_PARAM(ic_a9.C, CAP_U(.1)) NETDEV_PARAM(ic_a9.C, CAP_U(.1))
NETDEV_PARAM(ic_a9.VL, 0.7) NETDEV_PARAM(ic_a9.VL, 0.7)
TTL_7404_INVERT(ic_c9a, ic_a9.Q) TTL_7404_INVERT(ic_c9a, ic_a9.Q)
TTL_7400_NAND(ic_b7c, ic_a7a.Q, hsyncQ) TTL_7400_NAND(ic_b7c, ic_a7a.Q, hsyncQ)
TTL_7493(ic_a8, ic_b7c.Q, ic_a9.Q, ic_a9.Q) TTL_7493(ic_a8, ic_b7c.Q, ic_a8.QA, ic_a9.Q, ic_a9.Q)
TTL_7400_NAND(ic_b7d, ic_c9a.Q, ic_a7a.Q) TTL_7400_NAND(ic_b7d, ic_c9a.Q, ic_a7a.Q)
TTL_7420_NAND(ic_a7a, ic_a8.QA, ic_a8.QB, ic_a8.QC, ic_a8.QD) TTL_7420_NAND(ic_a7a, ic_a8.QA, ic_a8.QB, ic_a8.QC, ic_a8.QD)
NET_ALIAS(vpad2Q, ic_b7d.Q) NET_ALIAS(vpad2Q, ic_b7d.Q)
@ -314,7 +316,7 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(c2, ic_a8.QC) NET_ALIAS(c2, ic_a8.QC)
NET_ALIAS(d2, ic_a8.QD) NET_ALIAS(d2, ic_a8.QD)
/* C5-EN Logic */ // C5-EN Logic
TTL_7404_INVERT(ic_e3a, 128H) TTL_7404_INVERT(ic_e3a, 128H)
TTL_7427_NOR( ic_e3b, 256H, 64H, ic_e3a.Q) TTL_7427_NOR( ic_e3b, 256H, 64H, ic_e3a.Q)
@ -325,14 +327,14 @@ static NETLIST_START(pong_schematics)
TTL_7425_NOR(ic_f2a, ic_g1a.Q, 64V, 128V, ic_d2c.Q) TTL_7425_NOR(ic_f2a, ic_g1a.Q, 64V, 128V, ic_d2c.Q)
NET_ALIAS(c5-en, ic_f2a.Q) NET_ALIAS(c5-en, ic_f2a.Q)
/* Score logic ... */ // Score logic ...
TTL_7402_NOR(ic_f5b, L, Missed) TTL_7402_NOR(ic_f5b, L, Missed)
TTL_7490(ic_c7, ic_f5b, SRST, SRST, low, low) TTL_7490(ic_c7, ic_f5b, SRST, SRST, low, low)
TTL_74107(ic_c8a, ic_c7.QD, high, high, SRSTQ) TTL_74107(ic_c8a, ic_c7.QD, high, high, SRSTQ)
NETDEV_SWITCH2(sw1a, high, ic_c7.QC) NETDEV_SWITCH2(sw1a, high, ic_c7.QC)
NETDEV_PARAM(sw1a.POS, 0) NETDEV_PARAM(sw1a.POS, 0)
TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */ TTL_7410_NAND(ic_d8a, ic_c7.QA, sw1a.Q, ic_c8a.Q) // would be nand2 for 11 instead of 15 points, need a switch dev!
NET_ALIAS(StopG1Q, ic_d8a.Q) NET_ALIAS(StopG1Q, ic_d8a.Q)
NET_ALIAS(score1_1, ic_c7.QA) NET_ALIAS(score1_1, ic_c7.QA)
@ -347,7 +349,7 @@ static NETLIST_START(pong_schematics)
TTL_74107(ic_c8b, ic_d7.QD, high, high, SRSTQ) TTL_74107(ic_c8b, ic_d7.QD, high, high, SRSTQ)
NETDEV_SWITCH2(sw1b, high, ic_d7.QC) NETDEV_SWITCH2(sw1b, high, ic_d7.QC)
NETDEV_PARAM(sw1b.POS, 0) NETDEV_PARAM(sw1b.POS, 0)
TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) /* would be nand2 for 11 instead of 15 points, need a switch dev! */ TTL_7410_NAND(ic_d8b, ic_d7.QA, sw1b.Q, ic_c8b.Q) // would be nand2 for 11 instead of 15 points, need a switch dev!
NET_ALIAS(StopG2Q, ic_d8b.Q) NET_ALIAS(StopG2Q, ic_d8b.Q)
NET_ALIAS(score2_1, ic_d7.QA) NET_ALIAS(score2_1, ic_d7.QA)
@ -357,7 +359,7 @@ static NETLIST_START(pong_schematics)
NET_ALIAS(score2_10, ic_c8b.Q) NET_ALIAS(score2_10, ic_c8b.Q)
NET_ALIAS(score2_10Q, ic_c8b.QQ) NET_ALIAS(score2_10Q, ic_c8b.QQ)
/* Score display */ // Score display
TTL_74153(ic_d6a, score1_10Q, score1_4, score2_10Q, score2_4, 32H, 64H, low) TTL_74153(ic_d6a, score1_10Q, score1_4, score2_10Q, score2_4, 32H, 64H, low)
TTL_74153(ic_d6b, score1_10Q, score1_8, score2_10Q, score2_8, 32H, 64H, low) TTL_74153(ic_d6b, score1_10Q, score1_8, score2_10Q, score2_8, 32H, 64H, low)
@ -395,18 +397,26 @@ static NETLIST_START(pong_schematics)
TTL_7430_NAND(ic_d3, ic_d4a, ic_d5c, ic_c4c, ic_d5a, ic_d4c, ic_d4b, ic_d5b, high) TTL_7430_NAND(ic_d3, ic_d4a, ic_d5c, ic_c4c, ic_d5a, ic_d4c, ic_d4b, ic_d5b, high)
NET_ALIAS(score, ic_d3.Q) //FIXME NET_ALIAS(score, ic_d3.Q) //FIXME
/* net */ // net
TTL_74107(ic_f3b, clk, 256H, 256HQ, high) TTL_74107(ic_f3b, clk, 256H, 256HQ, high)
TTL_7400_NAND(ic_g3b, ic_f3b.QQ, 256H) TTL_7400_NAND(ic_g3b, ic_f3b.QQ, 256H)
TTL_7427_NOR(ic_g2b, ic_g3b.Q, vblank, 4V) TTL_7427_NOR(ic_g2b, ic_g3b.Q, vblank, 4V)
NET_ALIAS(net, ic_g2b.Q) NET_ALIAS(net, ic_g2b.Q)
/* video */ // video
TTL_7402_NOR(ic_g1b, hvidQ, vvidQ) TTL_7402_NOR(ic_g1b, hvidQ, vvidQ)
TTL_7425_NOR(ic_f2b, ic_g1b.Q, pad1, pad2, net) TTL_7425_NOR(ic_f2b, ic_g1b.Q, pad1, pad2, net)
TTL_7404_INVERT(ic_e4e, ic_f2b.Q) TTL_7404_INVERT(ic_e4e, ic_f2b.Q)
NET_ALIAS(video, ic_e4e.Q) NET_ALIAS(video, ic_e4e.Q)
TTL_7486_XOR(ic_a4d, hsyncQ, vsyncQ)
TTL_7404_INVERT(ic_e4f, ic_a4d.Q)
NETDEV_MIXER3(videomix, video, score, ic_e4f.Q)
NETDEV_PARAM(videomix.R1, RES_K(1))
NETDEV_PARAM(videomix.R2, RES_K(1.2))
NETDEV_PARAM(videomix.R3, RES_K(22))
NETLIST_END NETLIST_END
static NETLIST_START(pong) static NETLIST_START(pong)
@ -414,8 +424,7 @@ static NETLIST_START(pong)
//NETLIST_INCLUDE(pong_schematics) //NETLIST_INCLUDE(pong_schematics)
NETLIST_MEMREGION("maincpu") NETLIST_MEMREGION("maincpu")
NETDEV_CALLBACK(sound_cb, sound) NETDEV_CALLBACK(sound_cb, sound)
NETDEV_CALLBACK(video_cb, video) NETDEV_CALLBACK(video_cb, videomix)
NETDEV_CALLBACK(score_cb, score)
NETLIST_END NETLIST_END
@ -425,13 +434,12 @@ static NETLIST_START(pong_fast)
/* the signal above is delayed on pong due to counter at gate delays. /* the signal above is delayed on pong due to counter at gate delays.
* This is approximated by the following circuit ... * This is approximated by the following circuit ...
*/ */
NET_REMOVE_DEV(ic_h5b) //NET_REMOVE_DEV(ic_h5b)
NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q) //NETDEV_DELAY_RISE(ic_g5b_D, clk, ic_g5b.Q)
TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q) //TTL_7400_NAND(ic_h5b, ic_h5c.Q, ic_g5b_D.Q)
NETDEV_CALLBACK(sound_cb, sound) NETDEV_CALLBACK(sound_cb, sound)
NETDEV_CALLBACK(video_cb, video) NETDEV_CALLBACK(video_cb, videomix)
NETDEV_CALLBACK(score_cb, score)
NETLIST_END NETLIST_END
@ -443,10 +451,10 @@ public:
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_dac(*this, "dac"), /* just to have a sound device */ m_dac(*this, "dac"), /* just to have a sound device */
m_srst(*this, "maincpu", "SRST"), m_srst(*this, "maincpu", "SRST"),
m_p_V0(*this, "maincpu", "P1"),
m_p_V1(*this, "maincpu", "P2"),
m_sw1a(*this, "maincpu", "sw1a.POS"), m_sw1a(*this, "maincpu", "sw1a.POS"),
m_sw1b(*this, "maincpu", "sw1b.POS"), m_sw1b(*this, "maincpu", "sw1b.POS"),
m_p_V0(*this, "maincpu", "ic_a9.VT"),
m_p_V1(*this, "maincpu", "ic_b9.VT"),
m_p_R0(*this, "maincpu", "ic_a9.R"), m_p_R0(*this, "maincpu", "ic_a9.R"),
m_p_R1(*this, "maincpu", "ic_b9.R") m_p_R1(*this, "maincpu", "ic_b9.R")
{ {
@ -457,11 +465,11 @@ public:
required_device<dac_device> m_dac; /* just to have a sound device */ required_device<dac_device> m_dac; /* just to have a sound device */
// sub devices // sub devices
netlist_mame_device::required_output m_srst; netlist_mame_device::required_output<logic_output_t> m_srst;
netlist_mame_device::required_output<analog_output_t> m_p_V0;
netlist_mame_device::required_output<analog_output_t> m_p_V1;
netlist_mame_device::required_param m_sw1a; netlist_mame_device::required_param m_sw1a;
netlist_mame_device::required_param m_sw1b; netlist_mame_device::required_param m_sw1b;
netlist_mame_device::required_param m_p_V0;
netlist_mame_device::required_param m_p_V1;
netlist_mame_device::required_param m_p_R0; netlist_mame_device::required_param m_p_R0;
netlist_mame_device::required_param m_p_R1; netlist_mame_device::required_param m_p_R1;
@ -469,21 +477,21 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(input_changed); DECLARE_INPUT_CHANGED_MEMBER(input_changed);
void sound_cb(net_sig_t newval) void sound_cb(double newval)
{ {
m_dac->write_unsigned8(128*(!newval)); //printf("snd %f\n", newval);
//dac_w(m_dac, 0, newval*64);
m_dac->write_unsigned8(64*newval);
} }
void video_cb(net_sig_t newval) void video_cb(double newval)
{ {
update_vid(); //printf("%f\n", newval);
m_vid = (m_vid & 2) | (UINT8) newval; if (newval != m_vid)
} {
update_vid();
void score_cb(net_sig_t newval) m_vid = newval;
{ }
update_vid();
m_vid = (m_vid & 1) | ((UINT8) newval<<1);
} }
protected: protected:
@ -498,29 +506,75 @@ private:
void update_vid() void update_vid()
{ {
const netlist_time clock_period = netlist_time::from_hz(NETLIST_CLOCK);
const netlist_time hsync_min_time = netlist_time::from_us(4);
const netlist_time vsync_min_time = netlist_time::from_us(50); /* usec */
const int vsync_min_pulses = 4;
UINT64 clocks = m_maincpu->total_cycles(); // m_maincpu->attotime_to_cycles(m_maincpu->local_time()); UINT64 clocks = m_maincpu->total_cycles(); // m_maincpu->attotime_to_cycles(m_maincpu->local_time());
int new_x = clocks % ( m_maincpu->SubCycles() * H_TOTAL); int pw = NETLIST_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT;
int new_y = (clocks / (m_maincpu->SubCycles() * H_TOTAL)) % V_TOTAL; netlist_time time = clock_period * (clocks - m_last_clock);
if (m_vid > 0)
//UINT64 clocks = m_maincpu->netlist().time().as_raw() >> 10; // m_maincpu->attotime_to_cycles(m_maincpu->local_time());
//int pw = (NETLIST_INTERNAL_CLOCK / ((UINT64)MASTER_CLOCK) / HRES_MULT) >> 8;
if (m_last_y < m_bitmap->height())
{ {
rgb_t col = MAKE_RGB(255,255,255); int colv = (int) (m_vid / 3.5 * 255.0);
if (new_y > m_last_y) rgb_t col = MAKE_RGB(colv, colv, colv);
new_x = m_maincpu->SubCycles() * H_TOTAL-1; int pixels = (clocks - m_line_clock) / pw;
int delta = (new_x - m_last_x);
if (delta < m_maincpu->SubCycles()) while (pixels >= m_bitmap->width())
col = MAKE_RGB(255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles()),255 * delta /( m_maincpu->SubCycles())); {
for (int i = m_last_x / ( m_maincpu->SubCycles() / HRES_MULT); i < new_x / ( m_maincpu->SubCycles()/HRES_MULT); i++) for (int i = m_last_x ; i < m_bitmap->width() - 1; i++)
m_bitmap->pix(m_last_y, i) = col;
pixels -= m_bitmap->width();
m_last_x = 0;
}
for (int i = m_last_x ; i < pixels; i++)
m_bitmap->pix(m_last_y, i) = col; m_bitmap->pix(m_last_y, i) = col;
m_last_x = pixels;
} }
m_last_x = new_x; if (m_vid <= 0.34)
m_last_y = new_y; {
if (time >= vsync_min_time)
{
m_vsync_cnt++;
if (m_vsync_cnt >= vsync_min_pulses)
{
m_vsync_cnt = 0;
m_last_y = 0;
attoseconds_t new_refresh = DOUBLE_TO_ATTOSECONDS((double) (clocks - m_vsync_clock) / (double) NETLIST_CLOCK);
if (new_refresh != m_refresh)
{
m_refresh = new_refresh;
rectangle visarea(0, H_TOTAL * HRES_MULT - 1, 0, V_TOTAL-1);
this->mconfig().first_screen()->configure(H_TOTAL * HRES_MULT, V_TOTAL, visarea, m_refresh);
m_vsync_clock = clocks;
}
}
m_last_y++;
m_last_x = 0;
}
else if (time >= hsync_min_time)
{
m_last_x = 0; // hsync
m_last_y++;
m_line_clock = clocks;
}
}
m_last_clock = clocks;
} }
UINT8 m_vid; double m_vid;
int m_last_x; int m_last_x;
int m_last_y; int m_last_y;
UINT64 m_last_clock;
UINT64 m_line_clock;
UINT64 m_vsync_clock;
attoseconds_t m_refresh;
int m_vsync_cnt;
bitmap_rgb32 *m_bitmap; bitmap_rgb32 *m_bitmap;
}; };
void pong_state::machine_start() void pong_state::machine_start()
@ -530,13 +584,10 @@ void pong_state::machine_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("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("video_cb", net_output_delegate(&pong_state::video_cb, "pong_state::video_cb", this));
m_maincpu->setup().register_callback("score_cb", net_output_delegate(&pong_state::score_cb, "pong_state::score_cb", this));
} }
void pong_state::machine_reset() void pong_state::machine_reset()
{ {
// m_sound_nmi_enabled = FALSE;
// m_nmi_enable = 0;
} }
@ -549,7 +600,7 @@ void pong_state::video_start()
UINT32 pong_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect ) UINT32 pong_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
{ {
copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect); copybitmap(bitmap, *m_bitmap, 0, 0, 0, 0, cliprect);
m_bitmap->fill(MAKE_RGB(0,0,0)); //m_bitmap->fill(MAKE_RGB(0,0,0));
return 0; return 0;
} }
@ -579,8 +630,8 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
double pad = vA + (vB - vA)*PRE_R / (Req + PRE_R); double pad = vA + (vB - vA)*PRE_R / (Req + PRE_R);
switch (numpad) switch (numpad)
{ {
case IC_PADDLE1: m_p_V0->setTo(pad); break; case IC_PADDLE1: m_p_V0->setToPS(pad, NLTIME_FROM_NS(0)); break;
case IC_PADDLE2: m_p_V1->setTo(pad); break; case IC_PADDLE2: m_p_V1->setToPS(pad, NLTIME_FROM_NS(0)); break;
} }
break; break;
} }
@ -589,7 +640,7 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
m_sw1b->setTo(newval ? 1 : 0); m_sw1b->setTo(newval ? 1 : 0);
break; break;
case IC_COIN: case IC_COIN:
m_srst->setTo(newval & 1); m_srst->setToPS(newval & 1, NLTIME_FROM_US(500));
break; break;
case IC_VR1: case IC_VR1:
case IC_VR2: case IC_VR2:
@ -600,9 +651,6 @@ INPUT_CHANGED_MEMBER(pong_state::input_changed)
case IC_VR2: m_p_R1->setTo(pad); break; case IC_VR2: m_p_R1->setTo(pad); break;
} }
break; break;
case IC_GATEDELAY:
m_maincpu->netlist().set_gatedelay(newval);
break;
} }
@ -626,15 +674,15 @@ static INPUT_PORTS_START( pong )
PORT_ADJUSTER( 63, "VR1 - 50k, Paddle 1 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR1) PORT_ADJUSTER( 63, "VR1 - 50k, Paddle 1 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR1)
PORT_START("VR2") PORT_START("VR2")
PORT_ADJUSTER( 63, "VR2 - 50k, Paddle 2 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR2) PORT_ADJUSTER( 63, "VR2 - 50k, Paddle 2 adjustment" ) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_VR2)
PORT_START("GATESPEED") //PORT_START("GATESPEED")
PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY) //PORT_ADJUSTER( 100, "Logic Gate Delay" ) PORT_MINMAX(10, 200) PORT_CHANGED_MEMBER(DEVICE_SELF, pong_state, input_changed, IC_GATEDELAY)
INPUT_PORTS_END INPUT_PORTS_END
static MACHINE_CONFIG_START( pong, pong_state ) static MACHINE_CONFIG_START( pong, pong_state )
/* basic machine hardware */ /* basic machine hardware */
MCFG_NETLIST_ADD("maincpu", MASTER_CLOCK, pong, 10) MCFG_NETLIST_ADD("maincpu", pong)
/* video hardware */ /* video hardware */
MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_ADD("screen", RASTER)
@ -651,7 +699,8 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( pongf, pong ) static MACHINE_CONFIG_DERIVED( pongf, pong )
/* basic machine hardware */ /* basic machine hardware */
MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 2) //MCFG_NETLIST_REPLACE("maincpu", MASTER_CLOCK, pong_fast, 100)
MCFG_NETLIST_REPLACE("maincpu", pong_fast)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -663,7 +712,7 @@ MACHINE_CONFIG_END
ROM_START( pong ) /* dummy to satisfy game entry*/ ROM_START( pong ) /* dummy to satisfy game entry*/
ROM_REGION( 0x10000, "maincpu", 0 ) /* enough for netlist */ ROM_REGION( 0x10000, "maincpu", 0 ) /* enough for netlist */
ROM_LOAD( "pong.netlist", 0x00000, 10306, CRC(bb92b267) SHA1(0dd6b3209ac1335a97cfe159502d24556f531007) ) ROM_LOAD( "pong.netlist", 0x000000, 0x0029e4, CRC(e9c409a1) SHA1(1dc99437f49261c3cb3f46153c6258043bc720a0) )
ROM_END ROM_END
ROM_START( pongf ) /* dummy to satisfy game entry*/ ROM_START( pongf ) /* dummy to satisfy game entry*/