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); save_pointer((bool *) s->m_ptr, s->m_name, s->m_count);
break; break;
case DT_CUSTOM: case DT_CUSTOM:
break;
case NOT_SUPPORTED: case NOT_SUPPORTED:
default: default:
netlist().error("found unsupported save element %s\n", s->m_name.cstr()); netlist().error("found unsupported save element %s\n", s->m_name.cstr());

View File

@ -12,44 +12,46 @@
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
NETLIB_START(VCCS) 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("G", m_G, 1.0);
register_param("RI", m_RI, 1.0 / NETLIST_GMIN);
register_terminal("IP", m_IP); register_terminal("IP", m_IP);
register_terminal("IN", m_IN); register_terminal("IN", m_IN);
register_terminal("OP", m_OP); register_terminal("OP", m_OP);
register_terminal("ON", m_ON); register_terminal("ON", m_ON);
m_OP1.init_object(*this, name() + ".OP1"); register_terminal("_OP1", m_OP1);
m_ON1.init_object(*this, name() + ".ON1"); 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_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_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_OP.m_otherterm = &m_IP;
m_OP1.set(-m_mult, 0.0);
m_OP1.m_otherterm = &m_IN; m_OP1.m_otherterm = &m_IN;
m_ON.set(-m_mult, 0.0);
m_ON.m_otherterm = &m_IP; m_ON.m_otherterm = &m_IP;
m_ON1.set(m_mult, 0.0);
m_ON1.m_otherterm = &m_IN; m_ON1.m_otherterm = &m_IN;
connect(m_OP, m_OP1); connect(m_OP, m_OP1);
connect(m_ON, m_ON1); 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) NETLIB_UPDATE_PARAM(VCCS)
@ -60,10 +62,14 @@ NETLIB_UPDATE(VCCS)
{ {
/* only called if connected to a rail net ==> notify the solver to recalculate */ /* only called if connected to a rail net ==> notify the solver to recalculate */
/* Big FIXME ... */ /* Big FIXME ... */
m_IP.net().solve(); if (!m_IP.net().isRailNet())
m_IN.net().solve(); m_IP.net().solve();
m_OP.net().solve(); else if (!m_IN.net().isRailNet())
m_ON.net().solve(); 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_START(VCVS)
{ {
NETLIB_NAME(VCCS)::start();
register_param("RO", m_RO, 1.0); 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_OP2.m_otherterm = &m_ON2;
m_ON2.m_otherterm = &m_OP2; m_ON2.m_otherterm = &m_OP2;
@ -90,6 +92,15 @@ NETLIB_START(VCVS)
connect(m_ON2, m_ON1); 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) NETLIB_UPDATE_PARAM(VCVS)
{ {
} }

View File

@ -83,8 +83,6 @@ protected:
ATTR_COLD virtual void update_param(); ATTR_COLD virtual void update_param();
ATTR_HOT ATTR_ALIGN void update(); 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_OP;
netlist_terminal_t m_ON; netlist_terminal_t m_ON;
@ -95,6 +93,9 @@ protected:
netlist_terminal_t m_ON1; netlist_terminal_t m_ON1;
netlist_param_double_t m_G; netlist_param_double_t m_G;
netlist_param_double_t m_RI;
double m_gfac;
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -133,6 +134,7 @@ public:
protected: protected:
ATTR_COLD virtual void start(); ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param(); ATTR_COLD virtual void update_param();
//ATTR_HOT ATTR_ALIGN void update(); //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) 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")); 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].net_other = ot;
m_terms[m_term_num].term = terms[i]; m_terms[m_term_num].term = terms[i];
if (ot>=0) if (ot>=0)
{
m_term_num++; 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; 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].net_other = ot;
m_terms[m_term_num].term = terms[i]; m_terms[m_term_num].term = terms[i];
if (ot<0) if (ot<0)
{
m_term_num++; 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++) 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].net_other = -1; //get_net_idx(&rails[i]->m_otherterm->net());
m_terms[m_term_num].term = rails[i]; m_terms[m_term_num].term = rails[i];
m_term_num++; 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++) for (int i = 0; i < m_rail_start; i++)
{ {
terms_t &t = m_terms[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; RHS[t.net_this] += t.term->m_Idr;
A[t.net_this][t.net_this] += t.term->m_gt; 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 RHS),
double (* RESTRICT x)) 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++) { for (int i = 0; i < N(); i++) {
#if 0 #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]; tmp += A[j][k] * x[k];
x[j] = (RHS[j] - tmp) / A[j][j]; x[j] = (RHS[j] - tmp) / A[j][j];
} }
#if 0 #if 0
printf("Solution:\n");
for (int i = 0; i < N(); i++) for (int i = 0; i < N(); i++)
{ {
for (int k = 0; k < N(); k++) 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"); printf("\n");
#endif #endif
} }
template <int m_N, int _storage_N> 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) if (net->m_head == NULL)
return; return;
/* add the net */ /* 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); groups[cur_group].add(net);
for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next) 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)) 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_terminal_t *pt = static_cast<netlist_terminal_t *>(p);
netlist_net_t *other_net = &pt->m_otherterm->net(); netlist_net_t *other_net = &pt->m_otherterm->net();
if (!already_processed(groups, cur_group, other_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->m_resched_loops = m_resched_loops.Value();
ms->setup(groups[i], *this); ms->setup(groups[i], *this);
m_mat_solvers.add(ms); 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_dynamic() ? "dynamic" : "no dynamic"));
SOLVER_VERBOSE_OUT((" has %s elements\n", ms->is_timestep() ? "timestep" : "no timestep")); 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 // Macros
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
#define SOLVER(_name) \ #define SOLVER(_name, _freq) \
NET_REGISTER_DEV(solver, _name) NET_REGISTER_DEV(solver, _name) \
PARAM(_name.FREQ, _freq)
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// solver // solver

View File

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

View File

@ -18,20 +18,22 @@
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
#define TTL_INPUT(_name, _v) \ #define TTL_INPUT(_name, _v) \
NET_REGISTER_DEV(ttl_input, _name) \ NET_REGISTER_DEV(ttl_input, _name) \
PARAM(_name.IN, _v) PARAM(_name.IN, _v)
#define ANALOG_INPUT(_name, _v) \ #define ANALOG_INPUT(_name, _v) \
NET_REGISTER_DEV(analog_input, _name) \ NET_REGISTER_DEV(analog_input, _name) \
PARAM(_name.IN, _v) PARAM(_name.IN, _v)
#define MAINCLOCK(_name) \ #define MAINCLOCK(_name, _freq) \
NET_REGISTER_DEV(mainclock, _name) NET_REGISTER_DEV(mainclock, _name) \
PARAM(_name.FREQ, _freq)
#define CLOCK(_name) \ #define CLOCK(_name, _freq) \
NET_REGISTER_DEV(clock, _name) NET_REGISTER_DEV(clock, _name) \
PARAM(_name.FREQ, _freq)
#define NETDEV_GND() \ #define NETDEV_GND() \
NET_REGISTER_DEV(gnd, 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) void netlist_queue_t::register_state(pstate_manager_t &manager, const pstring &module)
{ {
NL_VERBOSE_OUT(("register_state\n")); NL_VERBOSE_OUT(("register_state\n"));
manager.save_item(m_qsize, module + "." + "qsize"); manager.save_item(m_qsize, this, module + "." + "qsize");
manager.save_item(m_times, module + "." + "times"); manager.save_item(m_times, this, module + "." + "times");
manager.save_item(&(m_name[0][0]), module + "." + "names", sizeof(m_name)); manager.save_item(&(m_name[0][0]), this, module + "." + "names", sizeof(m_name));
} }
void netlist_queue_t::on_pre_save() void netlist_queue_t::on_pre_save()
@ -140,18 +140,18 @@ static void tagmap_free_entries(T &tm)
netlist_base_t::~netlist_base_t() netlist_base_t::~netlist_base_t()
{ {
tagmap_free_entries<tagmap_devices_t>(m_devices); for (int i=0; i < m_nets.count(); i++)
netlist_net_t * const *p = m_nets.first();
while (p != NULL)
{ {
netlist_net_t * const *pn = m_nets.next(p); if (!m_nets[i]->isRailNet())
if (!(*p)->isRailNet()) {
delete (*p); delete m_nets[i];
p = pn; }
} }
m_nets.reset(); m_nets.reset();
tagmap_free_entries<tagmap_devices_t>(m_devices);
pstring::resetmem(); 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) 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; inp.m_family_desc = this->m_family_desc;
setup().register_object(*this, name, inp); setup().register_object(*this, name, inp);
m_terminals.add(inp.name()); 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; pstring fullname = this->name() + "." + sname;
param.init_object(*this, fullname); param.init_object(*this, fullname);
param.initial(initialVal); param.initial(initialVal);
//FIXME: pass fullname from above
setup().register_object(*this, fullname, param); 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; 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() ATTR_COLD void netlist_net_t::reset()
{ {
m_last.Analog = 0.0; m_last.Analog = 0.0;

View File

@ -62,7 +62,6 @@
* This would however introduce macro devices for RC, diodes and transistors again. * 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: * 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_analog_output_t;
friend class netlist_setup_t; friend class netlist_setup_t;
// FIXME: union does not work
struct hybrid_t struct hybrid_t
{ {
inline hybrid_t() : Q(0), Analog(0.0) {} 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 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 init_object(netlist_base_t &nl, const pstring &aname);
ATTR_COLD void register_con(netlist_core_terminal_t &terminal); 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; typedef netlist_list_t<netlist_terminal_t *> terminal_list_t;
terminal_list_t m_terms; 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; netlist_matrix_solver_t *m_solver;
ATTR_HOT void solve(); ATTR_HOT void solve();
netlist_core_terminal_t *m_head; 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 protected: //FIXME: needed by current solver code
UINT32 m_num_cons; UINT32 m_num_cons;
@ -671,13 +656,18 @@ public:
protected: 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() 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(); 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()) if (is_queued())
return; return;
// if (m_in_queue == 1) return; FIXME: check this at some time
m_time = netlist().time() + delay; m_time = netlist().time() + delay;
m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */ m_in_queue = (m_active > 0) ? 1 : 0; /* queued ? */
if (m_in_queue) 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); temp = m_alias.find(ret);
} while (temp != ""); } 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())); NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr()));
return ret; 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) void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out)
{ {
if (out.isFamily(netlist_terminal_t::ANALOG)) 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 &t1 = resolve_proxy(t1_in);
netlist_core_terminal_t &t2 = resolve_proxy(t2_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 (t1.isType(netlist_core_terminal_t::OUTPUT) && t2.isType(netlist_core_terminal_t::INPUT))
{ {
if (t2.has_net()) 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)); 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)) else if (t1.isType(netlist_core_terminal_t::INPUT) && t2.isType(netlist_core_terminal_t::OUTPUT))
{ {
if (t1.has_net()) 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)); 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)) 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 ..."); netlist().log("deleting empty nets ...");
// delete 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)) for (netlist_net_t *const *pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn))
{ {
if ((*pn)->m_head == NULL) if ((*pn)->m_head == NULL)
{ {
netlist().log("Deleting net %s ...", (*pn)->name().cstr()); todelete.add(*pn);
netlist_net_t *to_delete = *pn;
netlist().m_nets.remove(to_delete);
if (!to_delete->isRailNet())
delete to_delete;
pn--;
} }
} }
/* now that nets were deleted ... register all net items */ for (int i=0; i < todelete.count(); i++)
netlist().log("late state saving for nets ..."); {
netlist().log("Deleting net %s ...", todelete[i]->name().cstr());
for (netlist_net_t * const * pn = netlist().m_nets.first(); pn != NULL; pn = netlist().m_nets.next(pn)) netlist().m_nets.remove(todelete[i]);
(*pn)->late_save_register(); if (!todelete[i]->isRailNet())
delete todelete[i];
}
pstring errstr(""); 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; pstring fullname = stname;
ATTR_UNUSED pstring ts[] = { 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)); 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); 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() ATTR_COLD void pstate_manager_t::pre_save()
{ {
for (int i=0; i < m_callback.count(); i++) for (int i=0; i < m_save.count(); i++)
m_callback[i]->on_pre_save(); if (m_save[i]->m_dt == DT_CUSTOM)
m_save[i]->m_callback->on_pre_save();
} }
ATTR_COLD void pstate_manager_t::post_load() ATTR_COLD void pstate_manager_t::post_load()
{ {
for (int i=0; i < m_callback.count(); i++) for (int i=0; i < m_save.count(); i++)
m_callback[i]->on_post_load(); 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) \ #define PSTATE_INTERFACE(obj, manager, module) \
template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \ 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 { enum pstate_data_type_e {
@ -50,19 +50,6 @@ NETLIST_SAVE_TYPE(UINT32, DT_INT);
NETLIST_SAVE_TYPE(INT32, DT_INT); NETLIST_SAVE_TYPE(INT32, DT_INT);
//NETLIST_SAVE_TYPE(netlist_time::INTERNALTYPE, DT_INT64); //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_manager_t;
class pstate_callback_t class pstate_callback_t
@ -78,50 +65,71 @@ public:
protected: 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 class pstate_manager_t
{ {
public: public:
ATTR_COLD ~pstate_manager_t(); 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 pre_save();
ATTR_COLD void post_load(); 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; } inline const pstate_entry_t::list_t &save_list() const { return m_save; }
protected: 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: private:
pstate_entry_t::list_t m_save; 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); //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); 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 */ /* Standard stuff */
SOLVER(Solver) SOLVER(Solver, 48000)
PARAM(Solver.FREQ, 48000)
ANALOG_INPUT(V5, 5) ANALOG_INPUT(V5, 5)
/* AY 8910 internal resistors */ /* AY 8910 internal resistors */

View File

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