Netlist maintenance:

- made frequency a obligatory parameter for CLOCK, MAINCLOCK and SOLVER
- fixed a bad memory corruption.
- added "owner" to save states. This allows to remove objects after they registered state.
- fixed VCCS and VCVS.
This commit is contained in:
Couriersud 2014-02-09 22:36:05 +00:00
parent f44b1831a6
commit c7eee90411
14 changed files with 199 additions and 160 deletions

View File

@ -450,6 +450,7 @@ ATTR_COLD void netlist_mame_device_t::save_state()
save_pointer((bool *) s->m_ptr, s->m_name, s->m_count);
break;
case DT_CUSTOM:
break;
case NOT_SUPPORTED:
default:
netlist().error("found unsupported save element %s\n", s->m_name.cstr());

View File

@ -12,44 +12,46 @@
// ----------------------------------------------------------------------------------------
NETLIB_START(VCCS)
{
configure(1.0, NETLIST_GMIN);
}
NETLIB_RESET(VCCS)
{
}
ATTR_COLD void NETLIB_NAME(VCCS)::configure(const double Gfac, const double GI)
{
register_param("G", m_G, 1.0);
register_param("RI", m_RI, 1.0 / NETLIST_GMIN);
register_terminal("IP", m_IP);
register_terminal("IN", m_IN);
register_terminal("OP", m_OP);
register_terminal("ON", m_ON);
m_OP1.init_object(*this, name() + ".OP1");
m_ON1.init_object(*this, name() + ".ON1");
register_terminal("_OP1", m_OP1);
register_terminal("_ON1", m_ON1);
const double m_mult = m_G.Value() * Gfac; // 1.0 ==> 1V ==> 1A
m_IP.set(GI);
m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
m_IN.set(GI);
m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
m_OP.set(m_mult, 0.0);
m_OP.m_otherterm = &m_IP;
m_OP1.set(-m_mult, 0.0);
m_OP1.m_otherterm = &m_IN;
m_ON.set(-m_mult, 0.0);
m_ON.m_otherterm = &m_IP;
m_ON1.set(m_mult, 0.0);
m_ON1.m_otherterm = &m_IN;
connect(m_OP, m_OP1);
connect(m_ON, m_ON1);
m_gfac = 1.0;
}
NETLIB_RESET(VCCS)
{
const double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A
const double GI = 1.0 / m_RI.Value();
m_IP.set(GI);
m_IN.set(GI);
m_OP.set(m_mult, 0.0);
m_OP1.set(-m_mult, 0.0);
m_ON.set(-m_mult, 0.0);
m_ON1.set(m_mult, 0.0);
}
NETLIB_UPDATE_PARAM(VCCS)
@ -60,10 +62,14 @@ NETLIB_UPDATE(VCCS)
{
/* only called if connected to a rail net ==> notify the solver to recalculate */
/* Big FIXME ... */
m_IP.net().solve();
m_IN.net().solve();
m_OP.net().solve();
m_ON.net().solve();
if (!m_IP.net().isRailNet())
m_IP.net().solve();
else if (!m_IN.net().isRailNet())
m_IN.net().solve();
else if (!m_OP.net().isRailNet())
m_OP.net().solve();
else if (!m_ON.net().isRailNet())
m_ON.net().solve();
}
// ----------------------------------------------------------------------------------------
@ -72,17 +78,13 @@ NETLIB_UPDATE(VCCS)
NETLIB_START(VCVS)
{
NETLIB_NAME(VCCS)::start();
register_param("RO", m_RO, 1.0);
const double gRO = 1.0 / m_RO.Value();
register_terminal("_OP2", m_OP2);
register_terminal("_ON2", m_ON2);
configure(gRO, NETLIST_GMIN);
m_OP2.init_object(*this, "OP2");
m_ON2.init_object(*this, "ON2");
m_OP2.set(gRO);
m_ON2.set(gRO);
m_OP2.m_otherterm = &m_ON2;
m_ON2.m_otherterm = &m_OP2;
@ -90,6 +92,15 @@ NETLIB_START(VCVS)
connect(m_ON2, m_ON1);
}
NETLIB_RESET(VCVS)
{
m_gfac = 1.0 / m_RO.Value();
NETLIB_NAME(VCCS)::reset();
m_OP2.set(1.0 / m_RO.Value());
m_ON2.set(1.0 / m_RO.Value());
}
NETLIB_UPDATE_PARAM(VCVS)
{
}

