mirror of
https://github.com/holub/mame
synced 2025-06-25 22:04:15 +03:00
Netlist and Pong:
- Added save-state support. - Fixed a compile issue with MSVC The state saving is now 80% generic. This still needs some polishing, but works.
This commit is contained in:
parent
5eb4f5530b
commit
f46847e487
@ -50,7 +50,8 @@
|
||||
#include "netlist/nl_setup.h"
|
||||
#include "netlist/devices/net_lib.h"
|
||||
|
||||
#define LOG_DEV_CALLS(x) do { } while (0);
|
||||
//#define LOG_DEV_CALLS(x) printf x
|
||||
#define LOG_DEV_CALLS(x) do { } while (0)
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_mame_device
|
||||
@ -61,6 +62,7 @@ const device_type NETLIST = &device_creator<netlist_mame_device>;
|
||||
netlist_mame_device::netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, NETLIST, "netlist", tag, owner, clock, "netlist_mame", __FILE__),
|
||||
device_execute_interface(mconfig, *this),
|
||||
//device_state_interface(mconfig, *this),
|
||||
m_device_start_list(100),
|
||||
m_netlist(NULL),
|
||||
m_setup(NULL),
|
||||
@ -86,11 +88,13 @@ void netlist_mame_device::device_start()
|
||||
LOG_DEV_CALLS(("device_start\n"));
|
||||
|
||||
m_netlist = global_alloc_clear(netlist_mame_t(*this));
|
||||
m_netlist->set_clock_freq(this->clock());
|
||||
|
||||
m_setup = global_alloc_clear(netlist_setup_t(*m_netlist));
|
||||
m_netlist->init_object(*m_netlist, "netlist");
|
||||
m_setup->init();
|
||||
|
||||
// register additional devices
|
||||
m_netlist->set_clock_freq(this->clock());
|
||||
|
||||
// register additional devices
|
||||
|
||||
m_setup->factory().register_device<nld_analog_callback>( "NETDEV_CALLBACK", "nld_analog_callback");
|
||||
|
||||
@ -107,7 +111,6 @@ void netlist_mame_device::device_start()
|
||||
m_netlist->xfatalerror("required elements not found\n");
|
||||
|
||||
save_state();
|
||||
/* TODO: we have to save the round robin queue as well */
|
||||
|
||||
// set our instruction counter
|
||||
m_icountptr = &m_icount;
|
||||
@ -130,31 +133,113 @@ void netlist_mame_device::device_stop()
|
||||
m_netlist = NULL;
|
||||
}
|
||||
|
||||
void netlist_mame_device::device_post_load()
|
||||
ATTR_COLD void netlist_mame_device::device_post_load()
|
||||
{
|
||||
LOG_DEV_CALLS(("device_post_load\n"));
|
||||
m_netlist->queue().clear();
|
||||
NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize));
|
||||
for (int i = 0; i < qsize; i++ )
|
||||
{
|
||||
netlist_net_t *n = m_netlist->find_net(qtemp[i].m_name);
|
||||
NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n));
|
||||
NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double()));
|
||||
m_netlist->queue().push(netlist_base_t::queue_t::entry_t(qtemp[i].m_time, *n));
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_mame_device::device_pre_save()
|
||||
{
|
||||
LOG_DEV_CALLS(("device_pre_save\n"));
|
||||
|
||||
qsize = m_netlist->queue().count();
|
||||
NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize));
|
||||
for (int i = 0; i < qsize; i++ )
|
||||
{
|
||||
qtemp[i].m_time = m_netlist->queue().listptr()[i].time();
|
||||
const char *p = m_netlist->queue().listptr()[i].object().name().cstr();
|
||||
int n = MIN(63, strlen(p));
|
||||
strncpy(qtemp[i].m_name, p, n);
|
||||
qtemp[i].m_name[n] = 0;
|
||||
}
|
||||
#if 0
|
||||
|
||||
netlist_time *nlt = (netlist_time *) ;
|
||||
netlist_base_t::queue_t::entry_t *p = m_netlist->queue().listptr()[i];
|
||||
netlist_time *nlt = (netlist_time *) p->time_ptr();
|
||||
save_pointer(nlt->get_internaltype_ptr(), "queue", 1, i);
|
||||
#endif
|
||||
}
|
||||
|
||||
void netlist_mame_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
}
|
||||
|
||||
void netlist_mame_device::save_state()
|
||||
|
||||
|
||||
ATTR_COLD void netlist_mame_device::save_state()
|
||||
{
|
||||
for (netlist_setup_t::save_entry_list_t::entry_t *p = setup().m_save.first(); p != NULL; p = setup().m_save.next(p))
|
||||
{
|
||||
netlist_setup_t::save_entry_t *s = p->object();
|
||||
NL_VERBOSE_OUT(("saving state for %s\n", s->m_name.cstr()));
|
||||
switch (s->m_dt)
|
||||
{
|
||||
case DT_DOUBLE:
|
||||
save_pointer((double *) s->m_ptr, s->m_name, 1);
|
||||
break;
|
||||
case DT_INT64:
|
||||
save_pointer((INT64 *) s->m_ptr, s->m_name, 1);
|
||||
break;
|
||||
case DT_INT8:
|
||||
save_pointer((INT8 *) s->m_ptr, s->m_name, 1);
|
||||
break;
|
||||
case DT_INT:
|
||||
save_pointer((int *) s->m_ptr, s->m_name, 1);
|
||||
break;
|
||||
case DT_BOOLEAN:
|
||||
save_pointer((bool *) s->m_ptr, s->m_name, 1);
|
||||
break;
|
||||
#if 0
|
||||
for (netlist_setup_t::tagmap_output_t::entry_t *entry = m_setup->m_outputs.first(); entry != NULL; entry = m_setup->m_outputs.next(entry))
|
||||
{
|
||||
save_item(*entry->object()->Q_ptr(), entry->tag().cstr(), 0);
|
||||
save_item(*entry->object()->new_Q_ptr(), entry->tag().cstr(), 1);
|
||||
}
|
||||
case DT_NLTIME:
|
||||
{
|
||||
netlist_time *nlt = (netlist_time *) s->m_ptr;
|
||||
//save_pointer((netlist_time::INTERNALTYPE *) s->m_ptr, s->m_name, 1);
|
||||
//save_pointer(nlt->get_internaltype_ptr(), s->m_name, 1);
|
||||
save_item(*nlt->get_internaltype_ptr(), s->m_name.cstr());
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case NOT_SUPPORTED:
|
||||
default:
|
||||
m_netlist->xfatalerror("found unsupported save element %s\n", s->m_name.cstr());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// handle the queue
|
||||
|
||||
save_item(NAME(qsize));
|
||||
for (int i = 0; i < m_netlist->queue().capacity(); i++ )
|
||||
{
|
||||
save_pointer(qtemp[i].m_time.get_internaltype_ptr(), "queue_time", 1, i);
|
||||
save_pointer(qtemp[i].m_name, "queue_name", sizeof(qtemp[i].m_name), i);
|
||||
|
||||
}
|
||||
#if 0
|
||||
|
||||
netlist_time *nlt = (netlist_time *) ;
|
||||
netlist_base_t::queue_t::entry_t *p = m_netlist->queue().listptr()[i];
|
||||
netlist_time *nlt = (netlist_time *) p->time_ptr();
|
||||
save_pointer(nlt->get_internaltype_ptr(), "queue", 1, i);
|
||||
#endif
|
||||
}
|
||||
|
||||
UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
|
||||
ATTR_COLD UINT64 netlist_mame_device::execute_clocks_to_cycles(UINT64 clocks) const
|
||||
{
|
||||
return clocks;
|
||||
}
|
||||
|
||||
UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
|
||||
ATTR_COLD UINT64 netlist_mame_device::execute_cycles_to_clocks(UINT64 cycles) const
|
||||
{
|
||||
return cycles;
|
||||
}
|
||||
@ -169,5 +254,4 @@ ATTR_HOT void netlist_mame_device::execute_run()
|
||||
// debugger_instruction_hook(this, 0); //m_pc);
|
||||
|
||||
m_netlist->process_queue(m_icount);
|
||||
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ private:
|
||||
|
||||
class netlist_mame_device : public device_t,
|
||||
public device_execute_interface
|
||||
//public device_state_interface
|
||||
//, public device_memory_interface
|
||||
{
|
||||
public:
|
||||
@ -158,6 +159,7 @@ protected:
|
||||
virtual void device_stop();
|
||||
virtual void device_reset();
|
||||
virtual void device_post_load();
|
||||
virtual void device_pre_save();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const;
|
||||
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const;
|
||||
@ -168,6 +170,16 @@ protected:
|
||||
|
||||
netlist_setup_t *m_setup;
|
||||
|
||||
// more save state ... needs to go somewhere else
|
||||
|
||||
struct qentry {
|
||||
netlist_time m_time;
|
||||
char m_name[64];
|
||||
};
|
||||
|
||||
qentry qtemp[1024];
|
||||
int qsize;
|
||||
|
||||
private:
|
||||
|
||||
void save_state();
|
||||
|
@ -118,6 +118,8 @@ NETLIB_START(nic7448_sub)
|
||||
register_output("e", m_e);
|
||||
register_output("f", m_f);
|
||||
register_output("g", m_g);
|
||||
|
||||
save(NAME(m_state));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(nic7448_sub)
|
||||
@ -225,6 +227,10 @@ NETLIB_START(nic74107Asub)
|
||||
|
||||
m_Q.initial(0);
|
||||
m_QQ.initial(1);
|
||||
|
||||
save(NAME(m_Q1));
|
||||
save(NAME(m_Q2));
|
||||
save(NAME(m_F));
|
||||
}
|
||||
|
||||
NETLIB_START(nic74107A)
|
||||
|
@ -24,6 +24,8 @@ NETLIB_START(7483)
|
||||
register_output("SC", m_SC);
|
||||
register_output("SD", m_SD);
|
||||
register_output("C4", m_C4);
|
||||
|
||||
save(NAME(m_lastr));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(7483)
|
||||
|
@ -19,6 +19,9 @@ NETLIB_START(7490)
|
||||
register_output("QB", m_Q[1]);
|
||||
register_output("QC", m_Q[2]);
|
||||
register_output("QD", m_Q[3]);
|
||||
|
||||
save(NAME(m_cnt));
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(7490)
|
||||
|
@ -28,8 +28,12 @@ NETLIB_START(7493)
|
||||
|
||||
NETLIB_START(7493ff)
|
||||
{
|
||||
m_reset = 0;
|
||||
|
||||
register_input("CLK", m_I, netlist_input_t::STATE_INP_HL);
|
||||
register_output("Q", m_Q);
|
||||
|
||||
save(NAME(m_reset));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(7493ff)
|
||||
|
@ -48,6 +48,9 @@ NETLIB_START(9316_sub)
|
||||
register_output("QD", m_QD);
|
||||
register_output("RC", m_RC);
|
||||
|
||||
save(NAME(m_cnt));
|
||||
save(NAME(m_loadq));
|
||||
save(NAME(m_ent));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(9316_sub)
|
||||
|
@ -21,6 +21,9 @@ NETLIB_START(nicMultiSwitch)
|
||||
}
|
||||
register_param("POS", m_POS, 0);
|
||||
register_output("Q", m_Q);
|
||||
|
||||
save(NAME(m_position));
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(nicMultiSwitch)
|
||||
@ -116,11 +119,14 @@ NETLIB_START(nicNE555N_MSTABLE)
|
||||
register_param("VS", m_VS, 5.0);
|
||||
register_param("VL", m_VL, 0.0 *5.0);
|
||||
|
||||
m_THRESHOLD_OUT.init_object(*this, "THRESHOLD");
|
||||
m_THRESHOLD_OUT.init_object(*this, name() + "THRESHOLD");
|
||||
register_link_internal(m_THRESHOLD, m_THRESHOLD_OUT, netlist_input_t::STATE_INP_ACTIVE);
|
||||
|
||||
m_Q.initial(5.0 * 0.4);
|
||||
m_last = false;
|
||||
|
||||
save(NAME(m_last));
|
||||
|
||||
}
|
||||
|
||||
inline double NETLIB_NAME(nicNE555N_MSTABLE)::nicNE555N_cv()
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "nld_log.h"
|
||||
#include "sound/wavwrite.h"
|
||||
|
||||
//FIXME: what to do with save states?
|
||||
|
||||
NETLIB_START(log)
|
||||
{
|
||||
register_input("I", m_I);
|
||||
|
@ -48,6 +48,8 @@ NETLIB_START(NE555)
|
||||
setup().connect(m_RDIS.m_N, m_R3.m_N);
|
||||
|
||||
m_last_out = false;
|
||||
|
||||
save(NAME(m_last_out));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(NE555)
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
|
||||
}
|
||||
m_Q.initial(1);
|
||||
save(NAME(m_active));
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
@ -69,7 +70,7 @@ public:
|
||||
public:
|
||||
netlist_ttl_input_t m_i[_numdev];
|
||||
netlist_ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
INT32 m_active;
|
||||
};
|
||||
|
||||
|
||||
@ -92,6 +93,7 @@ public:
|
||||
{
|
||||
register_input(sIN[i], m_i[i]);
|
||||
}
|
||||
save(NAME(m_active));
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
@ -142,7 +144,7 @@ public:
|
||||
public:
|
||||
netlist_ttl_input_t m_i[_numdev];
|
||||
netlist_ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
INT32 m_active;
|
||||
};
|
||||
|
||||
#if 1
|
||||
@ -165,6 +167,7 @@ public:
|
||||
{
|
||||
register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE);
|
||||
}
|
||||
save(NAME(m_active));
|
||||
}
|
||||
|
||||
#if (USE_DEACTIVE_DEVICE)
|
||||
@ -214,7 +217,7 @@ public:
|
||||
public:
|
||||
netlist_ttl_input_t m_i[2];
|
||||
netlist_ttl_output_t m_Q;
|
||||
INT8 m_active;
|
||||
INT32 m_active;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
@ -187,6 +187,8 @@ static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t
|
||||
static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net)
|
||||
{
|
||||
/* add the net */
|
||||
if (net->m_head == NULL)
|
||||
return;
|
||||
groups[cur_group].add(net);
|
||||
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
|
||||
{
|
||||
@ -216,10 +218,18 @@ NETLIB_START(solver)
|
||||
register_param("ACCURACY", m_accuracy, 1e-3);
|
||||
register_param("CONVERG", m_convergence, 0.3);
|
||||
|
||||
register_link_internal(m_fb_sync, m_Q_sync, netlist_input_t::STATE_INP_ACTIVE);
|
||||
register_link_internal(m_fb_step, m_Q_step, netlist_input_t::STATE_INP_ACTIVE);
|
||||
// internal staff
|
||||
|
||||
register_input("FB_sync", m_fb_sync, netlist_input_t::STATE_INP_ACTIVE);
|
||||
register_input("FB_step", m_fb_step, netlist_input_t::STATE_INP_ACTIVE);
|
||||
|
||||
setup().connect(m_fb_sync, m_Q_sync);
|
||||
setup().connect(m_fb_step, m_Q_step);
|
||||
|
||||
m_last_step = netlist_time::zero;
|
||||
|
||||
save(NAME(m_last_step));
|
||||
|
||||
}
|
||||
|
||||
NETLIB_UPDATE_PARAM(solver)
|
||||
@ -237,13 +247,6 @@ NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
|
||||
e = en;
|
||||
}
|
||||
|
||||
netlist_net_t::list_t::entry_t *p = m_nets.first();
|
||||
while (p != NULL)
|
||||
{
|
||||
netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
|
||||
delete p->object();
|
||||
p = pn;
|
||||
}
|
||||
}
|
||||
|
||||
NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
@ -251,24 +254,9 @@ NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
netlist_net_t::list_t groups[100];
|
||||
int cur_group = -1;
|
||||
|
||||
NL_VERBOSE_OUT(("post start solver ...\n"));
|
||||
|
||||
// delete empty nets ...
|
||||
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
if (pn->object()->m_head == NULL)
|
||||
{
|
||||
NL_VERBOSE_OUT(("Deleting net ...\n"));
|
||||
netlist_net_t *to_delete = pn->object();
|
||||
m_nets.remove(to_delete);
|
||||
delete to_delete;
|
||||
pn--;
|
||||
}
|
||||
}
|
||||
|
||||
SOLVER_VERBOSE_OUT(("Scanning net groups ...\n"));
|
||||
// determine net groups
|
||||
for (netlist_net_t::list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
|
||||
{
|
||||
if (!already_processed(groups, cur_group, pn->object()))
|
||||
{
|
||||
|
@ -74,8 +74,6 @@ public:
|
||||
|
||||
~NETLIB_NAME(solver)();
|
||||
|
||||
netlist_net_t::list_t m_nets;
|
||||
|
||||
ATTR_HOT inline void schedule();
|
||||
|
||||
ATTR_COLD void post_start();
|
||||
|
@ -124,6 +124,9 @@ NETLIB_START(D)
|
||||
register_param("model", m_model, "");
|
||||
|
||||
m_Vd = 0.7;
|
||||
|
||||
save(NAME(m_Vd));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -197,6 +200,8 @@ NETLIB_START(QBJT_switch<_type>)
|
||||
setup().connect(m_RB.m_N, m_RC.m_N);
|
||||
setup().connect(m_RB.m_P, m_BV);
|
||||
setup().connect(m_RB.m_N, m_EV);
|
||||
|
||||
save(NAME(m_state_on));
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(Q)
|
||||
@ -256,8 +261,8 @@ ATTR_COLD void NETLIB_NAME(VCCS)::configure(const double Gfac, const double GI)
|
||||
register_terminal("OP", m_OP);
|
||||
register_terminal("ON", m_ON);
|
||||
|
||||
m_OP1.init_object(*this, "OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
|
||||
m_ON1.init_object(*this, "ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
|
||||
m_OP1.init_object(*this, name() + ".OP1", netlist_core_terminal_t::STATE_INP_ACTIVE);
|
||||
m_ON1.init_object(*this, name() + ".ON1", netlist_core_terminal_t::STATE_INP_ACTIVE);
|
||||
|
||||
const double m_mult = m_G.Value() * Gfac; // 1.0 ==> 1V ==> 1A
|
||||
m_IP.set(GI);
|
||||
|
@ -219,9 +219,11 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
//m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt;
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1200
|
||||
m_Vd = m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt;
|
||||
#else
|
||||
m_Vd = m_Vd + log1p((nVd - m_Vd) * m_VtInv) * m_Vt;
|
||||
|
||||
#endif
|
||||
const double eVDVt = exp(m_Vd * m_VtInv);
|
||||
Id = m_Is * (eVDVt - 1.0);
|
||||
|
||||
@ -348,7 +350,7 @@ protected:
|
||||
double m_gB; // base conductance / switch on
|
||||
double m_gC; // collector conductance / switch on
|
||||
double m_V; // internal voltage source
|
||||
int m_state_on;
|
||||
UINT8 m_state_on;
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ ATTR_COLD void netlist_object_t::init_object(netlist_base_t &nl, const pstring &
|
||||
{
|
||||
m_netlist = &nl;
|
||||
m_name = aname;
|
||||
save_register();
|
||||
}
|
||||
|
||||
ATTR_COLD const pstring &netlist_object_t::name() const
|
||||
@ -38,6 +39,23 @@ ATTR_COLD const pstring &netlist_object_t::name() const
|
||||
return m_name;
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_object_t::save_state_ptr(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr)
|
||||
{
|
||||
pstring fullname = name() + "." + stname;
|
||||
// do nothing for now;
|
||||
ATTR_UNUSED pstring ts[] = {
|
||||
"NOT_SUPPORTED",
|
||||
"DT_DOUBLE",
|
||||
"DT_INT64",
|
||||
"DT_INT8",
|
||||
"DT_INT",
|
||||
"DT_BOOLEAN"
|
||||
};
|
||||
|
||||
NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr));
|
||||
netlist().setup().save_state_ptr(fullname, dt, size, ptr);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_owned_object_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -61,7 +79,8 @@ ATTR_COLD void netlist_owned_object_t::init_object(netlist_core_device_t &dev,
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_base_t::netlist_base_t()
|
||||
: m_time_ps(netlist_time::zero),
|
||||
: netlist_object_t(NETLIST, GENERIC),
|
||||
m_time_ps(netlist_time::zero),
|
||||
m_rem(0),
|
||||
m_div(NETLIST_DIV),
|
||||
m_mainclock(NULL),
|
||||
@ -82,9 +101,30 @@ static void tagmap_free_entries(T &tm)
|
||||
netlist_base_t::~netlist_base_t()
|
||||
{
|
||||
tagmap_free_entries<tagmap_devices_t>(m_devices);
|
||||
|
||||
netlist_net_t::list_t::entry_t *p = m_nets.first();
|
||||
while (p != NULL)
|
||||
{
|
||||
netlist_net_t::list_t::entry_t *pn = m_nets.next(p);
|
||||
if (!p->object()->isRailNet())
|
||||
delete p->object();
|
||||
p = pn;
|
||||
}
|
||||
|
||||
m_nets.reset();
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
ATTR_COLD netlist_net_t *netlist_base_t::find_net(const pstring &name)
|
||||
{
|
||||
for (netlist_net_t::list_t::entry_t *p = m_nets.first(); p != NULL; p = m_nets.next(p))
|
||||
{
|
||||
if (p->object()->name() == name)
|
||||
return p->object();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_base_t::set_mainclock_dev(NETLIB_NAME(mainclock) *dev)
|
||||
{
|
||||
m_mainclock = dev;
|
||||
@ -339,6 +379,7 @@ ATTR_COLD void netlist_device_t::register_input(const pstring &name, netlist_inp
|
||||
setup().register_object(*this, *this, name, inp, type);
|
||||
}
|
||||
|
||||
//FIXME: Get rid of this
|
||||
static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term, netlist_input_t::state_e aState)
|
||||
{
|
||||
if (!term.isInitalized())
|
||||
@ -346,13 +387,13 @@ static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term,
|
||||
switch (term.type())
|
||||
{
|
||||
case netlist_terminal_t::OUTPUT:
|
||||
dynamic_cast<netlist_output_t &>(term).init_object(dev, "internal output");
|
||||
dynamic_cast<netlist_output_t &>(term).init_object(dev, dev.name() + ".INTOUT");
|
||||
break;
|
||||
case netlist_terminal_t::INPUT:
|
||||
dynamic_cast<netlist_input_t &>(term).init_object(dev, "internal input", aState);
|
||||
dynamic_cast<netlist_input_t &>(term).init_object(dev, dev.name() + ".INTINP", aState);
|
||||
break;
|
||||
case netlist_terminal_t::TERMINAL:
|
||||
dynamic_cast<netlist_terminal_t &>(term).init_object(dev, "internal terminal", aState);
|
||||
dynamic_cast<netlist_terminal_t &>(term).init_object(dev, dev.name() + ".INTTERM", aState);
|
||||
break;
|
||||
default:
|
||||
dev.netlist().xfatalerror("Unknown terminal type");
|
||||
@ -362,6 +403,7 @@ static void init_term(netlist_core_device_t &dev, netlist_core_terminal_t &term,
|
||||
}
|
||||
|
||||
// FIXME: Revise internal links ...
|
||||
//FIXME: Get rid of this
|
||||
ATTR_COLD void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, const netlist_input_t::state_e aState)
|
||||
{
|
||||
init_term(dev, in, aState);
|
||||
@ -377,9 +419,11 @@ ATTR_COLD void netlist_device_t::register_link_internal(netlist_input_t &in, net
|
||||
template <class C, class T>
|
||||
ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const pstring &sname, C ¶m, const T initialVal)
|
||||
{
|
||||
param.init_object(dev, sname);
|
||||
pstring fullname = dev.name() + "." + sname;
|
||||
param.init_object(dev, fullname);
|
||||
param.initial(initialVal);
|
||||
setup().register_object(*this, *this, sname, param, netlist_terminal_t::STATE_NONEX);
|
||||
//FIXME: pass fullname from above
|
||||
setup().register_object(*this, *this, fullname, param, netlist_terminal_t::STATE_NONEX);
|
||||
}
|
||||
|
||||
template ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const pstring &sname, netlist_param_double_t ¶m, const double initialVal);
|
||||
@ -405,6 +449,12 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil
|
||||
{
|
||||
};
|
||||
|
||||
ATTR_COLD void netlist_net_t::init_object(netlist_base_t &nl, const pstring &aname)
|
||||
{
|
||||
netlist_object_t::init_object(nl, aname);
|
||||
nl.m_nets.add(this);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_net_t::register_railterminal(netlist_output_t &mr)
|
||||
{
|
||||
assert(m_railterminal == NULL);
|
||||
@ -551,7 +601,7 @@ netlist_output_t::netlist_output_t(const type_t atype, const family_t afamily)
|
||||
ATTR_COLD void netlist_output_t::init_object(netlist_core_device_t &dev, const pstring &aname)
|
||||
{
|
||||
netlist_core_terminal_t::init_object(dev, aname, STATE_OUT);
|
||||
net().init_object(dev.netlist(), aname);
|
||||
net().init_object(dev.netlist(), aname + ".net");
|
||||
net().register_railterminal(*this);
|
||||
}
|
||||
|
||||
|
@ -246,6 +246,33 @@ class netlist_matrix_solver_t;
|
||||
class NETLIB_NAME(solver);
|
||||
class NETLIB_NAME(mainclock);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// state saving ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
enum netlist_data_type_e {
|
||||
NOT_SUPPORTED,
|
||||
DT_DOUBLE,
|
||||
DT_INT64,
|
||||
DT_INT8,
|
||||
DT_INT,
|
||||
DT_BOOLEAN
|
||||
};
|
||||
|
||||
template<typename _ItemType> struct nl_datatype { static const netlist_data_type_e type = netlist_data_type_e(NOT_SUPPORTED); };
|
||||
//template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };
|
||||
|
||||
#define NETLIST_SAVE_TYPE(TYPE, TYPEDESC) template<> struct nl_datatype<TYPE>{ static const netlist_data_type_e type = netlist_data_type_e(TYPEDESC); }
|
||||
|
||||
NETLIST_SAVE_TYPE(double, DT_DOUBLE);
|
||||
NETLIST_SAVE_TYPE(INT8, DT_INT8);
|
||||
NETLIST_SAVE_TYPE(UINT8, DT_INT8);
|
||||
NETLIST_SAVE_TYPE(INT64, DT_INT64);
|
||||
NETLIST_SAVE_TYPE(UINT64, DT_INT64);
|
||||
NETLIST_SAVE_TYPE(bool, DT_BOOLEAN);
|
||||
NETLIST_SAVE_TYPE(UINT32, DT_INT);
|
||||
NETLIST_SAVE_TYPE(INT32, DT_INT);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_object_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -261,6 +288,7 @@ public:
|
||||
PARAM = 3,
|
||||
NET = 4,
|
||||
DEVICE = 5,
|
||||
NETLIST = 6,
|
||||
};
|
||||
enum family_t {
|
||||
// Terminal families
|
||||
@ -285,6 +313,12 @@ public:
|
||||
|
||||
ATTR_COLD const pstring &name() const;
|
||||
|
||||
ATTR_COLD void save_state_ptr(const pstring &stname, const netlist_data_type_e, const int size, void *ptr);
|
||||
template<class C> ATTR_COLD void save(C &state, const pstring &stname)
|
||||
{
|
||||
save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), &state);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const type_t type() const { return m_objtype; }
|
||||
ATTR_HOT inline const family_t family() const { return m_family; }
|
||||
|
||||
@ -294,6 +328,11 @@ public:
|
||||
ATTR_HOT inline netlist_base_t & RESTRICT netlist() { return *m_netlist; }
|
||||
ATTR_HOT inline const netlist_base_t & RESTRICT netlist() const { return *m_netlist; }
|
||||
|
||||
protected:
|
||||
|
||||
// must call parent save_register !
|
||||
ATTR_COLD virtual void save_register() { };
|
||||
|
||||
private:
|
||||
pstring m_name;
|
||||
const type_t m_objtype;
|
||||
@ -301,6 +340,11 @@ private:
|
||||
netlist_base_t * RESTRICT m_netlist;
|
||||
};
|
||||
|
||||
template<> ATTR_COLD inline void netlist_object_t::save(netlist_time &state, const pstring &stname)
|
||||
{
|
||||
save_state_ptr(stname, DT_INT64, sizeof(netlist_time::INTERNALTYPE), state.get_internaltype_ptr());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_owned_object_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -338,6 +382,7 @@ public:
|
||||
STATE_NONEX = 256
|
||||
};
|
||||
|
||||
|
||||
ATTR_COLD netlist_core_terminal_t(const type_t atype, const family_t afamily);
|
||||
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname, const state_e astate);
|
||||
@ -357,11 +402,17 @@ public:
|
||||
|
||||
netlist_core_terminal_t *m_update_list_next;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register() { save(NAME(m_state)); netlist_owned_object_t::save_register(); }
|
||||
|
||||
private:
|
||||
netlist_net_t * RESTRICT m_net;
|
||||
state_e m_state;
|
||||
};
|
||||
|
||||
NETLIST_SAVE_TYPE(netlist_core_terminal_t::state_e, DT_INT);
|
||||
|
||||
|
||||
class netlist_terminal_t : public netlist_core_terminal_t
|
||||
{
|
||||
NETLIST_PREVENT_COPYING(netlist_terminal_t)
|
||||
@ -394,6 +445,16 @@ public:
|
||||
|
||||
|
||||
netlist_terminal_t *m_otherterm;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
save(NAME(m_Idr));
|
||||
save(NAME(m_go));
|
||||
save(NAME(m_gt));
|
||||
netlist_core_terminal_t::save_register();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -502,6 +563,7 @@ public:
|
||||
};
|
||||
|
||||
ATTR_COLD netlist_net_t(const type_t atype, const family_t afamily);
|
||||
ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname);
|
||||
|
||||
ATTR_COLD void register_con(netlist_core_terminal_t &terminal);
|
||||
ATTR_COLD void merge_net(netlist_net_t *othernet);
|
||||
@ -568,6 +630,21 @@ protected:
|
||||
|
||||
UINT32 m_num_cons;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
save(NAME(m_last.Analog));
|
||||
save(NAME(m_cur.Analog));
|
||||
save(NAME(m_new.Analog));
|
||||
save(NAME(m_last.Q));
|
||||
save(NAME(m_cur.Q));
|
||||
save(NAME(m_new.Q));
|
||||
save(NAME(m_time));
|
||||
save(NAME(m_active));
|
||||
save(NAME(m_in_queue));
|
||||
netlist_object_t::save_register();
|
||||
}
|
||||
|
||||
private:
|
||||
ATTR_HOT void update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const;
|
||||
|
||||
@ -688,6 +765,13 @@ public:
|
||||
ATTR_COLD inline void initial(const double val) { m_param = val; }
|
||||
ATTR_HOT inline const double Value() const { return m_param; }
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
save(NAME(m_param));
|
||||
netlist_param_t::save_register();
|
||||
}
|
||||
|
||||
private:
|
||||
double m_param;
|
||||
};
|
||||
@ -703,6 +787,13 @@ public:
|
||||
|
||||
ATTR_HOT inline const int Value() const { return m_param; }
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
save(NAME(m_param));
|
||||
netlist_param_t::save_register();
|
||||
}
|
||||
|
||||
private:
|
||||
int m_param;
|
||||
};
|
||||
@ -832,7 +923,7 @@ public:
|
||||
protected:
|
||||
|
||||
ATTR_HOT virtual void update() { }
|
||||
ATTR_HOT virtual void start() { }
|
||||
ATTR_COLD virtual void start() { }
|
||||
|
||||
private:
|
||||
};
|
||||
@ -892,7 +983,7 @@ private:
|
||||
|
||||
typedef tagmap_t<netlist_device_t *, 393> tagmap_devices_t;
|
||||
|
||||
class netlist_base_t
|
||||
class netlist_base_t : public netlist_object_t
|
||||
{
|
||||
NETLIST_PREVENT_COPYING(netlist_base_t)
|
||||
public:
|
||||
@ -920,6 +1011,8 @@ public:
|
||||
ATTR_COLD void set_solver_dev(NETLIB_NAME(solver) *dev);
|
||||
ATTR_COLD void set_setup(netlist_setup_t *asetup) { m_setup = asetup; }
|
||||
|
||||
ATTR_COLD netlist_net_t *find_net(const pstring &name);
|
||||
|
||||
ATTR_COLD void set_clock_freq(UINT64 clockfreq);
|
||||
|
||||
ATTR_COLD netlist_setup_t &setup() { return *m_setup; }
|
||||
@ -928,11 +1021,23 @@ public:
|
||||
ATTR_COLD void xfatalerror(const char *format, ...) const;
|
||||
|
||||
tagmap_devices_t m_devices;
|
||||
netlist_net_t::list_t m_nets;
|
||||
|
||||
protected:
|
||||
|
||||
// any derived netlist must override this ...
|
||||
virtual void vfatalerror(const char *format, va_list ap) const = 0;
|
||||
|
||||
protected:
|
||||
ATTR_COLD virtual void save_register()
|
||||
{
|
||||
//queue_t m_queue;
|
||||
save(NAME(m_time_ps));
|
||||
save(NAME(m_rem));
|
||||
save(NAME(m_div));
|
||||
netlist_object_t::save_register();
|
||||
}
|
||||
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
// performance
|
||||
int m_perf_out_processed;
|
||||
@ -978,9 +1083,8 @@ public:
|
||||
protected:
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
|
||||
|
||||
m_Q.init_object(*this, "Q");
|
||||
register_input("I", m_I, netlist_terminal_t::STATE_INP_ACTIVE);
|
||||
register_output("Q", m_Q);
|
||||
m_Q.initial(1);
|
||||
}
|
||||
|
||||
@ -1020,8 +1124,8 @@ public:
|
||||
protected:
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
m_I.init_object(*this, "I", netlist_terminal_t::STATE_INP_ACTIVE);
|
||||
m_Q.init_object(*this, "Q");
|
||||
register_input("I", m_I, netlist_terminal_t::STATE_INP_ACTIVE);
|
||||
register_output("Q", m_Q);
|
||||
m_Q.initial(0);
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,15 @@ public:
|
||||
ATTR_HOT inline bool empty() const { return (m_ptr < m_list); }
|
||||
ATTR_HOT inline void reset() { m_ptr = m_list - 1; }
|
||||
|
||||
ATTR_COLD void reset_and_free()
|
||||
{
|
||||
for (entry_t *i = m_list; i <= m_ptr; i++)
|
||||
{
|
||||
delete i->object();
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
//ATTR_HOT inline entry_t *item(int i) const { return &m_list[i]; }
|
||||
ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index].m_obj; }
|
||||
ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index].m_obj; }
|
||||
@ -142,6 +151,9 @@ public:
|
||||
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; }
|
||||
|
||||
ATTR_HOT inline const _Time *time_ptr() const { return &m_time; }
|
||||
ATTR_HOT inline _Element *object_ptr() const { return m_object; }
|
||||
private:
|
||||
_Time m_time;
|
||||
_Element *m_object;
|
||||
@ -153,6 +165,7 @@ public:
|
||||
clear();
|
||||
}
|
||||
|
||||
ATTR_HOT inline int capacity() const { return _Size; }
|
||||
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]); }
|
||||
|
||||
@ -193,6 +206,11 @@ public:
|
||||
m_end = &m_list[0];
|
||||
}
|
||||
|
||||
// save state support
|
||||
|
||||
ATTR_COLD entry_t *listptr() { return &m_list[0]; }
|
||||
ATTR_COLD int count() const { return m_end - m_list; }
|
||||
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
// profiling
|
||||
INT32 m_prof_start;
|
||||
|
@ -33,6 +33,10 @@ netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
|
||||
, m_proxy_cnt(0)
|
||||
{
|
||||
netlist.set_setup(this);
|
||||
}
|
||||
|
||||
void netlist_setup_t::init()
|
||||
{
|
||||
m_factory.initialize();
|
||||
NETLIST_NAME(base)(*this);
|
||||
}
|
||||
@ -45,6 +49,7 @@ netlist_setup_t::~netlist_setup_t()
|
||||
m_params.reset();
|
||||
m_terminals.reset();
|
||||
m_params_temp.reset();
|
||||
m_save.reset_and_free();
|
||||
|
||||
netlist().set_setup(NULL);
|
||||
|
||||
@ -132,6 +137,9 @@ pstring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
|
||||
case netlist_terminal_t::DEVICE:
|
||||
return "DEVICE";
|
||||
break;
|
||||
case netlist_terminal_t::NETLIST:
|
||||
return "NETLIST";
|
||||
break;
|
||||
}
|
||||
// FIXME: noreturn
|
||||
netlist().xfatalerror("Unknown object type %d\n", in.type());
|
||||
@ -161,10 +169,8 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
|
||||
break;
|
||||
case netlist_terminal_t::PARAM:
|
||||
{
|
||||
|
||||
netlist_param_t ¶m = dynamic_cast<netlist_param_t &>(obj);
|
||||
pstring temp = param.netdev().name() + "." + name;
|
||||
const pstring val = m_params_temp.find(temp);
|
||||
const pstring val = m_params_temp.find(name);
|
||||
if (val != "")
|
||||
{
|
||||
switch (param.param_type())
|
||||
@ -174,17 +180,17 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
|
||||
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", temp.cstr(), val->cstr()));
|
||||
double vald = 0;
|
||||
if (sscanf(val.cstr(), "%lf", &vald) != 1)
|
||||
netlist().xfatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val.cstr());
|
||||
netlist().xfatalerror("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
|
||||
dynamic_cast<netlist_param_double_t &>(param).initial(vald);
|
||||
}
|
||||
break;
|
||||
case netlist_param_t::INTEGER:
|
||||
case netlist_param_t::LOGIC:
|
||||
{
|
||||
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", temp.cstr(), val->cstr()));
|
||||
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", name.cstr(), val->cstr()));
|
||||
int vald = 0;
|
||||
if (sscanf(val.cstr(), "%d", &vald) != 1)
|
||||
netlist().xfatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val.cstr());
|
||||
netlist().xfatalerror("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
|
||||
dynamic_cast<netlist_param_int_t &>(param).initial(vald);
|
||||
}
|
||||
break;
|
||||
@ -213,14 +219,18 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
|
||||
}
|
||||
break;
|
||||
default:
|
||||
netlist().xfatalerror("Parameter is not supported %s : %s\n", temp.cstr(), val.cstr());
|
||||
netlist().xfatalerror("Parameter is not supported %s : %s\n", name.cstr(), val.cstr());
|
||||
}
|
||||
}
|
||||
if (!(m_params.add(temp, ¶m, false)==TMERR_NONE))
|
||||
if (!(m_params.add(name, ¶m, false)==TMERR_NONE))
|
||||
netlist().xfatalerror("Error adding parameter %s to parameter list\n", name.cstr());
|
||||
}
|
||||
break;
|
||||
case netlist_terminal_t::DEVICE:
|
||||
netlist().xfatalerror("Device registration not yet supported - \n", name.cstr());
|
||||
break;
|
||||
case netlist_terminal_t::NETLIST:
|
||||
netlist().xfatalerror("Netlist registration not yet supported - \n", name.cstr());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -462,9 +472,9 @@ void netlist_setup_t::connect_terminals(netlist_core_terminal_t &t1, netlist_cor
|
||||
NL_VERBOSE_OUT(("adding net ...\n"));
|
||||
netlist_net_t *anet = new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG);
|
||||
t1.set_net(*anet);
|
||||
m_netlist.solver()->m_nets.add(anet);
|
||||
//m_netlist.solver()->m_nets.add(anet);
|
||||
// FIXME: Nets should have a unique name
|
||||
t1.net().init_object(netlist(),"some net");
|
||||
t1.net().init_object(netlist(),"net." + t1.name() );
|
||||
t1.net().register_con(t2);
|
||||
t1.net().register_con(t1);
|
||||
}
|
||||
@ -533,6 +543,23 @@ void netlist_setup_t::resolve_inputs()
|
||||
//VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr()));
|
||||
}
|
||||
|
||||
#if 0
|
||||
NL_VERBOSE_OUT(("deleting empty nets ...\n"));
|
||||
|
||||
// delete empty nets ...
|
||||
for (netlist_net_t::list_t::entry_t *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
|
||||
{
|
||||
if (pn->object()->m_head == NULL)
|
||||
{
|
||||
NL_VERBOSE_OUT(("Deleting net ...\n"));
|
||||
netlist_net_t *to_delete = pn->object();
|
||||
netlist().m_nets.remove(to_delete);
|
||||
if (!to_delete->isRailNet())
|
||||
delete to_delete;
|
||||
pn--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (m_netlist.solver() != NULL)
|
||||
m_netlist.solver()->post_start();
|
||||
|
||||
@ -578,6 +605,7 @@ void netlist_setup_t::start_devices()
|
||||
netlist_device_t *dev = entry->object();
|
||||
dev->init(netlist(), entry->tag().cstr());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void netlist_setup_t::parse(const char *buf)
|
||||
|
@ -102,6 +102,8 @@ public:
|
||||
netlist_setup_t(netlist_base_t &netlist);
|
||||
~netlist_setup_t();
|
||||
|
||||
void init();
|
||||
|
||||
netlist_base_t &netlist() { return m_netlist; }
|
||||
const netlist_base_t &netlist() const { return m_netlist; }
|
||||
netlist_factory &factory() { return m_factory; }
|
||||
@ -133,6 +135,28 @@ public:
|
||||
|
||||
void print_stats();
|
||||
|
||||
/* save state */
|
||||
|
||||
struct save_entry_t
|
||||
{
|
||||
save_entry_t(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr) :
|
||||
m_name(stname), m_dt(dt), m_size(size), m_ptr(ptr) { }
|
||||
pstring m_name;
|
||||
netlist_data_type_e m_dt;
|
||||
int m_size;
|
||||
void *m_ptr;
|
||||
};
|
||||
|
||||
typedef netlist_list_t<save_entry_t *> save_entry_list_t;
|
||||
|
||||
void save_state_ptr(const pstring &stname, const netlist_data_type_e dt, const int size, void *ptr)
|
||||
{
|
||||
save_entry_t *p = new save_entry_t(stname, dt, size, ptr);
|
||||
m_save.add(p);
|
||||
}
|
||||
|
||||
save_entry_list_t m_save;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
@ -50,6 +50,9 @@ public:
|
||||
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
|
||||
ATTR_HOT inline const double as_double() const { return (double) m_time / (double) RESOLUTION; }
|
||||
|
||||
// for save states ....
|
||||
ATTR_HOT inline INTERNALTYPE *get_internaltype_ptr() { 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))); }
|
||||
|
@ -113,6 +113,31 @@ void fixedfreq_device::device_start()
|
||||
m_bitmap[1] = NULL;
|
||||
//m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
|
||||
recompute_parameters(false);
|
||||
|
||||
save_item(NAME(m_vid));
|
||||
save_item(NAME(m_last_x));
|
||||
save_item(NAME(m_last_y));
|
||||
save_item(NAME(m_last_time));
|
||||
save_item(NAME(m_line_time));
|
||||
save_item(NAME(m_last_hsync_time));
|
||||
save_item(NAME(m_last_vsync_time));
|
||||
save_item(NAME(m_refresh));
|
||||
save_item(NAME(m_clock_period));
|
||||
//save_item(NAME(m_bitmap[0]));
|
||||
//save_item(NAME(m_bitmap[1]));
|
||||
save_item(NAME(m_cur_bm));
|
||||
|
||||
/* sync separator */
|
||||
save_item(NAME(m_vint));
|
||||
save_item(NAME(m_int_trig));
|
||||
save_item(NAME(m_mult));
|
||||
|
||||
save_item(NAME(m_sig_vsync));
|
||||
save_item(NAME(m_sig_composite));
|
||||
save_item(NAME(m_sig_field));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void fixedfreq_device::device_reset()
|
||||
@ -122,6 +147,7 @@ void fixedfreq_device::device_reset()
|
||||
m_last_hsync_time = attotime::zero;
|
||||
m_last_vsync_time = attotime::zero;
|
||||
m_vint = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -982,5 +982,5 @@ ROM_START( pongf ) /* dummy to satisfy game entry*/
|
||||
ROM_END
|
||||
|
||||
|
||||
GAME( 1972, pong, 0, pong, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E)", 0 )
|
||||
GAME( 1972, pongf, 0, pongf, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E), no subcycles", 0 )
|
||||
GAME( 1972, pong, 0, pong, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E)", GAME_SUPPORTS_SAVE )
|
||||
GAME( 1972, pongf, 0, pongf, pong, driver_device, 0, ROT0, "Atari", "Pong (Rev E), no subcycles", GAME_SUPPORTS_SAVE )
|
||||
|
Loading…
Reference in New Issue
Block a user