mirror of
https://github.com/libretro/mame.git
synced 2024-11-23 17:39:50 +00:00
Netlist: Added pascal like strings (pstring) class. These use only size(void *) in objects. Uses reference counter to share identical string between various pstrings.
In addition, fixed some bugs and added auto-sizing to netlist_list_t. There shouldn't be memory holes left now, apart from memory allocated in a static class factory.
This commit is contained in:
parent
0d0f072d59
commit
cb6f1d0194
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -2144,6 +2144,8 @@ src/emu/netlist/nl_parser.h svneol=native#text/plain
|
||||
src/emu/netlist/nl_setup.c svneol=native#text/plain
|
||||
src/emu/netlist/nl_setup.h svneol=native#text/plain
|
||||
src/emu/netlist/nl_time.h svneol=native#text/plain
|
||||
src/emu/netlist/pstring.c svneol=native#text/plain
|
||||
src/emu/netlist/pstring.h svneol=native#text/plain
|
||||
src/emu/network.c svneol=native#text/plain
|
||||
src/emu/network.h svneol=native#text/plain
|
||||
src/emu/output.c svneol=native#text/plain
|
||||
|
@ -49,8 +49,6 @@
|
||||
#include "netlist/nl_setup.h"
|
||||
#include "netlist/devices/net_lib.h"
|
||||
|
||||
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_mame_device
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -91,8 +89,8 @@ void netlist_mame_device::device_start()
|
||||
m_setup->start_devices();
|
||||
|
||||
bool allok = true;
|
||||
for (on_device_start **ods = m_device_start_list.first(); ods <= m_device_start_list.last(); ods++)
|
||||
allok &= (*ods)->OnDeviceStart();
|
||||
for (device_start_list_t::entry_t *ods = m_device_start_list.first(); ods != NULL; ods = m_device_start_list.next(ods))
|
||||
allok &= ods->object()->OnDeviceStart();
|
||||
|
||||
if (!allok)
|
||||
fatalerror("required elements not found\n");
|
||||
|
@ -118,7 +118,9 @@ public:
|
||||
netlist_setup_t &setup() { return *m_setup; }
|
||||
netlist_t &netlist() { return *m_netlist; }
|
||||
|
||||
netlist_list_t<on_device_start *> m_device_start_list;
|
||||
typedef netlist_list_t<on_device_start *> device_start_list_t;
|
||||
|
||||
device_start_list_t m_device_start_list;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
|
@ -987,7 +987,7 @@ static const net_device_t_base_factory *netregistry[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
netlist_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup)
|
||||
netlist_device_t *net_create_device_by_classname(const pstring &classname, netlist_setup_t &setup)
|
||||
{
|
||||
const net_device_t_base_factory **p = &netregistry[0];
|
||||
while (*p != NULL)
|
||||
@ -1003,7 +1003,7 @@ netlist_device_t *net_create_device_by_classname(const astring &classname, netli
|
||||
return NULL; // appease code analysis
|
||||
}
|
||||
|
||||
netlist_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup)
|
||||
netlist_device_t *net_create_device_by_name(const pstring &name, netlist_setup_t &setup)
|
||||
{
|
||||
const net_device_t_base_factory **p = &netregistry[0];
|
||||
while (*p != NULL)
|
||||
|
@ -98,13 +98,24 @@ NETLIB_UPDATE_PARAM(solver)
|
||||
m_inc = netlist_time::from_hz(m_freq.Value());
|
||||
}
|
||||
|
||||
NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
|
||||
{
|
||||
net_list_t::entry_t *p = m_nets.first();
|
||||
while (p != NULL)
|
||||
{
|
||||
net_list_t::entry_t *pn = m_nets.next(pn);
|
||||
delete pn->object();
|
||||
p = pn;
|
||||
}
|
||||
}
|
||||
|
||||
NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
{
|
||||
NL_VERBOSE_OUT(("post start solver ...\n"));
|
||||
for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
NL_VERBOSE_OUT(("setting up net\n"));
|
||||
for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
|
||||
{
|
||||
switch (p->type())
|
||||
{
|
||||
@ -121,11 +132,11 @@ NETLIB_FUNC_VOID(solver, post_start, ())
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((*pn)->m_head == NULL)
|
||||
if (pn->object()->m_head == NULL)
|
||||
{
|
||||
NL_VERBOSE_OUT(("Deleting net ...\n"));
|
||||
netlist_net_t *to_delete = *pn;
|
||||
m_nets.del(to_delete);
|
||||
netlist_net_t *to_delete = pn->object();
|
||||
m_nets.remove(to_delete);
|
||||
delete to_delete;
|
||||
pn--;
|
||||
}
|
||||
@ -146,15 +157,15 @@ NETLIB_UPDATE(solver)
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
for (netlist_terminal_t **p = m_terms.first(); p != NULL; p = m_terms.next(p))
|
||||
(*p)->netdev().step_time(delta.as_double());
|
||||
for (terminal_list_t::entry_t *p = m_terms.first(); p != NULL; p = m_terms.next(p))
|
||||
p->object()->netdev().step_time(delta.as_double());
|
||||
}
|
||||
for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
for (net_list_t::entry_t *pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn))
|
||||
{
|
||||
double gtot = 0;
|
||||
double iIdr = 0;
|
||||
|
||||
for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next)
|
||||
for (netlist_terminal_t *p = pn->object()->m_head; p != NULL; p = p->m_update_list_next)
|
||||
{
|
||||
if (p->isType(netlist_terminal_t::TERMINAL))
|
||||
{
|
||||
@ -165,9 +176,9 @@ NETLIB_UPDATE(solver)
|
||||
}
|
||||
|
||||
double new_val = iIdr / gtot;
|
||||
if (fabs(new_val - (*pn)->m_cur.Analog) > 1e-4)
|
||||
if (fabs(new_val - pn->object()->m_cur.Analog) > 1e-4)
|
||||
resched = true;
|
||||
(*pn)->m_cur.Analog = (*pn)->m_new.Analog = new_val;
|
||||
pn->object()->m_cur.Analog = pn->object()->m_new.Analog = new_val;
|
||||
|
||||
NL_VERBOSE_OUT(("Info: %d\n", (*pn)->m_num_cons));
|
||||
NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val));
|
||||
@ -179,8 +190,8 @@ NETLIB_UPDATE(solver)
|
||||
else
|
||||
{
|
||||
/* update all inputs connected */
|
||||
for (netlist_terminal_t **p = m_inps.first(); p != NULL; p = m_inps.next(p))
|
||||
(*p)->netdev().update_dev();
|
||||
for (terminal_list_t::entry_t *p = m_inps.first(); p != NULL; p = m_inps.next(p))
|
||||
p->object()->netdev().update_dev();
|
||||
/* step circuit */
|
||||
if (!m_Q.net().is_queued())
|
||||
{
|
||||
|
@ -96,6 +96,9 @@ NETLIB_DEVICE_WITH_PARAMS(clock,
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
NETLIB_DEVICE_WITH_PARAMS(solver,
|
||||
typedef netlist_list_t<netlist_terminal_t *> terminal_list_t;
|
||||
typedef netlist_list_t<netlist_net_t *> net_list_t;
|
||||
|
||||
netlist_ttl_input_t m_feedback;
|
||||
netlist_ttl_output_t m_Q;
|
||||
|
||||
@ -104,11 +107,14 @@ NETLIB_DEVICE_WITH_PARAMS(solver,
|
||||
netlist_time m_inc;
|
||||
netlist_time m_last_step;
|
||||
|
||||
netlist_list_t<netlist_terminal_t *> m_terms;
|
||||
netlist_list_t<netlist_terminal_t *> m_inps;
|
||||
terminal_list_t m_terms;
|
||||
terminal_list_t m_inps;
|
||||
|
||||
public:
|
||||
netlist_list_t<netlist_net_t *> m_nets;
|
||||
|
||||
~NETLIB_NAME(solver)();
|
||||
|
||||
net_list_t m_nets;
|
||||
|
||||
ATTR_HOT inline void schedule();
|
||||
|
||||
|
@ -18,8 +18,9 @@ NETLISTOBJ = $(EMUOBJ)/netlist
|
||||
#-------------------------------------------------
|
||||
|
||||
NETLISTOBJS+= \
|
||||
$(NETLISTOBJ)/nl_setup.o \
|
||||
$(NETLISTOBJ)/nl_base.o \
|
||||
$(NETLISTOBJ)/pstring.o \
|
||||
$(NETLISTOBJ)/nl_setup.o \
|
||||
$(NETLISTOBJ)/nl_parser.o \
|
||||
$(NETLISTOBJ)/devices/nld_system.o \
|
||||
$(NETLISTOBJ)/devices/net_lib.o \
|
||||
|
@ -5,6 +5,9 @@
|
||||
|
||||
#include "nl_base.h"
|
||||
#include "devices/nld_system.h"
|
||||
#include "pstring.h"
|
||||
|
||||
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_object_t
|
||||
@ -14,25 +17,24 @@ ATTR_COLD netlist_object_t::netlist_object_t(const type_t atype, const family_t
|
||||
: m_objtype(atype)
|
||||
, m_family(afamily)
|
||||
, m_netlist(NULL)
|
||||
, m_name(NULL)
|
||||
{}
|
||||
|
||||
ATTR_COLD netlist_object_t::~netlist_object_t()
|
||||
{
|
||||
delete m_name;
|
||||
//delete m_name;
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_object_t::init_object(netlist_base_t &nl, const astring &aname)
|
||||
ATTR_COLD void netlist_object_t::init_object(netlist_base_t &nl, const pstring &aname)
|
||||
{
|
||||
m_netlist = &nl;
|
||||
m_name = new astring(aname);
|
||||
m_name = aname;
|
||||
}
|
||||
|
||||
ATTR_COLD const astring &netlist_object_t::name() const
|
||||
ATTR_COLD const pstring &netlist_object_t::name() const
|
||||
{
|
||||
if (m_name == NULL)
|
||||
if (m_name == "")
|
||||
fatalerror("object not initialized");
|
||||
return *m_name;
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -47,7 +49,7 @@ ATTR_COLD netlist_owned_object_t::netlist_owned_object_t(const type_t atype,
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_owned_object_t::init_object(netlist_core_device_t &dev,
|
||||
const astring &aname)
|
||||
const pstring &aname)
|
||||
{
|
||||
netlist_object_t::init_object(dev.netlist(), aname);
|
||||
m_netdev = &dev;
|
||||
@ -58,15 +60,17 @@ ATTR_COLD void netlist_owned_object_t::init_object(netlist_core_device_t &dev,
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_base_t::netlist_base_t()
|
||||
: m_mainclock(NULL),
|
||||
m_time_ps(netlist_time::zero),
|
||||
: m_time_ps(netlist_time::zero),
|
||||
m_rem(0),
|
||||
m_div(NETLIST_DIV)
|
||||
m_div(NETLIST_DIV),
|
||||
m_mainclock(NULL),
|
||||
m_solver(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
netlist_base_t::~netlist_base_t()
|
||||
{
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_base_t::set_mainclock_dev(NETLIB_NAME(mainclock) *dev)
|
||||
@ -81,11 +85,12 @@ ATTR_COLD void netlist_base_t::set_solver_dev(NETLIB_NAME(solver) *dev)
|
||||
|
||||
ATTR_COLD void netlist_base_t::reset()
|
||||
{
|
||||
m_time_ps = netlist_time::zero;
|
||||
m_rem = 0;
|
||||
m_queue.clear();
|
||||
if (m_mainclock != NULL)
|
||||
m_mainclock->m_Q.net().set_time(netlist_time::zero);
|
||||
m_time_ps = netlist_time::zero;
|
||||
m_rem = 0;
|
||||
m_queue.clear();
|
||||
if (m_mainclock != NULL)
|
||||
m_mainclock->m_Q.net().set_time(netlist_time::zero);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -121,7 +126,7 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime)
|
||||
{
|
||||
while ( (atime > 0) && (m_queue.is_not_empty()))
|
||||
{
|
||||
const queue_t::entry_t e = m_queue.pop();
|
||||
const queue_t::entry_t &e = m_queue.pop();
|
||||
update_time(e.time(), atime);
|
||||
|
||||
//if (FATAL_ERROR_AFTER_NS)
|
||||
@ -156,7 +161,7 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(INT32 &atime)
|
||||
NETLIB_NAME(mainclock)::mc_update(mcQ, time() + inc);
|
||||
|
||||
}
|
||||
const queue_t::entry_t e = m_queue.pop();
|
||||
const queue_t::entry_t &e = m_queue.pop();
|
||||
|
||||
update_time(e.time(), atime);
|
||||
|
||||
@ -197,7 +202,7 @@ netlist_core_device_t::netlist_core_device_t()
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const astring &name)
|
||||
ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const pstring &name)
|
||||
{
|
||||
init_object(setup.netlist(), name);
|
||||
|
||||
@ -248,7 +253,7 @@ netlist_device_t::~netlist_device_t()
|
||||
//NL_VERBOSE_OUT(("~net_device_t\n");
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::init(netlist_setup_t &setup, const astring &name)
|
||||
ATTR_COLD void netlist_device_t::init(netlist_setup_t &setup, const pstring &name)
|
||||
{
|
||||
netlist_core_device_t::init(setup, name);
|
||||
m_setup = &setup;
|
||||
@ -256,33 +261,33 @@ ATTR_COLD void netlist_device_t::init(netlist_setup_t &setup, const astring &nam
|
||||
}
|
||||
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_sub(netlist_core_device_t &dev, const astring &name)
|
||||
ATTR_COLD void netlist_device_t::register_sub(netlist_core_device_t &dev, const pstring &name)
|
||||
{
|
||||
dev.init(*m_setup, this->name() + "." + name);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_output(netlist_core_device_t &dev, const astring &name, netlist_output_t &port)
|
||||
ATTR_COLD void netlist_device_t::register_output(netlist_core_device_t &dev, const pstring &name, netlist_output_t &port)
|
||||
{
|
||||
m_setup->register_object(*this, dev, name, port, netlist_terminal_t::STATE_OUT);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_terminal(const astring &name, netlist_terminal_t &port)
|
||||
ATTR_COLD void netlist_device_t::register_terminal(const pstring &name, netlist_terminal_t &port)
|
||||
{
|
||||
m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_INP_ACTIVE);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_output(const astring &name, netlist_output_t &port)
|
||||
ATTR_COLD void netlist_device_t::register_output(const pstring &name, netlist_output_t &port)
|
||||
{
|
||||
m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_OUT);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_input(netlist_core_device_t &dev, const astring &name, netlist_input_t &inp, netlist_input_t::state_e type)
|
||||
ATTR_COLD void netlist_device_t::register_input(netlist_core_device_t &dev, const pstring &name, netlist_input_t &inp, netlist_input_t::state_e type)
|
||||
{
|
||||
m_terminals.add(name);
|
||||
m_setup->register_object(*this, dev, name, inp, type);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_input(const astring &name, netlist_input_t &inp, netlist_input_t::state_e type)
|
||||
ATTR_COLD void netlist_device_t::register_input(const pstring &name, netlist_input_t &inp, netlist_input_t::state_e type)
|
||||
{
|
||||
register_input(*this, name, inp, type);
|
||||
}
|
||||
@ -303,14 +308,14 @@ ATTR_COLD void netlist_device_t::register_link_internal(netlist_input_t &in, net
|
||||
register_link_internal(*this, in, out, aState);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const astring &name, netlist_param_t ¶m, double initialVal)
|
||||
ATTR_COLD void netlist_device_t::register_param(netlist_core_device_t &dev, const pstring &name, netlist_param_t ¶m, double initialVal)
|
||||
{
|
||||
param.set_netdev(dev);
|
||||
param.initial(initialVal);
|
||||
m_setup->register_object(*this, *this, name, param, netlist_terminal_t::STATE_NONEX);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_device_t::register_param(const astring &name, netlist_param_t ¶m, double initialVal)
|
||||
ATTR_COLD void netlist_device_t::register_param(const pstring &name, netlist_param_t ¶m, double initialVal)
|
||||
{
|
||||
register_param(*this,name, param, initialVal);
|
||||
}
|
||||
@ -451,7 +456,7 @@ ATTR_COLD netlist_terminal_t::netlist_terminal_t()
|
||||
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_terminal_t::init_object(netlist_core_device_t &dev, const astring &aname, const state_e astate)
|
||||
ATTR_COLD void netlist_terminal_t::init_object(netlist_core_device_t &dev, const pstring &aname, const state_e astate)
|
||||
{
|
||||
set_state(astate);
|
||||
netlist_owned_object_t::init_object(dev, aname);
|
||||
@ -480,7 +485,7 @@ netlist_output_t::netlist_output_t(const type_t atype, const family_t afamily)
|
||||
this->set_net(m_my_net);
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_output_t::init_object(netlist_core_device_t &dev, const astring &aname)
|
||||
ATTR_COLD void netlist_output_t::init_object(netlist_core_device_t &dev, const pstring &aname)
|
||||
{
|
||||
netlist_terminal_t::init_object(dev, aname, STATE_OUT);
|
||||
net().init_object(dev.netlist(), aname);
|
||||
|
@ -138,6 +138,7 @@
|
||||
#include "nl_config.h"
|
||||
#include "nl_lists.h"
|
||||
#include "nl_time.h"
|
||||
#include "pstring.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
@ -248,9 +249,9 @@ public:
|
||||
|
||||
virtual ~netlist_object_t();
|
||||
|
||||
ATTR_COLD void init_object(netlist_base_t &nl, const astring &aname);
|
||||
ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname);
|
||||
|
||||
ATTR_COLD const astring &name() const;
|
||||
ATTR_COLD const pstring &name() const;
|
||||
|
||||
ATTR_HOT inline const type_t type() const { return m_objtype; }
|
||||
ATTR_HOT inline const family_t family() const { return m_family; }
|
||||
@ -262,10 +263,10 @@ public:
|
||||
ATTR_HOT inline const netlist_base_t & RESTRICT netlist() const { return *m_netlist; }
|
||||
|
||||
private:
|
||||
pstring m_name;
|
||||
const type_t m_objtype;
|
||||
const family_t m_family;
|
||||
netlist_base_t * RESTRICT m_netlist;
|
||||
astring *m_name;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -277,7 +278,7 @@ class netlist_owned_object_t : public netlist_object_t
|
||||
public:
|
||||
ATTR_COLD netlist_owned_object_t(const type_t atype, const family_t afamily);
|
||||
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const astring &aname);
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname);
|
||||
|
||||
ATTR_HOT inline netlist_core_device_t & RESTRICT netdev() const { return *m_netdev; }
|
||||
private:
|
||||
@ -306,7 +307,7 @@ public:
|
||||
ATTR_COLD netlist_terminal_t(const type_t atype, const family_t afamily);
|
||||
ATTR_COLD netlist_terminal_t();
|
||||
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const astring &aname, const state_e astate);
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname, const state_e astate);
|
||||
|
||||
ATTR_COLD void set_net(netlist_net_t &anet);
|
||||
ATTR_COLD inline bool has_net() { return (m_net != NULL); }
|
||||
@ -515,7 +516,7 @@ public:
|
||||
|
||||
ATTR_COLD netlist_output_t(const type_t atype, const family_t afamily);
|
||||
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const astring &aname);
|
||||
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname);
|
||||
|
||||
double m_low_V;
|
||||
double m_high_V;
|
||||
@ -601,7 +602,7 @@ public:
|
||||
|
||||
ATTR_COLD virtual ~netlist_core_device_t();
|
||||
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const pstring &name);
|
||||
|
||||
|
||||
ATTR_HOT virtual void update_param() {}
|
||||
@ -656,9 +657,11 @@ public:
|
||||
ATTR_HOT virtual void step_time(const double st) { }
|
||||
ATTR_HOT virtual void update_terminals() { }
|
||||
|
||||
/* stats */
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
/* stats */
|
||||
osd_ticks_t total_time;
|
||||
INT32 stat_count;
|
||||
#endif
|
||||
|
||||
#if USE_DELEGATES
|
||||
net_update_delegate static_update;
|
||||
@ -681,21 +684,21 @@ public:
|
||||
|
||||
ATTR_COLD virtual ~netlist_device_t();
|
||||
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const astring &name);
|
||||
ATTR_COLD virtual void init(netlist_setup_t &setup, const pstring &name);
|
||||
|
||||
ATTR_COLD const netlist_setup_t *setup() const { return m_setup; }
|
||||
|
||||
ATTR_COLD bool variable_input_count() { return m_variable_input_count; }
|
||||
|
||||
ATTR_COLD void register_sub(netlist_core_device_t &dev, const astring &name);
|
||||
ATTR_COLD void register_sub(netlist_core_device_t &dev, const pstring &name);
|
||||
|
||||
ATTR_COLD void register_terminal(const astring &name, netlist_terminal_t &port);
|
||||
ATTR_COLD void register_terminal(const pstring &name, netlist_terminal_t &port);
|
||||
|
||||
ATTR_COLD void register_output(const astring &name, netlist_output_t &out);
|
||||
ATTR_COLD void register_output(netlist_core_device_t &dev, const astring &name, netlist_output_t &out);
|
||||
ATTR_COLD void register_output(const pstring &name, netlist_output_t &out);
|
||||
ATTR_COLD void register_output(netlist_core_device_t &dev, const pstring &name, netlist_output_t &out);
|
||||
|
||||
ATTR_COLD void register_input(const astring &name, netlist_input_t &in, netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
|
||||
ATTR_COLD void register_input(netlist_core_device_t &dev, const astring &name, netlist_input_t &in, netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
|
||||
ATTR_COLD void register_input(const pstring &name, netlist_input_t &in, netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
|
||||
ATTR_COLD void register_input(netlist_core_device_t &dev, const pstring &name, netlist_input_t &in, netlist_input_t::state_e state = netlist_input_t::STATE_INP_ACTIVE);
|
||||
|
||||
ATTR_COLD void register_link_internal(netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState);
|
||||
ATTR_COLD void register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState);
|
||||
@ -703,15 +706,15 @@ public:
|
||||
ATTR_HOT virtual void update_terminals() { }
|
||||
|
||||
/* driving logic outputs don't count in here */
|
||||
netlist_list_t<astring> m_terminals;
|
||||
netlist_list_t<pstring, 20> m_terminals;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void update() { }
|
||||
virtual void start() { }
|
||||
|
||||
ATTR_COLD void register_param(const astring &sname, netlist_param_t ¶m, const double initialVal = 0.0);
|
||||
ATTR_COLD void register_param(netlist_core_device_t &dev, const astring &sname, netlist_param_t ¶m, const double initialVal = 0.0);
|
||||
ATTR_COLD void register_param(const pstring &sname, netlist_param_t ¶m, const double initialVal = 0.0);
|
||||
ATTR_COLD void register_param(netlist_core_device_t &dev, const pstring &sname, netlist_param_t ¶m, const double initialVal = 0.0);
|
||||
|
||||
netlist_setup_t *m_setup;
|
||||
bool m_variable_input_count;
|
||||
@ -780,19 +783,22 @@ public:
|
||||
ATTR_COLD void reset();
|
||||
|
||||
protected:
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
// performance
|
||||
int m_perf_out_processed;
|
||||
int m_perf_inp_processed;
|
||||
int m_perf_inp_active;
|
||||
#endif
|
||||
|
||||
private:
|
||||
netlist_time m_time_ps;
|
||||
queue_t m_queue;
|
||||
NETLIB_NAME(mainclock) * m_mainclock;
|
||||
NETLIB_NAME(solver) * m_solver;
|
||||
netlist_time m_time_ps;
|
||||
UINT32 m_rem;
|
||||
UINT32 m_div;
|
||||
|
||||
NETLIB_NAME(mainclock) * m_mainclock;
|
||||
NETLIB_NAME(solver) * m_solver;
|
||||
|
||||
ATTR_HOT void update_time(const netlist_time t, INT32 &atime);
|
||||
|
||||
};
|
||||
@ -994,7 +1000,7 @@ ATTR_HOT inline const bool netlist_analog_input_t::is_highz() const
|
||||
class net_device_t_base_factory
|
||||
{
|
||||
public:
|
||||
net_device_t_base_factory(const astring &name, const astring &classname)
|
||||
net_device_t_base_factory(const pstring &name, const pstring &classname)
|
||||
: m_name(name), m_classname(classname)
|
||||
{}
|
||||
|
||||
@ -1002,18 +1008,18 @@ public:
|
||||
|
||||
virtual netlist_device_t *Create() const = 0;
|
||||
|
||||
const astring &name() const { return m_name; }
|
||||
const astring &classname() const { return m_classname; }
|
||||
const pstring &name() const { return m_name; }
|
||||
const pstring &classname() const { return m_classname; }
|
||||
protected:
|
||||
astring m_name; /* device name */
|
||||
astring m_classname; /* device class name */
|
||||
pstring m_name; /* device name */
|
||||
pstring m_classname; /* device class name */
|
||||
};
|
||||
|
||||
template <class C>
|
||||
class net_device_t_factory : public net_device_t_base_factory
|
||||
{
|
||||
public:
|
||||
net_device_t_factory(const astring &name, const astring &classname)
|
||||
net_device_t_factory(const pstring &name, const pstring &classname)
|
||||
: net_device_t_base_factory(name, classname) { }
|
||||
|
||||
netlist_device_t *Create() const
|
||||
@ -1024,8 +1030,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
netlist_device_t *net_create_device_by_classname(const astring &classname, netlist_setup_t &setup);
|
||||
netlist_device_t *net_create_device_by_name(const astring &name, netlist_setup_t &setup);
|
||||
netlist_device_t *net_create_device_by_classname(const pstring &classname, netlist_setup_t &setup);
|
||||
netlist_device_t *net_create_device_by_name(const pstring &name, netlist_setup_t &setup);
|
||||
|
||||
|
||||
#endif /* NLBASE_H_ */
|
||||
|
@ -16,6 +16,8 @@
|
||||
// SETUP
|
||||
//============================================================
|
||||
|
||||
//#define astring breakme()
|
||||
|
||||
#define USE_DELEGATES (0)
|
||||
/*
|
||||
* The next options needs -Wno-pmf-conversions to compile and gcc
|
||||
|
@ -15,14 +15,23 @@
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class _ListClass>
|
||||
template <class _ListClass, int _NumElem = 128>
|
||||
struct netlist_list_t
|
||||
{
|
||||
public:
|
||||
ATTR_COLD netlist_list_t(int numElements = 100)
|
||||
|
||||
struct entry_t {
|
||||
|
||||
// keep compatibility with tagmap
|
||||
_ListClass object() { return m_obj; }
|
||||
|
||||
_ListClass m_obj;
|
||||
};
|
||||
|
||||
ATTR_COLD netlist_list_t(int numElements = _NumElem)
|
||||
{
|
||||
m_num_elements = numElements;
|
||||
m_list = new _ListClass[m_num_elements];
|
||||
m_list = new entry_t[m_num_elements];
|
||||
m_ptr = m_list;
|
||||
m_ptr--;
|
||||
}
|
||||
@ -32,24 +41,29 @@ public:
|
||||
}
|
||||
ATTR_HOT inline void add(const _ListClass elem)
|
||||
{
|
||||
assert(m_ptr-m_list <= m_num_elements - 1);
|
||||
if (m_ptr-m_list >= m_num_elements - 1)
|
||||
resize(m_num_elements * 2);
|
||||
|
||||
*(++m_ptr) = elem;
|
||||
(++m_ptr)->m_obj = elem;
|
||||
}
|
||||
ATTR_HOT inline void resize(const int new_size)
|
||||
{
|
||||
int cnt = count();
|
||||
_ListClass *m_new = new _ListClass[new_size];
|
||||
memcpy(m_new, m_list, new_size * sizeof(_ListClass));
|
||||
entry_t *m_new = new entry_t[new_size];
|
||||
entry_t *pd = m_new;
|
||||
|
||||
for (entry_t *ps = m_list; ps <= m_ptr; ps++, pd++)
|
||||
*pd = *ps;
|
||||
delete[] m_list;
|
||||
m_list = m_new;
|
||||
m_ptr = m_list + cnt - 1;
|
||||
m_num_elements = new_size;
|
||||
}
|
||||
ATTR_HOT inline void del(const _ListClass elem)
|
||||
ATTR_HOT inline void remove(const _ListClass elem)
|
||||
{
|
||||
for (_ListClass * i=m_list; i<=m_ptr; i++)
|
||||
for (entry_t *i = m_list; i <= m_ptr; i++)
|
||||
{
|
||||
if (*i == elem)
|
||||
if (i->object() == elem)
|
||||
{
|
||||
while (i <= m_ptr)
|
||||
{
|
||||
@ -61,16 +75,16 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
ATTR_HOT inline _ListClass *first() { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
|
||||
ATTR_HOT inline _ListClass *next(_ListClass *lc) { return (lc < last() ? lc + 1 : NULL ); }
|
||||
ATTR_HOT inline _ListClass *last() { return m_ptr; }
|
||||
ATTR_HOT inline _ListClass *item(int i) { return &m_list[i]; }
|
||||
ATTR_HOT inline entry_t *first() { return (m_ptr >= m_list ? &m_list[0] : NULL ); }
|
||||
ATTR_HOT inline entry_t *next(entry_t *lc) { return (lc < last() ? lc + 1 : NULL ); }
|
||||
ATTR_HOT inline entry_t *last() { return m_ptr; }
|
||||
ATTR_HOT inline entry_t *item(int i) { return &m_list[i]; }
|
||||
ATTR_HOT inline int count() const { return m_ptr - m_list + 1; }
|
||||
ATTR_HOT inline bool empty() { return (m_ptr < m_list); }
|
||||
ATTR_HOT inline void clear() { m_ptr = m_list - 1; }
|
||||
ATTR_HOT inline void reset() { m_ptr = m_list - 1; }
|
||||
private:
|
||||
_ListClass * m_ptr;
|
||||
_ListClass * m_list;
|
||||
entry_t * m_ptr;
|
||||
entry_t * m_list;
|
||||
int m_num_elements;
|
||||
//_ListClass m_list[_NumElements];
|
||||
};
|
||||
@ -111,7 +125,7 @@ public:
|
||||
if (is_empty() || (e.time() <= (m_end - 1)->time()))
|
||||
{
|
||||
*m_end++ = e;
|
||||
//inc_stat(m_prof_end);
|
||||
inc_stat(m_prof_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -120,20 +134,20 @@ public:
|
||||
{
|
||||
i--;
|
||||
*(i+1) = *i;
|
||||
//inc_stat(m_prof_sortmove);
|
||||
inc_stat(m_prof_sortmove);
|
||||
}
|
||||
*i = e;
|
||||
//inc_stat(m_prof_sort);
|
||||
inc_stat(m_prof_sort);
|
||||
}
|
||||
assert(m_end - m_list < _Size);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const entry_t pop()
|
||||
ATTR_HOT inline const entry_t &pop()
|
||||
{
|
||||
return *--m_end;
|
||||
}
|
||||
|
||||
ATTR_HOT inline const entry_t peek() const
|
||||
ATTR_HOT inline const entry_t &peek() const
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
@ -142,12 +156,15 @@ public:
|
||||
{
|
||||
m_end = &m_list[0];
|
||||
}
|
||||
// profiling
|
||||
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
// profiling
|
||||
INT32 m_prof_start;
|
||||
INT32 m_prof_end;
|
||||
INT32 m_prof_sortmove;
|
||||
INT32 m_prof_sort;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
entry_t * RESTRICT m_end;
|
||||
|
@ -16,7 +16,7 @@ void netlist_parser::parse(char *buf)
|
||||
m_p = buf;
|
||||
while (*m_p)
|
||||
{
|
||||
astring n;
|
||||
pstring n;
|
||||
skipws();
|
||||
if (!*m_p) break;
|
||||
n = getname('(');
|
||||
@ -34,8 +34,8 @@ void netlist_parser::parse(char *buf)
|
||||
|
||||
void netlist_parser::net_alias()
|
||||
{
|
||||
astring alias;
|
||||
astring out;
|
||||
pstring alias;
|
||||
pstring out;
|
||||
skipws();
|
||||
alias = getname(',');
|
||||
skipws();
|
||||
@ -46,7 +46,7 @@ void netlist_parser::net_alias()
|
||||
|
||||
void netlist_parser::netdev_param()
|
||||
{
|
||||
astring param;
|
||||
pstring param;
|
||||
double val;
|
||||
skipws();
|
||||
param = getname(',');
|
||||
@ -58,11 +58,11 @@ void netlist_parser::netdev_param()
|
||||
check_char(')');
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_const(const astring &dev_name)
|
||||
void netlist_parser::netdev_const(const pstring &dev_name)
|
||||
{
|
||||
astring name;
|
||||
pstring name;
|
||||
netlist_device_t *dev;
|
||||
astring paramfq;
|
||||
pstring paramfq;
|
||||
double val;
|
||||
|
||||
skipws();
|
||||
@ -72,16 +72,15 @@ void netlist_parser::netdev_const(const astring &dev_name)
|
||||
skipws();
|
||||
val = eval_param();
|
||||
check_char(')');
|
||||
paramfq = name;
|
||||
paramfq.cat(".CONST");
|
||||
paramfq = name + ".CONST";
|
||||
NL_VERBOSE_OUT(("Parser: Const: %s %f\n", name.cstr(), val));
|
||||
//m_setup.find_param(paramfq).initial(val);
|
||||
m_setup.register_param(paramfq, val);
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_device(const astring &dev_type)
|
||||
void netlist_parser::netdev_device(const pstring &dev_type)
|
||||
{
|
||||
astring devname;
|
||||
pstring devname;
|
||||
netlist_device_t *dev;
|
||||
int cnt;
|
||||
|
||||
@ -96,11 +95,9 @@ void netlist_parser::netdev_device(const astring &dev_type)
|
||||
{
|
||||
m_p++;
|
||||
skipws();
|
||||
astring output_name = getname2(',', ')');
|
||||
pstring output_name = getname2(',', ')');
|
||||
NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), dev->m_terminals.item(cnt)->cstr()));
|
||||
astring temp;
|
||||
temp.printf("%s.[%d]", devname.cstr(), cnt);
|
||||
m_setup.register_link(temp, output_name);
|
||||
m_setup.register_link(pstring::sprintf("%s.[%d]", devname.cstr(), cnt), output_name);
|
||||
skipws();
|
||||
cnt++;
|
||||
}
|
||||
@ -156,7 +153,7 @@ void netlist_parser::skipws()
|
||||
}
|
||||
}
|
||||
|
||||
astring netlist_parser::getname(char sep)
|
||||
pstring netlist_parser::getname(char sep)
|
||||
{
|
||||
char buf[300];
|
||||
char *p1 = buf;
|
||||
@ -165,10 +162,10 @@ astring netlist_parser::getname(char sep)
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
m_p++;
|
||||
return astring(buf);
|
||||
return pstring(buf);
|
||||
}
|
||||
|
||||
astring netlist_parser::getname2(char sep1, char sep2)
|
||||
pstring netlist_parser::getname2(char sep1, char sep2)
|
||||
{
|
||||
char buf[300];
|
||||
char *p1 = buf;
|
||||
@ -176,7 +173,7 @@ astring netlist_parser::getname2(char sep1, char sep2)
|
||||
while ((*m_p != sep1) && (*m_p != sep2))
|
||||
*p1++ = *m_p++;
|
||||
*p1 = 0;
|
||||
return astring(buf);
|
||||
return pstring(buf);
|
||||
}
|
||||
|
||||
void netlist_parser::check_char(char ctocheck)
|
||||
|
@ -19,15 +19,15 @@ public:
|
||||
void parse(char *buf);
|
||||
void net_alias();
|
||||
void netdev_param();
|
||||
void netdev_const(const astring &dev_name);
|
||||
void netdev_device(const astring &dev_type);
|
||||
void netdev_const(const pstring &dev_name);
|
||||
void netdev_device(const pstring &dev_type);
|
||||
|
||||
private:
|
||||
|
||||
void skipeol();
|
||||
void skipws();
|
||||
astring getname(char sep);
|
||||
astring getname2(char sep1, char sep2);
|
||||
pstring getname(char sep);
|
||||
pstring getname2(char sep1, char sep2);
|
||||
void check_char(char ctocheck);
|
||||
double eval_param();
|
||||
|
||||
|
@ -41,13 +41,17 @@ static void tagmap_free_entries(T &tm)
|
||||
netlist_setup_t::~netlist_setup_t()
|
||||
{
|
||||
tagmap_free_entries<tagmap_devices_t>(m_devices);
|
||||
tagmap_free_entries<tagmap_link_t>(m_links);
|
||||
tagmap_free_entries<tagmap_astring_t>(m_alias);
|
||||
//tagmap_free_entries<tagmap_link_t>(m_links);
|
||||
//tagmap_free_entries<tagmap_nstring_t>(m_alias);
|
||||
m_links.reset();
|
||||
m_alias.reset();
|
||||
m_params.reset();
|
||||
m_terminals.reset();
|
||||
m_params_temp.reset();
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
netlist_device_t *netlist_setup_t::register_dev(netlist_device_t *dev, const astring &name)
|
||||
netlist_device_t *netlist_setup_t::register_dev(netlist_device_t *dev, const pstring &name)
|
||||
{
|
||||
if (!(m_devices.add(name, dev, false)==TMERR_NONE))
|
||||
fatalerror("Error adding %s to device list\n", name.cstr());
|
||||
@ -55,13 +59,14 @@ netlist_device_t *netlist_setup_t::register_dev(netlist_device_t *dev, const ast
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void remove_start_with(T &hm, astring &sw)
|
||||
static void remove_start_with(T &hm, pstring &sw)
|
||||
{
|
||||
typename T::entry_t *entry = hm.first();
|
||||
while (entry != NULL)
|
||||
{
|
||||
typename T::entry_t *next = hm.next(entry);
|
||||
if (sw.cmpsubstr(entry->tag(), 0, sw.len()) == 0)
|
||||
pstring x = entry->tag().cstr();
|
||||
if (sw.equals(x.substr(0, sw.len())))
|
||||
{
|
||||
NL_VERBOSE_OUT(("removing %s\n", entry->tag().cstr()));
|
||||
hm.remove(entry->object());
|
||||
@ -70,15 +75,13 @@ static void remove_start_with(T &hm, astring &sw)
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_setup_t::remove_dev(const astring &name)
|
||||
void netlist_setup_t::remove_dev(const pstring &name)
|
||||
{
|
||||
netlist_device_t *dev = m_devices.find(name);
|
||||
astring temp = name;
|
||||
pstring temp = name + ".";
|
||||
if (dev == NULL)
|
||||
fatalerror("Device %s does not exist\n", name.cstr());
|
||||
|
||||
temp.cat(".");
|
||||
|
||||
//remove_start_with<tagmap_input_t>(m_inputs, temp);
|
||||
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
|
||||
remove_start_with<tagmap_param_t>(m_params, temp);
|
||||
@ -87,14 +90,14 @@ void netlist_setup_t::remove_dev(const astring &name)
|
||||
while (p != NULL)
|
||||
{
|
||||
tagmap_link_t::entry_t *n = m_links.next(p);
|
||||
if (temp.cmpsubstr(p->object()->e1,0,temp.len()) == 0 || temp.cmpsubstr(p->object()->e2,0,temp.len()) == 0)
|
||||
if (temp.equals(p->object().e1.substr(0,temp.len())) || temp.equals(p->object().e2.substr(0,temp.len())))
|
||||
m_links.remove(p->object());
|
||||
p = n;
|
||||
}
|
||||
m_devices.remove(name);
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_callback(const astring &devname, netlist_output_delegate delegate)
|
||||
void netlist_setup_t::register_callback(const pstring &devname, netlist_output_delegate delegate)
|
||||
{
|
||||
NETLIB_NAME(analog_callback) *dev = (NETLIB_NAME(analog_callback) *) m_devices.find(devname);
|
||||
if (dev == NULL)
|
||||
@ -102,13 +105,14 @@ void netlist_setup_t::register_callback(const astring &devname, netlist_output_d
|
||||
dev->register_callback(delegate);
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_alias(const astring &alias, const astring &out)
|
||||
void netlist_setup_t::register_alias(const pstring &alias, const pstring &out)
|
||||
{
|
||||
if (!(m_alias.add(alias, new astring(out), false)==TMERR_NONE))
|
||||
//if (!(m_alias.add(alias, new nstring(out), false)==TMERR_NONE))
|
||||
if (!(m_alias.add(alias, out, false)==TMERR_NONE))
|
||||
fatalerror("Error adding alias %s to alias list\n", alias.cstr());
|
||||
}
|
||||
|
||||
astring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
|
||||
pstring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
|
||||
{
|
||||
switch (in.type())
|
||||
{
|
||||
@ -134,7 +138,7 @@ astring netlist_setup_t::objtype_as_astr(netlist_object_t &in)
|
||||
fatalerror("Unknown object type %d\n", in.type());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_object_t &obj, netlist_input_t::state_e state)
|
||||
void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const pstring &name, netlist_object_t &obj, netlist_input_t::state_e state)
|
||||
{
|
||||
switch (obj.type())
|
||||
{
|
||||
@ -157,17 +161,16 @@ 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);
|
||||
astring temp = param.netdev().name();
|
||||
temp.cat(".");
|
||||
temp.cat(name);
|
||||
const astring *val = m_params_temp.find(temp);
|
||||
if (val != NULL)
|
||||
pstring temp = param.netdev().name() + "." + name;
|
||||
const pstring val = m_params_temp.find(temp);
|
||||
if (val != "")
|
||||
{
|
||||
//printf("Found parameter ... %s : %s\n", temp.cstr(), val->cstr());
|
||||
double vald = 0;
|
||||
if (sscanf(val->cstr(), "%lf", &vald) != 1)
|
||||
fatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val->cstr());
|
||||
if (sscanf(val.cstr(), "%lf", &vald) != 1)
|
||||
fatalerror("Invalid number conversion %s : %s\n", temp.cstr(), val.cstr());
|
||||
param.initial(vald);
|
||||
}
|
||||
if (!(m_params.add(temp, ¶m, false)==TMERR_NONE))
|
||||
@ -179,52 +182,52 @@ void netlist_setup_t::register_object(netlist_device_t &dev, netlist_core_device
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_link(const astring &sin, const astring &sout)
|
||||
void netlist_setup_t::register_link(const pstring &sin, const pstring &sout)
|
||||
{
|
||||
link_t *temp = new link_t(sin, sout);
|
||||
link_t temp = link_t(sin, sout);
|
||||
NL_VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr()));
|
||||
if (!(m_links.add(sin + "." + sout, temp, false)==TMERR_NONE))
|
||||
fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
|
||||
m_links.add(temp);
|
||||
//if (!(m_links.add(sin + "." + sout, temp, false)==TMERR_NONE))
|
||||
// fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_param(const astring ¶m, const double value)
|
||||
void netlist_setup_t::register_param(const pstring ¶m, const double value)
|
||||
{
|
||||
// FIXME: there should be a better way
|
||||
astring temp;
|
||||
temp.printf("%.9e", value);
|
||||
register_param(param, temp);
|
||||
register_param(param, pstring::sprintf("%.9e", value));
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_param(const astring ¶m, const astring &value)
|
||||
void netlist_setup_t::register_param(const pstring ¶m, const pstring &value)
|
||||
{
|
||||
if (!(m_params_temp.add(param, new astring(value), false)==TMERR_NONE))
|
||||
//if (!(m_params_temp.add(param, new nstring(value), false)==TMERR_NONE))
|
||||
if (!(m_params_temp.add(param, value, false)==TMERR_NONE))
|
||||
fatalerror("Error adding parameter %s to parameter list\n", param.cstr());
|
||||
}
|
||||
|
||||
const astring netlist_setup_t::resolve_alias(const astring &name) const
|
||||
const pstring netlist_setup_t::resolve_alias(const pstring &name) const
|
||||
{
|
||||
const astring *temp = m_alias.find(name);
|
||||
astring ret = name;
|
||||
if (temp != NULL)
|
||||
ret = *temp;
|
||||
const pstring temp = m_alias.find(name);
|
||||
pstring ret = name;
|
||||
if (temp != "")
|
||||
ret = temp;
|
||||
int p = ret.find(".[");
|
||||
if (p > 0)
|
||||
{
|
||||
astring dname = ret;
|
||||
pstring dname = ret;
|
||||
netlist_device_t *dev = m_devices.find(dname.substr(0,p));
|
||||
if (dev == NULL)
|
||||
fatalerror("Device for %s not found\n", name.cstr());
|
||||
ret.substr(p+2,ret.len()-p-3);
|
||||
int c = atoi(ret);
|
||||
ret = dev->name() + "." + *(dev->m_terminals.item(c));
|
||||
int c = atoi(ret.substr(p+2,ret.len()-p-3));
|
||||
ret = dev->name() + "." + dev->m_terminals.item(c)->object();
|
||||
}
|
||||
|
||||
//printf("%s==>%s\n", name.cstr(), ret.cstr());
|
||||
return ret;
|
||||
}
|
||||
|
||||
netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in)
|
||||
netlist_terminal_t &netlist_setup_t::find_terminal(const pstring &terminal_in)
|
||||
{
|
||||
const astring &tname = resolve_alias(terminal_in);
|
||||
const pstring &tname = resolve_alias(terminal_in);
|
||||
netlist_terminal_t *ret;
|
||||
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(tname));
|
||||
@ -232,8 +235,7 @@ netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in)
|
||||
if (ret == NULL)
|
||||
{
|
||||
/* look for ".Q" std output */
|
||||
astring s = tname;
|
||||
s.cat(".Q");
|
||||
pstring s = tname + ".Q";
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(s));
|
||||
}
|
||||
if (ret == NULL)
|
||||
@ -242,9 +244,9 @@ netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in)
|
||||
return *ret;
|
||||
}
|
||||
|
||||
netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in, netlist_object_t::type_t atype)
|
||||
netlist_terminal_t &netlist_setup_t::find_terminal(const pstring &terminal_in, netlist_object_t::type_t atype)
|
||||
{
|
||||
const astring &tname = resolve_alias(terminal_in);
|
||||
const pstring &tname = resolve_alias(terminal_in);
|
||||
netlist_terminal_t *ret;
|
||||
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(tname));
|
||||
@ -252,8 +254,7 @@ netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in, n
|
||||
if (ret == NULL && atype == netlist_object_t::OUTPUT)
|
||||
{
|
||||
/* look for ".Q" std output */
|
||||
astring s = tname;
|
||||
s.cat(".Q");
|
||||
pstring s = tname + ".Q";
|
||||
ret = dynamic_cast<netlist_terminal_t *>(m_terminals.find(s));
|
||||
}
|
||||
if (ret == NULL)
|
||||
@ -264,9 +265,9 @@ netlist_terminal_t &netlist_setup_t::find_terminal(const astring &terminal_in, n
|
||||
return *ret;
|
||||
}
|
||||
|
||||
netlist_param_t &netlist_setup_t::find_param(const astring ¶m_in)
|
||||
netlist_param_t &netlist_setup_t::find_param(const pstring ¶m_in)
|
||||
{
|
||||
const astring &outname = resolve_alias(param_in);
|
||||
const pstring &outname = resolve_alias(param_in);
|
||||
netlist_param_t *ret;
|
||||
|
||||
ret = m_params.find(outname);
|
||||
@ -282,10 +283,10 @@ void netlist_setup_t::connect_input_output(netlist_input_t &in, netlist_output_t
|
||||
if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC))
|
||||
{
|
||||
nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(in);
|
||||
astring x = "";
|
||||
x.printf("proxy_ad_%d", m_proxy_cnt++);
|
||||
pstring x = pstring::sprintf("proxy_ad_%d", m_proxy_cnt);
|
||||
m_proxy_cnt++;
|
||||
|
||||
proxy->init(*this, x.cstr());
|
||||
proxy->init(*this, x);
|
||||
register_dev(proxy, x);
|
||||
|
||||
proxy->m_Q.net().register_con(in);
|
||||
@ -296,9 +297,10 @@ void netlist_setup_t::connect_input_output(netlist_input_t &in, netlist_output_t
|
||||
{
|
||||
//printf("here 1\n");
|
||||
nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", m_proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
pstring x = pstring::sprintf("proxy_da_%d", m_proxy_cnt);
|
||||
m_proxy_cnt++;
|
||||
|
||||
proxy->init(*this, x);
|
||||
register_dev(proxy, x);
|
||||
|
||||
proxy->m_Q.net().register_con(in);
|
||||
@ -320,9 +322,10 @@ void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_i
|
||||
{
|
||||
NL_VERBOSE_OUT(("connect_terminal_input: connecting proxy\n"));
|
||||
nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(inp);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", m_proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
pstring x = pstring::sprintf("proxy_da_%d", m_proxy_cnt);
|
||||
m_proxy_cnt++;
|
||||
|
||||
proxy->init(*this, x);
|
||||
register_dev(proxy, x);
|
||||
|
||||
connect_terminals(term, proxy->m_I);
|
||||
@ -355,9 +358,10 @@ void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_ou
|
||||
{
|
||||
NL_VERBOSE_OUT(("connect_terminal_output: connecting proxy\n"));
|
||||
nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out);
|
||||
astring x = "";
|
||||
x.printf("proxy_da_%d", m_proxy_cnt++);
|
||||
proxy->init(*this, x.cstr());
|
||||
pstring x = pstring::sprintf("proxy_da_%d", m_proxy_cnt);
|
||||
m_proxy_cnt++;
|
||||
|
||||
proxy->init(*this, x);
|
||||
register_dev(proxy, x);
|
||||
|
||||
out.net().register_con(proxy->m_I);
|
||||
@ -426,8 +430,8 @@ void netlist_setup_t::resolve_inputs(void)
|
||||
NL_VERBOSE_OUT(("Resolving ...\n"));
|
||||
for (tagmap_link_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry))
|
||||
{
|
||||
const astring t1s = entry->object()->e1;
|
||||
const astring t2s = entry->object()->e2;
|
||||
const pstring t1s = entry->object().e1;
|
||||
const pstring t2s = entry->object().e2;
|
||||
netlist_terminal_t &t1 = find_terminal(t1s);
|
||||
netlist_terminal_t &t2 = find_terminal(t2s);
|
||||
|
||||
@ -490,7 +494,7 @@ void netlist_setup_t::start_devices(void)
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
netlist_device_t *dev = entry->object();
|
||||
dev->init(*this, entry->tag());
|
||||
dev->init(*this, entry->tag().cstr());
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,7 +522,7 @@ void netlist_setup_t::parse(char *buf)
|
||||
|
||||
void netlist_setup_t::print_stats()
|
||||
{
|
||||
if (NL_KEEP_STATISTICS)
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
{
|
||||
for (netlist_setup_t::tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
@ -530,4 +534,5 @@ void netlist_setup_t::print_stats()
|
||||
printf("Queue Sort %15d\n", m_netlist.queue().m_prof_sort);
|
||||
printf("Queue Move %15d\n", m_netlist.queue().m_prof_sortmove);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -68,42 +68,53 @@ public:
|
||||
|
||||
struct link_t
|
||||
{
|
||||
link_t(const astring &ae1, const astring &ae2)
|
||||
link_t() { }
|
||||
// Copy constructor
|
||||
link_t(const link_t &from)
|
||||
{
|
||||
e1 = from.e1;
|
||||
e2 = from.e2;
|
||||
}
|
||||
|
||||
link_t(const pstring &ae1, const pstring &ae2)
|
||||
{
|
||||
e1 = ae1;
|
||||
e2 = ae2;
|
||||
}
|
||||
astring e1;
|
||||
astring e2;
|
||||
pstring e1;
|
||||
pstring e2;
|
||||
|
||||
bool operator==(const link_t &rhs) const { return (e1 == rhs.e1) && (e2 == rhs.e2); }
|
||||
link_t &operator=(const link_t &rhs) { e1 = rhs.e1; e2 = rhs.e2; return *this; }
|
||||
};
|
||||
|
||||
typedef tagmap_t<netlist_device_t *, 393> tagmap_devices_t;
|
||||
typedef tagmap_t<link_t *, 393> tagmap_link_t;
|
||||
typedef tagmap_t<const astring *, 393> tagmap_astring_t;
|
||||
typedef tagmap_t<pstring, 393> tagmap_nstring_t;
|
||||
typedef tagmap_t<netlist_param_t *, 393> tagmap_param_t;
|
||||
typedef tagmap_t<netlist_terminal_t *, 393> tagmap_terminal_t;
|
||||
typedef netlist_list_t<link_t> tagmap_link_t;
|
||||
|
||||
netlist_setup_t(netlist_base_t &netlist);
|
||||
~netlist_setup_t();
|
||||
|
||||
netlist_base_t &netlist() { return m_netlist; }
|
||||
|
||||
netlist_device_t *register_dev(netlist_device_t *dev, const astring &name);
|
||||
void remove_dev(const astring &name);
|
||||
netlist_device_t *register_dev(netlist_device_t *dev, const pstring &name);
|
||||
void remove_dev(const pstring &name);
|
||||
|
||||
void register_alias(const astring &alias, const astring &out);
|
||||
void register_link(const astring &sin, const astring &sout);
|
||||
void register_param(const astring ¶m, const astring &value);
|
||||
void register_param(const astring ¶m, const double value);
|
||||
void register_alias(const pstring &alias, const pstring &out);
|
||||
void register_link(const pstring &sin, const pstring &sout);
|
||||
void register_param(const pstring ¶m, const pstring &value);
|
||||
void register_param(const pstring ¶m, const double value);
|
||||
|
||||
void register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const astring &name, netlist_object_t &obj, netlist_input_t::state_e state);
|
||||
void register_object(netlist_device_t &dev, netlist_core_device_t &upd_dev, const pstring &name, netlist_object_t &obj, netlist_input_t::state_e state);
|
||||
|
||||
netlist_terminal_t &find_terminal(const astring &outname_in);
|
||||
netlist_terminal_t &find_terminal(const astring &outname_in, netlist_object_t::type_t atype);
|
||||
netlist_terminal_t &find_terminal(const pstring &outname_in);
|
||||
netlist_terminal_t &find_terminal(const pstring &outname_in, netlist_object_t::type_t atype);
|
||||
|
||||
netlist_param_t &find_param(const astring ¶m_in);
|
||||
netlist_param_t &find_param(const pstring ¶m_in);
|
||||
|
||||
void register_callback(const astring &devname, netlist_output_delegate delegate);
|
||||
void register_callback(const pstring &devname, netlist_output_delegate delegate);
|
||||
|
||||
void parse(char *buf);
|
||||
|
||||
@ -123,10 +134,10 @@ private:
|
||||
netlist_base_t &m_netlist;
|
||||
|
||||
tagmap_devices_t m_devices;
|
||||
tagmap_astring_t m_alias;
|
||||
tagmap_nstring_t m_alias;
|
||||
tagmap_param_t m_params;
|
||||
tagmap_link_t m_links;
|
||||
tagmap_astring_t m_params_temp;
|
||||
tagmap_link_t m_links;
|
||||
tagmap_nstring_t m_params_temp;
|
||||
|
||||
int m_proxy_cnt;
|
||||
|
||||
@ -136,9 +147,9 @@ private:
|
||||
void connect_terminal_input(netlist_terminal_t &term, netlist_input_t &inp);
|
||||
|
||||
// helpers
|
||||
astring objtype_as_astr(netlist_object_t &in);
|
||||
pstring objtype_as_astr(netlist_object_t &in);
|
||||
|
||||
const astring resolve_alias(const astring &name) const;
|
||||
const pstring resolve_alias(const pstring &name) const;
|
||||
};
|
||||
|
||||
#endif /* NLSETUP_H_ */
|
||||
|
@ -26,50 +26,50 @@ struct netlist_time
|
||||
{
|
||||
public:
|
||||
|
||||
typedef UINT64 INTERNALTYPE;
|
||||
typedef UINT64 INTERNALTYPE;
|
||||
|
||||
static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
|
||||
static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
|
||||
|
||||
ATTR_HOT inline netlist_time() : m_time(0) {}
|
||||
ATTR_HOT inline netlist_time() : m_time(0) {}
|
||||
|
||||
ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
|
||||
ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor);
|
||||
ATTR_HOT friend inline const UINT32 operator/(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right);
|
||||
ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right);
|
||||
|
||||
ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
|
||||
ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
|
||||
ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
|
||||
ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
|
||||
|
||||
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
|
||||
ATTR_HOT inline const INTERNALTYPE as_raw() const { return m_time; }
|
||||
ATTR_HOT inline const double as_double() const { return (double) m_time / (double) RESOLUTION; }
|
||||
|
||||
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
|
||||
ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
|
||||
ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
|
||||
ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); }
|
||||
ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); }
|
||||
ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); }
|
||||
ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
|
||||
|
||||
static const netlist_time zero;
|
||||
static const netlist_time zero;
|
||||
|
||||
protected:
|
||||
|
||||
ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
|
||||
ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {}
|
||||
|
||||
INTERNALTYPE m_time;
|
||||
INTERNALTYPE m_time;
|
||||
};
|
||||
|
||||
ATTR_HOT inline const netlist_time operator-(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time - right.m_time);
|
||||
return netlist_time::from_raw(left.m_time - right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const netlist_time operator*(const netlist_time &left, const UINT32 factor)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time * factor);
|
||||
return netlist_time::from_raw(left.m_time * factor);
|
||||
}
|
||||
|
||||
ATTR_HOT inline const UINT32 operator/(const netlist_time &left, const netlist_time &right)
|
||||
@ -79,27 +79,27 @@ ATTR_HOT inline const UINT32 operator/(const netlist_time &left, const netlist_t
|
||||
|
||||
ATTR_HOT inline const netlist_time operator+(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return netlist_time::from_raw(left.m_time + right.m_time);
|
||||
return netlist_time::from_raw(left.m_time + right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time < right.m_time);
|
||||
return (left.m_time < right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time > right.m_time);
|
||||
return (left.m_time > right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time <= right.m_time);
|
||||
return (left.m_time <= right.m_time);
|
||||
}
|
||||
|
||||
ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
|
||||
{
|
||||
return (left.m_time >= right.m_time);
|
||||
return (left.m_time >= right.m_time);
|
||||
}
|
||||
|
||||
|
||||
|
218
src/emu/netlist/pstring.c
Normal file
218
src/emu/netlist/pstring.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* nl_string.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pstring.h"
|
||||
#include <cstdio>
|
||||
|
||||
//nstring::str_t *nstring::m_zero = NULL;
|
||||
pstring::str_t *pstring::m_zero = pstring::salloc(0);
|
||||
pstring::memblock *pstring::m_first = NULL;
|
||||
|
||||
#define IMMEDIATE_MODE (1)
|
||||
#define DEBUG_MODE (0)
|
||||
|
||||
pstring::~pstring()
|
||||
{
|
||||
sfree(m_ptr);
|
||||
}
|
||||
|
||||
void pstring::init()
|
||||
{
|
||||
if (m_zero == NULL)
|
||||
{
|
||||
m_zero = (str_t *) alloc_str(sizeof(str_t) + 1);
|
||||
m_zero->reference_count = 1;
|
||||
m_zero->m_len = 0;
|
||||
m_zero->m_str[0] = 0;
|
||||
}
|
||||
m_ptr = m_zero;
|
||||
m_ptr->reference_count++;
|
||||
}
|
||||
|
||||
void pstring::pcat(const char *s)
|
||||
{
|
||||
int slen = strlen(s);
|
||||
str_t *n = salloc(m_ptr->len() + slen);
|
||||
if (m_ptr->len() > 0)
|
||||
memcpy(n->str(), m_ptr->str(), m_ptr->len());
|
||||
if (slen > 0)
|
||||
memcpy(n->str() + m_ptr->len(), s, slen);
|
||||
*(n->str() + n->len()) = 0;
|
||||
sfree(m_ptr);
|
||||
m_ptr = n;
|
||||
}
|
||||
|
||||
void pstring::pcopy(const char *from, int size)
|
||||
{
|
||||
str_t *n = salloc(size);
|
||||
if (size > 0)
|
||||
memcpy(n->str(), from, size);
|
||||
*(n->str() + size) = 0;
|
||||
sfree(m_ptr);
|
||||
m_ptr = n;
|
||||
}
|
||||
|
||||
pstring pstring::substr(unsigned int start, int count) const
|
||||
{
|
||||
int alen = len();
|
||||
if (start >= alen)
|
||||
return pstring();
|
||||
if (count <0 || start + count > alen)
|
||||
count = alen - start;
|
||||
pstring ret;
|
||||
ret.pcopy(cstr() + start, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pstring pstring::vprintf(va_list args) const
|
||||
{
|
||||
// sprintf into the temporary buffer
|
||||
char tempbuf[4096];
|
||||
vsprintf(tempbuf, cstr(), args);
|
||||
|
||||
return pstring(tempbuf);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// static stuff ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void pstring::sfree(str_t *s)
|
||||
{
|
||||
s->reference_count--;
|
||||
if (s->reference_count == 0)
|
||||
dealloc_str(s);
|
||||
}
|
||||
|
||||
pstring::str_t *pstring::salloc(int n)
|
||||
{
|
||||
str_t *ret = (str_t *) alloc_str(sizeof(str_t) + n + 1);
|
||||
ret->reference_count = 1;
|
||||
ret->m_len = n;
|
||||
ret->m_str[0] = 0;
|
||||
return ret;
|
||||
//std::printf("old string %d <%s> %p %p\n", n, old, old, m_ptr);
|
||||
}
|
||||
|
||||
pstring pstring::sprintf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
pstring ret = pstring(format).vprintf(ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *pstring::alloc_str(int n)
|
||||
{
|
||||
#if (IMMEDIATE_MODE)
|
||||
return (char *) malloc(n);
|
||||
#else
|
||||
#if (DEBUG_MODE)
|
||||
int min_alloc = MAX(0, n+sizeof(memblock));
|
||||
#else
|
||||
int min_alloc = MAX(8192, n+sizeof(memblock));
|
||||
#endif
|
||||
char *ret = NULL;
|
||||
|
||||
//std::printf("m_first %p\n", m_first);
|
||||
for (memblock *p = m_first; p != NULL && ret == NULL; p = p->next)
|
||||
{
|
||||
if (p->remaining > n)
|
||||
{
|
||||
ret = p->cur;
|
||||
p->cur += n;
|
||||
p->allocated += 1;
|
||||
p->remaining -= n;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
// need to allocate a new block
|
||||
memblock *p = (memblock *) malloc(min_alloc); //new char[min_alloc];
|
||||
p->allocated = 0;
|
||||
p->cur = &p->data[0];
|
||||
p->size = p->remaining = min_alloc - sizeof(memblock);
|
||||
p->next = m_first;
|
||||
//std::printf("allocated block size %d\n", p->size);
|
||||
|
||||
ret = p->cur;
|
||||
p->cur += n;
|
||||
p->allocated += 1;
|
||||
p->remaining -= n;
|
||||
|
||||
m_first = p;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pstring::dealloc_str(void *ptr)
|
||||
{
|
||||
#if (IMMEDIATE_MODE)
|
||||
free(ptr);
|
||||
#else
|
||||
for (memblock *p = m_first; p != NULL; p = p->next)
|
||||
{
|
||||
if (ptr >= &p->data[0] && ptr < &p->data[p->size])
|
||||
{
|
||||
p->allocated -= 1;
|
||||
if (p->allocated < 0)
|
||||
fatalerror("nstring: memory corruption\n");
|
||||
if (p->allocated == 0)
|
||||
{
|
||||
//std::printf("Block entirely freed\n");
|
||||
p->remaining = p->size;
|
||||
p->cur = &p->data[0];
|
||||
}
|
||||
// shutting down ?
|
||||
if (m_zero == NULL)
|
||||
resetmem(); // try to free blocks
|
||||
return;
|
||||
}
|
||||
}
|
||||
fatalerror("nstring: string <%p> not found\n", ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pstring::resetmem()
|
||||
{
|
||||
#if (IMMEDIATE_MODE)
|
||||
#else
|
||||
memblock **p = &m_first;
|
||||
int totalblocks = 0;
|
||||
int freedblocks = 0;
|
||||
|
||||
// Release the 0 string
|
||||
if (m_zero != NULL) sfree(m_zero);
|
||||
m_zero = NULL;
|
||||
|
||||
while (*p != NULL)
|
||||
{
|
||||
totalblocks++;
|
||||
memblock **next = &((*p)->next);
|
||||
if ((*p)->allocated == 0)
|
||||
{
|
||||
//std::printf("freeing block %p\n", *p);
|
||||
memblock *freeme = *p;
|
||||
*p = *next;
|
||||
free(freeme); //delete[] *p;
|
||||
freedblocks++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (DEBUG_MODE)
|
||||
std::printf("Allocated: <%s>\n", ((str_t *)(&(*p)->data[0]))->str());
|
||||
#endif
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
#if (DEBUG_MODE)
|
||||
std::printf("Freed %d out of total %d blocks\n", freedblocks, totalblocks);
|
||||
#endif
|
||||
#endif
|
||||
}
|
164
src/emu/netlist/pstring.h
Normal file
164
src/emu/netlist/pstring.h
Normal file
@ -0,0 +1,164 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
/*
|
||||
* pstring.h
|
||||
*/
|
||||
|
||||
#ifndef _PSTRING_H_
|
||||
#define _PSTRING_H_
|
||||
|
||||
#include "nl_config.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// nstring: immutable strings ...
|
||||
//
|
||||
// nstrings are just a pointer to a "pascal-style" string representation.
|
||||
// It uses reference counts and only uses new memory when a string changes.
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
struct pstring
|
||||
{
|
||||
public:
|
||||
// simple construction/destruction
|
||||
pstring()
|
||||
{
|
||||
init();
|
||||
}
|
||||
~pstring();
|
||||
|
||||
// construction with copy
|
||||
pstring(const char *string) {init(); if (string != NULL) pcopy(string); }
|
||||
pstring(const pstring &string) {init(); pcopy(string); }
|
||||
|
||||
// assignment operators
|
||||
pstring &operator=(const char *string) { pcopy(string); return *this; }
|
||||
pstring &operator=(const pstring &string) { pcopy(string); return *this; }
|
||||
|
||||
// C string conversion operators and helpers
|
||||
operator const char *() const { return m_ptr->str(); }
|
||||
inline const char *cstr() const { return m_ptr->str(); }
|
||||
|
||||
// concatenation operators
|
||||
pstring& operator+=(const pstring &string) { pcat(string.cstr()); return *this; }
|
||||
friend pstring operator+(const pstring &lhs, const pstring &rhs) { return pstring(lhs) += rhs; }
|
||||
friend pstring operator+(const pstring &lhs, const char *rhs) { return pstring(lhs) += rhs; }
|
||||
friend pstring operator+(const char *lhs, const pstring &rhs) { return pstring(lhs) += rhs; }
|
||||
|
||||
// comparison operators
|
||||
bool operator==(const char *string) const { return (pcmp(string) == 0); }
|
||||
bool operator==(const pstring &string) const { return (pcmp(string.cstr()) == 0); }
|
||||
bool operator!=(const char *string) const { return (pcmp(string) != 0); }
|
||||
bool operator!=(const pstring &string) const { return (pcmp(string.cstr()) != 0); }
|
||||
bool operator<(const char *string) const { return (pcmp(string) < 0); }
|
||||
bool operator<(const pstring &string) const { return (pcmp(string.cstr()) < 0); }
|
||||
bool operator<=(const char *string) const { return (pcmp(string) <= 0); }
|
||||
bool operator<=(const pstring &string) const { return (pcmp(string.cstr()) <= 0); }
|
||||
bool operator>(const char *string) const { return (pcmp(string) > 0); }
|
||||
bool operator>(const pstring &string) const { return (pcmp(string.cstr()) > 0); }
|
||||
bool operator>=(const char *string) const { return (pcmp(string) >= 0); }
|
||||
bool operator>=(const pstring &string) const { return (pcmp(string.cstr()) >= 0); }
|
||||
|
||||
//
|
||||
inline const int len() const { return m_ptr->len(); }
|
||||
|
||||
inline bool equals(const pstring &string) { return (pcmp(string.cstr(), m_ptr->str()) == 0); }
|
||||
int cmp(pstring &string) { return pcmp(string.cstr()); }
|
||||
|
||||
int find(const char *search, int start = 0) const
|
||||
{
|
||||
int alen = len();
|
||||
const char *result = strstr(cstr() + MIN(start, alen), search);
|
||||
return (result != NULL) ? (result - cstr()) : -1;
|
||||
}
|
||||
|
||||
// various
|
||||
|
||||
bool startsWith(pstring &arg) { return (pcmp(cstr(), arg.cstr(), arg.len()) == 0); }
|
||||
bool startsWith(const char *arg) { return (pcmp(cstr(), arg, strlen(arg)) == 0); }
|
||||
|
||||
// these return nstring ...
|
||||
pstring cat(const pstring &s) const { return *this + s; }
|
||||
pstring cat(const char *s) const { return *this + s; }
|
||||
|
||||
pstring substr(unsigned int start, int count = -1) const ;
|
||||
|
||||
pstring left(unsigned int count) const { return substr(0, count); }
|
||||
pstring right(unsigned int count) const { return substr(len() - count, count); }
|
||||
|
||||
// printf using string as format ...
|
||||
|
||||
pstring vprintf(va_list args) const;
|
||||
|
||||
// static
|
||||
static pstring sprintf(const char *format, ...);
|
||||
static void resetmem();
|
||||
|
||||
protected:
|
||||
|
||||
struct str_t
|
||||
{
|
||||
int reference_count;
|
||||
char *str() { return &m_str[0]; }
|
||||
int len() { return m_len; }
|
||||
//private:
|
||||
int m_len;
|
||||
char m_str[];
|
||||
};
|
||||
|
||||
str_t *m_ptr;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
inline int pcmp(const char *right) const
|
||||
{
|
||||
return pcmp(m_ptr->str(), right);
|
||||
}
|
||||
|
||||
inline int pcmp(const char *left, const char *right, int count = -1) const
|
||||
{
|
||||
if (count < 0)
|
||||
return strcmp(left, right);
|
||||
else
|
||||
return strncmp(left, right, count);
|
||||
}
|
||||
|
||||
void pcopy(const char *from, int size);
|
||||
|
||||
inline void pcopy(const char *from)
|
||||
{
|
||||
pcopy(from, strlen(from));
|
||||
}
|
||||
|
||||
inline void pcopy(const pstring &from)
|
||||
{
|
||||
sfree(m_ptr);
|
||||
m_ptr = from.m_ptr;
|
||||
m_ptr->reference_count++;
|
||||
}
|
||||
|
||||
void pcat(const char *s);
|
||||
|
||||
static str_t *m_zero;
|
||||
|
||||
static str_t *salloc(int n);
|
||||
static void sfree(str_t *s);
|
||||
|
||||
struct memblock
|
||||
{
|
||||
memblock *next;
|
||||
int size;
|
||||
int allocated;
|
||||
int remaining;
|
||||
char *cur;
|
||||
char data[];
|
||||
};
|
||||
|
||||
static memblock *m_first;
|
||||
static char *alloc_str(int n);
|
||||
static void dealloc_str(void *ptr);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _PSTRING_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user