View File

@ -83,8 +83,6 @@ protected:
ATTR_COLD virtual void update_param();
ATTR_HOT ATTR_ALIGN void update();
ATTR_COLD void configure(const double Gfac, const double GI);
netlist_terminal_t m_OP;
netlist_terminal_t m_ON;
@ -95,6 +93,9 @@ protected:
netlist_terminal_t m_ON1;
netlist_param_double_t m_G;
netlist_param_double_t m_RI;
double m_gfac;
};
// ----------------------------------------------------------------------------------------
@ -133,6 +134,7 @@ public:
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param();
//ATTR_HOT ATTR_ALIGN void update();

View File

@ -19,9 +19,7 @@
ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &aowner)
{
/* make sure we loop at least once */
m_owner = &aowner;
m_owner = &aowner;
NL_VERBOSE_OUT(("New solver setup\n"));
@ -205,7 +203,10 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_ne
m_terms[m_term_num].net_other = ot;
m_terms[m_term_num].term = terms[i];
if (ot>=0)
{
m_term_num++;
SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go));
}
}
}
m_rail_start = m_term_num;
@ -221,7 +222,10 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_ne
m_terms[m_term_num].net_other = ot;
m_terms[m_term_num].term = terms[i];
if (ot<0)
{
m_term_num++;
SOLVER_VERBOSE_OUT(("found term with missing othernet %s\n", terms[i]->name().cstr()));
}
}
for (int i = 0; i < rails.count(); i++)
{
@ -229,6 +233,7 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_ne
m_terms[m_term_num].net_other = -1; //get_net_idx(&rails[i]->m_otherterm->net());
m_terms[m_term_num].term = rails[i];
m_term_num++;
SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go));
}
}
}
@ -258,6 +263,7 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE(
for (int i = 0; i < m_rail_start; i++)
{
terms_t &t = m_terms[i];
//printf("A %d %d %s %f %f\n",t.net_this, t.net_other, t.term->name().cstr(), t.term->m_gt, t.term->m_go);
RHS[t.net_this] += t.term->m_Idr;
A[t.net_this][t.net_this] += t.term->m_gt;
@ -280,6 +286,16 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
double (* RESTRICT RHS),
double (* RESTRICT x))
{
#if 0
for (int i = 0; i < N(); i++)
{
for (int k = 0; k < N(); k++)
printf("%f ", A[i][k]);
printf("| %f = %f \n", x[i], RHS[i]);
}
printf("\n");
#endif
for (int i = 0; i < N(); i++) {
#if 0
@ -322,8 +338,8 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
tmp += A[j][k] * x[k];
x[j] = (RHS[j] - tmp) / A[j][j];
}
#if 0
printf("Solution:\n");
for (int i = 0; i < N(); i++)
{
for (int k = 0; k < N(); k++)
@ -332,6 +348,7 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE(
}
printf("\n");
#endif
}
template <int m_N, int _storage_N>
@ -608,14 +625,14 @@ ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_n
if (net->m_head == NULL)
return;
/* add the net */
NL_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr()));
SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr()));
groups[cur_group].add(net);
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next)
{
NL_VERBOSE_OUT(("terminal %s\n", p->name().cstr()));
SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr()));
if (p->isType(netlist_terminal_t::TERMINAL))
{
NL_VERBOSE_OUT(("isterminal\n"));
SOLVER_VERBOSE_OUT(("isterminal\n"));
netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
netlist_net_t *other_net = &pt->m_otherterm->net();
if (!already_processed(groups, cur_group, other_net))
@ -805,9 +822,18 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start()
ms->m_resched_loops = m_resched_loops.Value();
ms->setup(groups[i], *this);
m_mat_solvers.add(ms);
SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), groups[i].first()->object()->m_head->name().cstr()));
SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), (*groups[i].first())->m_head->name().cstr()));
SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_dynamic() ? "dynamic" : "no dynamic"));
SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep"));
for (int j=0; j<groups[i].count(); j++)
{
SOLVER_VERBOSE_OUT(("Net %d: %s\n", j, groups[i][j]->name().cstr()));
netlist_net_t *n = groups[i][j];
for (netlist_core_terminal_t *p = n->m_head; p != NULL; p = p->m_update_list_next)
{
SOLVER_VERBOSE_OUT((" %s\n", p->name().cstr()));
}
}
}
}

View File

@ -13,8 +13,9 @@
// Macros
// ----------------------------------------------------------------------------------------
#define SOLVER(_name) \
NET_REGISTER_DEV(solver, _name)
#define SOLVER(_name, _freq) \
NET_REGISTER_DEV(solver, _name) \
PARAM(_name.FREQ, _freq)
// ----------------------------------------------------------------------------------------
// solver

View File

@ -86,9 +86,9 @@ void netlist_factory_t::initialize()
ENTRY(analog_input, ANALOG_INPUT, "IN")
ENTRY(log, LOG, "+I")
ENTRY(logD, LOGD, "+I,I2")
ENTRY(clock, CLOCK, "-") // FIXME
ENTRY(mainclock, MAINCLOCK, "-") // FIXME
ENTRY(solver, SOLVER, "-") // FIXME
ENTRY(clock, CLOCK, "FREQ")
ENTRY(mainclock, MAINCLOCK, "FREQ")
ENTRY(solver, SOLVER, "FREQ")
ENTRY(gnd, NETDEV_GND, "-")
ENTRY(switch2, SWITCH2, "+i1,i2")
ENTRY(nicRSFF, NETDEV_RSFF, "+S,R")

View File

@ -18,20 +18,22 @@
// ----------------------------------------------------------------------------------------
#define TTL_INPUT(_name, _v) \
NET_REGISTER_DEV(ttl_input, _name) \
NET_REGISTER_DEV(ttl_input, _name) \
PARAM(_name.IN, _v)
#define ANALOG_INPUT(_name, _v) \
NET_REGISTER_DEV(analog_input, _name) \
NET_REGISTER_DEV(analog_input, _name) \
PARAM(_name.IN, _v)
#define MAINCLOCK(_name) \
NET_REGISTER_DEV(mainclock, _name)
#define MAINCLOCK(_name, _freq) \
NET_REGISTER_DEV(mainclock, _name) \
PARAM(_name.FREQ, _freq)
#define CLOCK(_name) \
NET_REGISTER_DEV(clock, _name)
#define CLOCK(_name, _freq) \
NET_REGISTER_DEV(clock, _name) \
PARAM(_name.FREQ, _freq)
#define NETDEV_GND() \
#define NETDEV_GND() \
NET_REGISTER_DEV(gnd, GND)
// ----------------------------------------------------------------------------------------

View File

@ -34,9 +34,9 @@ netlist_queue_t::netlist_queue_t(netlist_base_t &nl)
void netlist_queue_t::register_state(pstate_manager_t &manager, const pstring &module)
{
NL_VERBOSE_OUT(("register_state\n"));
manager.save_item(m_qsize, module + "." + "qsize");
manager.save_item(m_times, module + "." + "times");
manager.save_item(&(m_name[0][0]), module + "." + "names", sizeof(m_name));
manager.save_item(m_qsize, this, module + "." + "qsize");
manager.save_item(m_times, this, module + "." + "times");
manager.save_item(&(m_name[0][0]), this, module + "." + "names", sizeof(m_name));
}
void netlist_queue_t::on_pre_save()
@ -140,18 +140,18 @@ static void tagmap_free_entries(T &tm)
netlist_base_t::~netlist_base_t()
{
tagmap_free_entries<tagmap_devices_t>(m_devices);
netlist_net_t * const *p = m_nets.first();
while (p != NULL)
for (int i=0; i < m_nets.count(); i++)
{
netlist_net_t * const *pn = m_nets.next(p);
if (!(*p)->isRailNet())
delete (*p);
p = pn;
if (!m_nets[i]->isRailNet())
{
delete m_nets[i];
}
}
m_nets.reset();
tagmap_free_entries<tagmap_devices_t>(m_devices);
pstring::resetmem();
}
@ -407,7 +407,6 @@ ATTR_COLD void netlist_device_t::register_output(const pstring &name, netlist_ou
ATTR_COLD void netlist_device_t::register_input(const pstring &name, netlist_input_t &inp)
{
// FIXME: change register_object as well
inp.m_family_desc = this->m_family_desc;
setup().register_object(*this, name, inp);
m_terminals.add(inp.name());
@ -425,7 +424,6 @@ ATTR_COLD void netlist_device_t::register_param(const pstring &sname, C &param,
pstring fullname = this->name() + "." + sname;
param.init_object(*this, fullname);
param.initial(initialVal);
//FIXME: pass fullname from above
setup().register_object(*this, fullname, param);
}
@ -456,6 +454,12 @@ ATTR_COLD netlist_net_t::netlist_net_t(const type_t atype, const family_t afamil
m_cur.Analog = 0.0;
};
ATTR_COLD netlist_net_t::~netlist_net_t()
{
netlist().remove_save_items(this);
}
ATTR_COLD void netlist_net_t::reset()
{
m_last.Analog = 0.0;

View File

@ -62,7 +62,6 @@
* This would however introduce macro devices for RC, diodes and transistors again.
*
* ====================================================================================
* FIXME: Terminals are not yet implemented.
*
* Instead, the following approach in case of a pure terminal/input network is taken:
*
@ -557,7 +556,6 @@ public:
friend class netlist_analog_output_t;
friend class netlist_setup_t;
// FIXME: union does not work
struct hybrid_t
{
inline hybrid_t() : Q(0), Analog(0.0) {}
@ -566,6 +564,8 @@ public:
};
ATTR_COLD netlist_net_t(const type_t atype, const family_t afamily);
ATTR_COLD virtual ~netlist_net_t();
ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname);
ATTR_COLD void register_con(netlist_core_terminal_t &terminal);
@ -638,28 +638,13 @@ public:
typedef netlist_list_t<netlist_terminal_t *> terminal_list_t;
terminal_list_t m_terms;
terminal_list_t m_rails; // FIXME: Make the solver use this !
terminal_list_t m_rails;
netlist_matrix_solver_t *m_solver;
ATTR_HOT void solve();
netlist_core_terminal_t *m_head;
/* use this to register state.... */
ATTR_COLD virtual void late_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();
}
protected: //FIXME: needed by current solver code
UINT32 m_num_cons;
@ -671,13 +656,18 @@ public:
protected:
/* we don't use this to save state
* because we may get deleted again ...
* FIXME: save_register should be called after setup is complete
*/
ATTR_COLD virtual void save_register()
{
//assert_always(false, "trying too early to register state in netlist_net_t");
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();
}
ATTR_COLD virtual void reset();
@ -1235,7 +1225,6 @@ ATTR_HOT inline void netlist_net_t::push_to_queue(const netlist_time delay)
{
if (is_queued())
return;
// if (m_in_queue == 1) return; FIXME: check this at some time
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
if (m_in_queue)

View File

@ -270,22 +270,6 @@ const pstring netlist_setup_t::resolve_alias(const pstring &name) const
temp = m_alias.find(ret);
} while (temp != "");
int p = ret.find(".[");
if (p > 0)
{
pstring dname = ret;
netlist_device_t *dev = netlist().m_devices.find(dname.substr(0,p));
if (dev == NULL)
netlist().error("Device for %s not found\n", name.cstr());
int c = atoi(ret.substr(p+2,ret.len()-p-3));
temp = dev->m_terminals[c];
// reresolve ....
do {
ret = temp;
temp = m_alias.find(ret);
} while (temp != "");
}
NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr()));
return ret;
}
@ -447,7 +431,6 @@ void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_i
}
}
// FIXME: optimize code ...
void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out)
{
if (out.isFamily(netlist_terminal_t::ANALOG))
@ -521,18 +504,16 @@ void netlist_setup_t::connect(netlist_core_terminal_t &t1_in, netlist_core_termi
netlist_core_terminal_t &t1 = resolve_proxy(t1_in);
netlist_core_terminal_t &t2 = resolve_proxy(t2_in);
// FIXME: amend device design so that warnings can be turned into errors
// Only variable inputs have this issue
if (t1.isType(netlist_core_terminal_t::OUTPUT) && t2.isType(netlist_core_terminal_t::INPUT))
{
if (t2.has_net())
NL_VERBOSE_OUT(("Input %s already connected\n", t2.name().cstr()));
netlist().error("Input %s already connected\n", t2.name().cstr());
connect_input_output(dynamic_cast<netlist_input_t &>(t2), dynamic_cast<netlist_output_t &>(t1));
}
else if (t1.isType(netlist_core_terminal_t::INPUT) && t2.isType(netlist_core_terminal_t::OUTPUT))
{
if (t1.has_net())
NL_VERBOSE_OUT(("Input %s already connected\n", t1.name().cstr()));
netlist().error("Input %s already connected\n", t1.name().cstr());
connect_input_output(dynamic_cast<netlist_input_t &>(t1), dynamic_cast<netlist_output_t &>(t2));
}
else if (t1.isType(netlist_core_terminal_t::OUTPUT) && t2.isType(netlist_core_terminal_t::TERMINAL))
@ -585,24 +566,24 @@ void netlist_setup_t::resolve_inputs()
netlist().log("deleting empty nets ...");
// delete empty nets ...
netlist_net_t::list_t todelete;
for (netlist_net_t *const *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
{
if ((*pn)->m_head == NULL)
{
netlist().log("Deleting net %s ...", (*pn)->name().cstr());
netlist_net_t *to_delete = *pn;
netlist().m_nets.remove(to_delete);
if (!to_delete->isRailNet())
delete to_delete;
pn--;
todelete.add(*pn);
}
}
/* now that nets were deleted ... register all net items */
netlist().log("late state saving for nets ...");
for (netlist_net_t * const * pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
(*pn)->late_save_register();
for (int i=0; i < todelete.count(); i++)
{
netlist().log("Deleting net %s ...", todelete[i]->name().cstr());
netlist().m_nets.remove(todelete[i]);
if (!todelete[i]->isRailNet())
delete todelete[i];
}
pstring errstr("");

View File

@ -12,7 +12,7 @@ ATTR_COLD pstate_manager_t::~pstate_manager_t()
ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const int size, const int count, void *ptr)
ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const void *owner, const int size, const int count, void *ptr)
{
pstring fullname = stname;
ATTR_UNUSED pstring ts[] = {
@ -25,19 +25,36 @@ ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pst
};
NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr));
pstate_entry_t *p = new pstate_entry_t(stname, dt, size, count, ptr);
pstate_entry_t *p = new pstate_entry_t(stname, dt, owner, size, count, ptr);
m_save.add(p);
}
ATTR_COLD void pstate_manager_t::remove_save_items(const void *owner)
{
pstate_entry_t::list_t todelete;
for (int i=0; i < m_save.count(); i++)
{
if (m_save[i]->m_owner == owner)
todelete.add(m_save[i]);
}
for (int i=0; i < todelete.count(); i++)
{
m_save.remove(todelete[i]);
}
todelete.reset_and_free();
}
ATTR_COLD void pstate_manager_t::pre_save()
{
for (int i=0; i < m_callback.count(); i++)
m_callback[i]->on_pre_save();
for (int i=0; i < m_save.count(); i++)
if (m_save[i]->m_dt == DT_CUSTOM)
m_save[i]->m_callback->on_pre_save();
}
ATTR_COLD void pstate_manager_t::post_load()
{
for (int i=0; i < m_callback.count(); i++)
m_callback[i]->on_post_load();
for (int i=0; i < m_save.count(); i++)
if (m_save[i]->m_dt == DT_CUSTOM)
m_save[i]->m_callback->on_post_load();
}

View File

@ -21,7 +21,7 @@
#define PSTATE_INTERFACE(obj, manager, module) \
template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \
{ \
manager->save_item(state, module + "." + stname); \
manager->save_item(state, this, module + "." + stname); \
}
enum pstate_data_type_e {
@ -50,19 +50,6 @@ NETLIST_SAVE_TYPE(UINT32, DT_INT);
NETLIST_SAVE_TYPE(INT32, DT_INT);
//NETLIST_SAVE_TYPE(netlist_time::INTERNALTYPE, DT_INT64);
struct pstate_entry_t
{
typedef netlist_list_t<pstate_entry_t *> list_t;
pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const int size, const int count, void *ptr) :
m_name(stname), m_dt(dt), m_size(size), m_count(count), m_ptr(ptr) { }
pstring m_name;
pstate_data_type_e m_dt;
int m_size;
int m_count;
void *m_ptr;
};
class pstate_manager_t;
class pstate_callback_t
@ -78,50 +65,71 @@ public:
protected:
};
struct pstate_entry_t
{
typedef netlist_list_t<pstate_entry_t *> list_t;
pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const void *owner,
const int size, const int count, void *ptr)
: m_name(stname), m_dt(dt), m_owner(owner), m_callback(NULL), m_size(size), m_count(count), m_ptr(ptr) { }
pstate_entry_t(const pstring &stname, const void *owner, pstate_callback_t *callback)
: m_name(stname), m_dt(DT_CUSTOM), m_owner(owner), m_callback(callback), m_size(0), m_count(0), m_ptr(NULL) { }
pstring m_name;
const pstate_data_type_e m_dt;
const void *m_owner;
pstate_callback_t *m_callback;
const int m_size;
const int m_count;
void *m_ptr;
};
class pstate_manager_t
{
public:
ATTR_COLD ~pstate_manager_t();
template<typename C> ATTR_COLD void save_item(C &state, const pstring &stname)
template<typename C> ATTR_COLD void save_item(C &state, const void *owner, const pstring &stname)
{
save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), 1, &state);
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), 1, &state);
}
template<typename C, std::size_t N> ATTR_COLD void save_item(C (&state)[N], const pstring &stname)
template<typename C, std::size_t N> ATTR_COLD void save_item(C (&state)[N], const void *owner, const pstring &stname)
{
save_state_ptr(stname, nl_datatype<C>::type, sizeof(state[0]), N, &(state[0]));
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(state[0]), N, &(state[0]));
}
template<typename C> ATTR_COLD void save_item(C *state, const pstring &stname, const int count)
template<typename C> ATTR_COLD void save_item(C *state, const void *owner, const pstring &stname, const int count)
{
save_state_ptr(stname, nl_datatype<C>::type, sizeof(C), count, state);
save_state_ptr(stname, nl_datatype<C>::type, owner, sizeof(C), count, state);
}
ATTR_COLD void pre_save();
ATTR_COLD void post_load();
ATTR_COLD void remove_save_items(const void *owner);
inline const pstate_entry_t::list_t &save_list() const { return m_save; }
protected:
ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const int size, const int count, void *ptr);
ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const void *owner, const int size, const int count, void *ptr);
private:
pstate_entry_t::list_t m_save;
pstate_callback_t::list_t m_callback;
};
template<> ATTR_COLD inline void pstate_manager_t::save_item(pstate_callback_t &state, const pstring &stname)
template<> ATTR_COLD inline void pstate_manager_t::save_item(pstate_callback_t &state, const void *owner, const pstring &stname)
{
//save_state_ptr(stname, DT_CUSTOM, 0, 1, &state);
m_callback.add(&state);
pstate_entry_t *p = new pstate_entry_t(stname, owner, &state);
m_save.add(p);
state.register_state(*this, stname);
}
template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist_time &nlt, const pstring &stname)
template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist_time &nlt, const void *owner, const pstring &stname)
{
save_state_ptr(stname, DT_INT64, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr());
save_state_ptr(stname, DT_INT64, owner, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr());
}

View File

@ -82,8 +82,7 @@ static NETLIST_START(nl_1942)
/* Standard stuff */
SOLVER(Solver)
PARAM(Solver.FREQ, 48000)
SOLVER(Solver, 48000)
ANALOG_INPUT(V5, 5)
/* AY 8910 internal resistors */

View File

@ -94,8 +94,7 @@ enum input_changed_enum
static NETLIST_START(pong_schematics)
SOLVER(Solver)
PARAM(Solver.FREQ, 48000)
SOLVER(Solver, 48000)
PARAM(Solver.ACCURACY, 1e-4) // works and is sufficient
ANALOG_INPUT(V5, 5)
@ -114,9 +113,8 @@ static NETLIST_START(pong_schematics)
#else
/* abstracting this, performance increases by 40%
* No surprise, the clock is extremely expensive */
MAINCLOCK(clk)
//CLOCK(clk)
PARAM(clk.FREQ, 7159000.0)
MAINCLOCK(clk, 7159000.0)
//CLOCK(clk, 7159000.0)
#endif
#else
// benchmarking ...