Cleaned up includes in header files and reworked memory allocation. (nw)

This commit is contained in:
couriersud 2015-05-24 13:00:35 +02:00
parent 790cec0ac3
commit fede658aa6
27 changed files with 431 additions and 302 deletions

View File

@ -7,7 +7,6 @@ files {
MAME_DIR .. "src/emu/netlist/nl_lists.h",
MAME_DIR .. "src/emu/netlist/nl_time.h",
MAME_DIR .. "src/emu/netlist/nl_util.h",
MAME_DIR .. "src/emu/netlist/plists.h",
MAME_DIR .. "src/emu/netlist/nl_base.c",
MAME_DIR .. "src/emu/netlist/nl_base.h",
MAME_DIR .. "src/emu/netlist/nl_parser.c",
@ -16,8 +15,12 @@ files {
MAME_DIR .. "src/emu/netlist/nl_setup.h",
MAME_DIR .. "src/emu/netlist/nl_factory.c",
MAME_DIR .. "src/emu/netlist/nl_factory.h",
MAME_DIR .. "src/emu/netlist/pconfig.h",
MAME_DIR .. "src/emu/netlist/palloc.c",
MAME_DIR .. "src/emu/netlist/palloc.h",
MAME_DIR .. "src/emu/netlist/pstring.c",
MAME_DIR .. "src/emu/netlist/pstring.h",
MAME_DIR .. "src/emu/netlist/plists.h",
MAME_DIR .. "src/emu/netlist/pstate.c",
MAME_DIR .. "src/emu/netlist/pstate.h",
MAME_DIR .. "src/emu/netlist/analog/nld_bjt.c",

View File

@ -67,20 +67,12 @@ private:
template <int m_N, int _storage_N>
netlist_matrix_solver_direct_t<m_N, _storage_N>::~netlist_matrix_solver_direct_t()
{
for (int k=0; k<_storage_N; k++)
{
//delete[] m_A[k];
}
for (int k = 0; k < N(); k++)
{
nl_free(m_terms[k]);
pfree(m_terms[k]);
}
//delete[] m_last_RHS;
//delete[] m_RHS;
nl_free_array(m_terms);
nl_free_array(m_rails_temp);
//delete[] m_row_ops;
pfree_array(m_terms);
pfree_array(m_rails_temp);
}
template <int m_N, int _storage_N>
@ -431,12 +423,12 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(
, m_dim(size)
, m_lp_fact(0)
{
m_terms = nl_alloc_array(terms_t *, N());
m_rails_temp = nl_alloc_array(terms_t, N());
m_terms = palloc_array(terms_t *, N());
m_rails_temp = palloc_array(terms_t, N());
for (int k = 0; k < N(); k++)
{
m_terms[k] = nl_alloc(terms_t);
m_terms[k] = palloc(terms_t);
}
}
@ -446,12 +438,12 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(
, m_dim(size)
, m_lp_fact(0)
{
m_terms = nl_alloc_array(terms_t *, N());
m_rails_temp = nl_alloc_array(terms_t, N());
m_terms = palloc_array(terms_t *, N());
m_rails_temp = palloc_array(terms_t, N());
for (int k = 0; k < N(); k++)
{
m_terms[k] = nl_alloc(terms_t);
m_terms[k] = palloc(terms_t);
}
}

View File

@ -8,8 +8,6 @@
#ifndef NLD_MS_GAUSS_SEIDEL_H_
#define NLD_MS_GAUSS_SEIDEL_H_
#include <cmath>
#include "nld_solver.h"
#include "nld_ms_direct.h"

View File

@ -12,8 +12,6 @@
#ifndef NLD_MS_SOR_H_
#define NLD_MS_SOR_H_
#include <cmath>
#include "nld_solver.h"
#include "nld_ms_direct.h"

View File

@ -12,8 +12,6 @@
#ifndef NLD_MS_SOR_MAT_H_
#define NLD_MS_SOR_MAT_H_
#include <cmath>
#include "nld_solver.h"
#include "nld_ms_direct.h"
@ -64,13 +62,13 @@ void netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::log_stats()
{
if (this->m_stat_calculations != 0 && m_log_stats)
{
printf("==============================================\n");
printf("Solver %s\n", this->name().cstr());
printf(" ==> %d nets\n", this->N()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr());
printf(" has %s elements\n", this->is_dynamic() ? "dynamic" : "no dynamic");
printf(" has %s elements\n", this->is_timestep() ? "timestep" : "no timestep");
printf(" %6.3f average newton raphson loops\n", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls);
printf(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %6.3f average\n",
this->netlist().log("==============================================\n");
this->netlist().log("Solver %s\n", this->name().cstr());
this->netlist().log(" ==> %d nets\n", this->N()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr());
this->netlist().log(" has %s elements\n", this->is_dynamic() ? "dynamic" : "no dynamic");
this->netlist().log(" has %s elements\n", this->is_timestep() ? "timestep" : "no timestep");
this->netlist().log(" %6.3f average newton raphson loops\n", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls);
this->netlist().log(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %6.3f average\n",
this->m_stat_calculations,
this->m_stat_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0),
this->m_gs_fail,

View File

@ -79,8 +79,7 @@ ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType typ
ATTR_COLD netlist_matrix_solver_t::~netlist_matrix_solver_t()
{
for (int i = 0; i < m_inps.count(); i++)
global_free(m_inps[i]);
m_inps.clear_and_free();
}
ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets)
@ -144,7 +143,7 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets
if (net_proxy_output == NULL)
{
net_proxy_output = nl_alloc(netlist_analog_output_t);
net_proxy_output = palloc(netlist_analog_output_t);
net_proxy_output->init_object(*this, this->name() + "." + pstring::sprintf("m%d", m_inps.count()));
m_inps.add(net_proxy_output);
net_proxy_output->m_proxied_net = &p->net().as_analog();
@ -352,7 +351,7 @@ NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
while (e != NULL)
{
netlist_matrix_solver_t * const *en = m_mat_solvers.next(e);
global_free(*e);
pfree(*e);
e = en;
}
@ -410,9 +409,9 @@ template <int m_N, int _storage_N>
netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int gs_threshold, const bool use_specific)
{
if (use_specific && m_N == 1)
return nl_alloc(netlist_matrix_solver_direct1_t, m_params);
return palloc(netlist_matrix_solver_direct1_t, m_params);
else if (use_specific && m_N == 2)
return nl_alloc(netlist_matrix_solver_direct2_t, m_params);
return palloc(netlist_matrix_solver_direct2_t, m_params);
else
{
if (size >= gs_threshold)
@ -420,18 +419,18 @@ netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int
if (USE_MATRIX_GS)
{
typedef netlist_matrix_solver_SOR_mat_t<m_N,_storage_N> solver_mat;
return nl_alloc(solver_mat, m_params, size);
return palloc(solver_mat, m_params, size);
}
else
{
typedef netlist_matrix_solver_SOR_t<m_N,_storage_N> solver_GS;
return nl_alloc(solver_GS, m_params, size);
return palloc(solver_GS, m_params, size);
}
}
else
{
typedef netlist_matrix_solver_direct_t<m_N,_storage_N> solver_D;
return nl_alloc(solver_D, m_params, size);
return palloc(solver_D, m_params, size);
}
}
}

View File

@ -171,8 +171,8 @@ NETLIB_UPDATE_PARAM(POT)
m_R1.update_dev();
m_R2.update_dev();
m_R1.set_R(MAX(m_R.Value() * v, netlist().gmin()));
m_R2.set_R(MAX(m_R.Value() * (1.0 - v), netlist().gmin()));
m_R1.set_R(std::max(m_R.Value() * v, netlist().gmin()));
m_R2.set_R(std::max(m_R.Value() * (1.0 - v), netlist().gmin()));
}
@ -218,7 +218,7 @@ NETLIB_UPDATE_PARAM(POT2)
m_R1.update_dev();
m_R1.set_R(MAX(m_R.Value() * v, netlist().gmin()));
m_R1.set_R(std::max(m_R.Value() * v, netlist().gmin()));
}
// ----------------------------------------------------------------------------------------

View File

@ -5,6 +5,8 @@
*
*/
#include <cstdio>
#include "nld_log.h"
//#include "sound/wavwrite.h"
@ -24,12 +26,12 @@ NETLIB_RESET(log)
NETLIB_UPDATE(log)
{
fprintf(m_file, "%20.9e %e\n", netlist().time().as_double(), (nl_double) INPANALOG(m_I));
std::fprintf(static_cast<FILE *>(m_file), "%20.9e %e\n", netlist().time().as_double(), (nl_double) INPANALOG(m_I));
}
NETLIB_NAME(log)::~NETLIB_NAME(log)()
{
fclose(m_file);
std::fclose(static_cast<FILE *>(m_file));
}
NETLIB_START(logD)
@ -44,7 +46,7 @@ NETLIB_RESET(logD)
NETLIB_UPDATE(logD)
{
fprintf(m_file, "%e %e\n", netlist().time().as_double(), (nl_double) (INPANALOG(m_I) - INPANALOG(m_I2)));
std::fprintf(static_cast<FILE *>(m_file), "%e %e\n", netlist().time().as_double(), (nl_double) (INPANALOG(m_I) - INPANALOG(m_I2)));
}
// FIXME: Implement wav later, this must be clock triggered device where the input to be written

View File

@ -28,7 +28,7 @@ NETLIB_DEVICE(log,
~NETLIB_NAME(log)();
netlist_analog_input_t m_I;
protected:
FILE * m_file;
void * m_file;
);
#define LOGD(_name, _I, _I2) \

View File

@ -5,6 +5,10 @@
*
*/
#include <cstring>
#include "palloc.h"
#include "nl_base.h"
#include "devices/nld_system.h"
#include "analog/nld_solver.h"
@ -13,6 +17,28 @@
const netlist_time netlist_time::zero = netlist_time::from_raw(0);
//============================================================
// Exceptions
//============================================================
// emu_fatalerror is a generic fatal exception that provides an error string
nl_fatalerror::nl_fatalerror(const char *format, ...)
{
va_list ap;
va_start(ap, format);
m_text = pstring(format).vprintf(ap);
va_end(ap);
}
nl_fatalerror::nl_fatalerror(const char *format, va_list ap)
{
m_text = pstring(format).vprintf(ap);
}
// ----------------------------------------------------------------------------------------
// netlist_logic_family_ttl_t
// ----------------------------------------------------------------------------------------
class netlist_logic_family_ttl_t : public netlist_logic_family_desc_t
{
public:
@ -28,7 +54,7 @@ public:
}
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const
{
return nl_alloc(nld_d_to_a_proxy , proxied);
return palloc(nld_d_to_a_proxy , proxied);
}
};
@ -48,7 +74,7 @@ public:
}
virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const
{
return nl_alloc(nld_d_to_a_proxy , proxied);
return palloc(nld_d_to_a_proxy , proxied);
}
};
@ -84,9 +110,10 @@ void netlist_queue_t::on_pre_save()
for (int i = 0; i < m_qsize; i++ )
{
m_times[i] = this->listptr()[i].exec_time().as_raw();
const char *p = this->listptr()[i].object()->name().cstr();
int n = MIN(63, strlen(p));
strncpy(&(m_name[i][0]), p, n);
pstring p = this->listptr()[i].object()->name();
int n = p.len();
n = std::min(63, n);
std::strncpy(&(m_name[i][0]), p, n);
m_name[i][n] = 0;
}
}
@ -117,7 +144,7 @@ ATTR_COLD netlist_object_t::netlist_object_t(const type_t atype, const family_t
ATTR_COLD netlist_object_t::~netlist_object_t()
{
//delete m_name;
}
ATTR_COLD void netlist_object_t::init_object(netlist_base_t &nl, const pstring &aname)
@ -161,10 +188,10 @@ netlist_base_t::netlist_base_t()
m_stop(netlist_time::zero),
m_time(netlist_time::zero),
m_queue(*this),
m_use_deactivate(0),
m_mainclock(NULL),
m_solver(NULL),
m_gnd(NULL),
m_use_deactivate(0),
m_setup(NULL)
{
}
@ -175,7 +202,7 @@ netlist_base_t::~netlist_base_t()
{
if (!m_nets[i]->isRailNet())
{
global_free(m_nets[i]);
pfree(m_nets[i]);
}
}

View File

@ -254,6 +254,32 @@ ATTR_COLD virtual const netlist_logic_family_desc_t *default_logic_family()
return &netlist_family_ ## _fam; \
}
//============================================================
// Exceptions
//============================================================
class nl_fatalerror : public std::exception
{
public:
nl_fatalerror(const char *format, ...) ATTR_PRINTF(2,3);
nl_fatalerror(const char *format, va_list ap);
virtual ~nl_fatalerror() throw() {}
inline const pstring &text() { return m_text; }
private:
pstring m_text;
};
//============================================================
// Asserts
//============================================================
#ifdef MAME_DEBUG
#define nl_assert(x) do { if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0)
#else
#define nl_assert(x) do { if (0) if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0)
#endif
#define nl_assert_always(x, msg) do { if (!(x)) throw nl_fatalerror("Fatal error: %s\nCaused by assert: %s:%d: %s", msg, __FILE__, __LINE__, #x); } while (0)
// -----------------------------------------------------------------------------
@ -619,8 +645,6 @@ protected:
}
};
//#define INPVAL(_x) (_x).Q()
// -----------------------------------------------------------------------------
// net_net_t
// -----------------------------------------------------------------------------
@ -1246,12 +1270,12 @@ private:
netlist_time m_time;
netlist_queue_t m_queue;
bool m_use_deactivate;
NETLIB_NAME(mainclock) * m_mainclock;
NETLIB_NAME(solver) * m_solver;
NETLIB_NAME(gnd) * m_gnd;
bool m_use_deactivate;
NETLIB_NAME(netlistparams) *m_params;
netlist_setup_t *m_setup;
};

View File

@ -8,14 +8,7 @@
#ifndef NLCONFIG_H_
#define NLCONFIG_H_
/* FIXME: at some time, make it compile on its own */
#include "osdcore.h"
#include "corealloc.h"
#include "eminline.h"
#include <math.h>
#include <exception>
#include <typeinfo>
#include "pconfig.h"
//============================================================
// SETUP
@ -102,8 +95,6 @@
// DEBUGGING
//============================================================
//#define fatalerror xxbreakme
#define NL_VERBOSE (0)
#define NL_KEEP_STATISTICS (0)
@ -129,16 +120,6 @@
_name(const _name &); \
_name &operator=(const _name &);
#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
#define ATTR_ALIGN __attribute__ ((aligned(64)))
#else
#define ATTR_ALIGN
#endif
#else
#define ATTR_ALIGN
#endif
//============================================================
// Performance tracking
//============================================================
@ -158,128 +139,6 @@
// this macro passes an item followed by a string version of itself as two consecutive parameters
#define NLNAME(x) x, #x
//============================================================
// Exceptions
//============================================================
// emu_fatalerror is a generic fatal exception that provides an error string
class nl_fatalerror : public std::exception
{
public:
nl_fatalerror(const char *format, ...) ATTR_PRINTF(2,3)
{
char text[1024];
va_list ap;
va_start(ap, format);
vsprintf(text, format, ap);
va_end(ap);
osd_printf_error("%s\n", text);
}
nl_fatalerror(const char *format, va_list ap)
{
char text[1024];
vsprintf(text, format, ap);
osd_printf_error("%s\n", text);
}
};
//============================================================
// Memory allocation
//============================================================
#define nl_alloc(T, ...) global_alloc(T(__VA_ARGS__))
#define nl_alloc_array(T, N) global_alloc_array(T, N)
#define nl_free(_ptr) global_free(_ptr)
#define nl_free_array(_ptr) global_free_array(_ptr)
//============================================================
// Asserts
//============================================================
#ifdef MAME_DEBUG
#define nl_assert(x) do { if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0)
#else
#define nl_assert(x) do { if (0) if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0)
//#define assert_always(x, msg) do { if (!(x)) throw emu_fatalerror("Fatal error: %s (%s:%d)", msg, __FILE__, __LINE__); } while (0)
#endif
#define nl_assert_always(x, msg) do { if (!(x)) throw nl_fatalerror("Fatal error: %s\nCaused by assert: %s:%d: %s", msg, __FILE__, __LINE__, #x); } while (0)
//============================================================
// Compiling standalone
//============================================================
// Compiling without mame ?
#ifndef ATTR_HOT
#warning ATTR_HOT not defined
// standard C includes
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
// standard C++ includes
#include <exception>
#include <typeinfo>
#include <new>
#define ATTR_HOT
#define ATTR_COLD
#define ATTR_PRINTF(n1,n2)
#define RESTRICT
#define EXPECTED
#define UNEXPECTED
#define ATTR_UNUSED __attribute__((__unused__))
/* 8-bit values */
typedef unsigned char UINT8;
typedef signed char INT8;
/* 16-bit values */
typedef unsigned short UINT16;
typedef signed short INT16;
/* 32-bit values */
#ifndef _WINDOWS_H
typedef unsigned int UINT32;
typedef signed int INT32;
#endif
/* 64-bit values */
#ifndef _WINDOWS_H
#ifdef _MSC_VER
typedef signed __int64 INT64;
typedef unsigned __int64 UINT64;
#else
__extension__ typedef unsigned long long UINT64;
__extension__ typedef signed long long INT64;
#endif
#endif
/* U64 and S64 are used to wrap long integer constants. */
#if defined(__GNUC__) || defined(_MSC_VER)
#define U64(val) val##ULL
#define S64(val) val##LL
#else
#define U64(val) val
#define S64(val) val
#endif
/* Standard MIN/MAX macros */
#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#endif
//============================================================
// WARNINGS
//============================================================

View File

@ -41,7 +41,7 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
#ifndef NL_CONVERT_CPP
#ifdef NETLIST_DEVELOPMENT
#define CHIP(_n, _t) setup.register_dev( nl_alloc(nld_ ## _t ## _dip), _n);
#define CHIP(_n, _t) setup.register_dev( palloc(nld_ ## _t ## _dip), _n);
#else
#define CHIP(_n, _t) setup.register_dev(NETLIB_NAME_STR(_t ## _dip), _n);
#endif

View File

@ -80,7 +80,7 @@ netlist_factory_t::~netlist_factory_t()
for (net_device_t_base_factory * const *e = m_list.first(); e != NULL; e = m_list.next(e))
{
net_device_t_base_factory *p = *e;
global_free(p);
pfree(p);
}
m_list.clear();
}
@ -90,7 +90,7 @@ netlist_device_t *netlist_factory_t::new_device_by_classname(const pstring &clas
for (net_device_t_base_factory * const *e = m_list.first(); e != NULL; e = m_list.next(e))
{
net_device_t_base_factory *p = *e;
if (strcmp(p->classname(), classname) == 0)
if (p->classname() == classname)
{
netlist_device_t *ret = p->Create();
return ret;
@ -111,7 +111,7 @@ net_device_t_base_factory * netlist_factory_t::factory_by_name(const pstring &na
for (net_device_t_base_factory * const *e = m_list.first(); e != NULL; e = m_list.next(e))
{
net_device_t_base_factory *p = *e;
if (strcmp(p->name(), name) == 0)
if (p->name() == name)
{
return p;
}

View File

@ -10,6 +10,7 @@
#define NLFACTORY_H_
#include "nl_config.h"
#include "palloc.h"
#include "plists.h"
#include "nl_base.h"
#include "pstring.h"
@ -54,7 +55,7 @@ public:
ATTR_COLD netlist_device_t *Create() const
{
netlist_device_t *r = nl_alloc(C);
netlist_device_t *r = palloc(C);
//r->init(setup, name);
return r;
}
@ -72,7 +73,7 @@ public:
ATTR_COLD void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
m_list.add(nl_alloc(net_device_t_factory< _C >, name, classname, def_param));
m_list.add(palloc(net_device_t_factory< _C >, name, classname, def_param));
}
ATTR_COLD netlist_device_t *new_device_by_classname(const pstring &classname) const;

View File

@ -45,7 +45,6 @@ public:
netlist_timed_queue()
{
//m_list = global_alloc_array(entry_t, SIZE);
clear();
}
@ -64,7 +63,7 @@ public:
}
*i = e;
inc_stat(m_prof_sort);
nl_assert(m_end - m_list < _Size);
//nl_assert(m_end - m_list < _Size);
}
ATTR_HOT inline const entry_t *pop()

View File

@ -5,6 +5,9 @@
*
*/
#include <cstdio>
#include "palloc.h"
#include "nl_base.h"
#include "nl_setup.h"
#include "nl_parser.h"
@ -36,7 +39,7 @@ netlist_setup_t::netlist_setup_t(netlist_base_t &netlist)
, m_proxy_cnt(0)
{
netlist.set_setup(this);
m_factory = nl_alloc(netlist_factory_t);
m_factory = palloc(netlist_factory_t);
}
void netlist_setup_t::init()
@ -55,7 +58,7 @@ netlist_setup_t::~netlist_setup_t()
m_params_temp.clear();
netlist().set_setup(NULL);
nl_free(m_factory);
pfree(m_factory);
pstring::resetmem();
}
@ -221,7 +224,7 @@ void netlist_setup_t::register_object(netlist_device_t &dev, const pstring &name
{
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", name.cstr(), val.cstr()));
double vald = 0;
if (sscanf(val.cstr(), "%lf", &vald) != 1)
if (std::sscanf(val.cstr(), "%lf", &vald) != 1)
netlist().error("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
dynamic_cast<netlist_param_double_t &>(param).initial(vald);
}
@ -231,7 +234,7 @@ void netlist_setup_t::register_object(netlist_device_t &dev, const pstring &name
{
NL_VERBOSE_OUT(("Found parameter ... %s : %s\n", name.cstr(), val.cstr()));
double vald = 0;
if (sscanf(val.cstr(), "%lf", &vald) != 1)
if (std::sscanf(val.cstr(), "%lf", &vald) != 1)
netlist().error("Invalid number conversion %s : %s\n", name.cstr(), val.cstr());
dynamic_cast<netlist_param_int_t &>(param).initial((int) vald);
}
@ -436,7 +439,7 @@ void netlist_setup_t::connect_input_output(netlist_core_terminal_t &in, netlist_
if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC))
{
netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(in);
nld_a_to_d_proxy *proxy = nl_alloc(nld_a_to_d_proxy, incast);
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast);
incast.set_proxy(proxy);
pstring x = pstring::sprintf("proxy_ad_%s_%d", in.name().cstr(), m_proxy_cnt);
m_proxy_cnt++;
@ -475,7 +478,7 @@ void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_c
{
netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(inp);
NL_VERBOSE_OUT(("connect_terminal_input: connecting proxy\n"));
nld_a_to_d_proxy *proxy = nl_alloc(nld_a_to_d_proxy, incast);
nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast);
incast.set_proxy(proxy);
pstring x = pstring::sprintf("proxy_ad_%s_%d", inp.name().cstr(), m_proxy_cnt);
m_proxy_cnt++;
@ -544,7 +547,7 @@ void netlist_setup_t::connect_terminals(netlist_core_terminal_t &t1, netlist_cor
else
{
NL_VERBOSE_OUT(("adding net ...\n"));
netlist_analog_net_t *anet = nl_alloc(netlist_analog_net_t);
netlist_analog_net_t *anet = palloc(netlist_analog_net_t);
t1.set_net(*anet);
//m_netlist.solver()->m_nets.add(anet);
// FIXME: Nets should have a unique name
@ -721,7 +724,7 @@ void netlist_setup_t::resolve_inputs()
netlist().log("Deleting net %s ...", todelete[i]->name().cstr());
netlist().m_nets.remove(todelete[i]);
if (!todelete[i]->isRailNet())
delete todelete[i];
pfree(todelete[i]);
}
pstring errstr("");

View File

@ -9,7 +9,6 @@
#define NLSETUP_H_
#include "nl_base.h"
//#include "nl_factory.h"
//============================================================
// MACROS / inline netlist definitions
@ -23,8 +22,6 @@
#define ALIAS(_alias, _name) \
setup.register_alias(# _alias, # _name);
//#define NET_NEW(_type) setup.factory().new_device_by_classname(NETLIB_NAME_STR(_type), setup)
#define NET_REGISTER_DEV(_type, _name) \
setup.register_dev(NETLIB_NAME_STR(_type), # _name);

22
src/emu/netlist/palloc.c Normal file
View File

@ -0,0 +1,22 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* palloc.c
*
*/
#include <malloc.h>
#include <xmmintrin.h>
void *palloc_raw(const size_t size)
{
//size_t asize = ((size + 63) / 64) * 64;
//return aligned_alloc(64, asize);
return _mm_malloc(size, 64);
}
void pfree_raw(void *p)
{
//free(p);
_mm_free(p);
}

93
src/emu/netlist/palloc.h Normal file
View File

@ -0,0 +1,93 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* palloc.h
*
*/
#ifndef PALLOC_H_
#define PALLOC_H_
#include "pconfig.h"
//============================================================
// Memory allocation
//============================================================
#if (PSTANDALONE)
#include <cstddef>
#include <new>
void *palloc_raw(const size_t size);
void pfree_raw(void *p);
template<typename T>
inline T *palloc_t()
{
void *p = palloc_raw(sizeof(T));
return new (p) T();
}
template<typename T, typename P1>
inline T *palloc_t(P1 &p1)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1);
}
template<typename T, typename P1, typename P2>
inline T *palloc_t(P1 &p1, P2 &p2)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2);
}
template<typename T, typename P1, typename P2, typename P3>
inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2, p3);
}
template<typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7)
{
void *p = palloc_raw(sizeof(T));
return new (p) T(p1, p2, p3, p4, p5, p6, p7);
}
template<typename T>
inline void pfree_t(T *p)
{
p->~T();
pfree_raw(p);
//delete p;
}
template <typename T>
inline T *palloc_array_t(size_t N)
{
return new T[N];
}
template <typename T>
inline void pfree_array_t(T *p)
{
delete[] p;
}
#define palloc(T, ...) palloc_t<T>(__VA_ARGS__)
#define pfree(_ptr) pfree_t(_ptr)
#define palloc_array(T, N) palloc_array_t<T>(N)
#define pfree_array(_ptr) pfree_array_t(_ptr)
#else
#include "corealloc.h"
#define palloc(T, ...) global_alloc(T(__VA_ARGS__))
#define pfree(_ptr) global_free(_ptr)
#define palloc_array(T, N) global_alloc_array(T, N)
#define pfree_array(_ptr) global_free_array(_ptr)
#endif
#endif /* NLCONFIG_H_ */

79
src/emu/netlist/pconfig.h Normal file
View File

@ -0,0 +1,79 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* pconfig.h
*
*/
#ifndef PCONFIG_H_
#define PCONFIG_H_
#ifndef PSTANDALONE
#define PSTANDALONE (0)
#endif
#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
#define ATTR_ALIGN __attribute__ ((aligned(64)))
#else
#define ATTR_ALIGN
#endif
#else
#define ATTR_ALIGN
#endif
//============================================================
// Compiling standalone
//============================================================
// Compiling without mame ?
#if !(PSTANDALONE)
#include "osdcore.h"
#else
#define ATTR_HOT
#define ATTR_COLD
#define RESTRICT
#define EXPECTED(x) (x)
#define UNEXPECTED(x) (x)
#define ATTR_PRINTF(n1,n2)
#define ATTR_UNUSED __attribute__((__unused__))
/* 8-bit values */
typedef unsigned char UINT8;
typedef signed char INT8;
/* 16-bit values */
typedef unsigned short UINT16;
typedef signed short INT16;
/* 32-bit values */
#ifndef _WINDOWS_H
typedef unsigned int UINT32;
typedef signed int INT32;
#endif
/* 64-bit values */
#ifndef _WINDOWS_H
#ifdef _MSC_VER
typedef signed __int64 INT64;
typedef unsigned __int64 UINT64;
#else
__extension__ typedef unsigned long long UINT64;
__extension__ typedef signed long long INT64;
#endif
#endif
/* U64 and S64 are used to wrap long integer constants. */
#if defined(__GNUC__) || defined(_MSC_VER)
#define U64(val) val##ULL
#define S64(val) val##LL
#else
#define U64(val) val
#define S64(val) val
#endif
#endif
#endif /* PCONFIG_H_ */

View File

@ -11,6 +11,7 @@
#define PLISTS_H_
#include "nl_config.h"
#include "palloc.h"
#include "pstring.h"
// ----------------------------------------------------------------------------------------
@ -47,7 +48,7 @@ public:
ATTR_COLD ~parray_t()
{
if (m_list != NULL)
nl_free_array(m_list);
pfree_array(m_list);
m_list = NULL;
}
@ -70,9 +71,9 @@ protected:
ATTR_COLD void set_capacity(const int new_capacity)
{
if (m_list != NULL)
nl_free_array(m_list);
pfree_array(m_list);
if (new_capacity > 0)
m_list = nl_alloc_array(_ListClass, new_capacity);
m_list = palloc_array(_ListClass, new_capacity);
else
m_list = NULL;
m_capacity = new_capacity;
@ -98,7 +99,7 @@ public:
if (m_capacity == 0)
m_list = NULL;
else
m_list = nl_alloc_array(_ListClass, m_capacity);
m_list = palloc_array(_ListClass, m_capacity);
m_count = 0;
}
@ -108,7 +109,7 @@ public:
if (m_capacity == 0)
m_list = NULL;
else
m_list = nl_alloc_array(_ListClass, m_capacity);
m_list = palloc_array(_ListClass, m_capacity);
m_count = 0;
for (int i=0; i<rhs.count(); i++)
{
@ -130,7 +131,7 @@ public:
ATTR_COLD ~plist_t()
{
if (m_list != NULL)
nl_free_array(m_list);
pfree_array(m_list);
m_list = NULL;
}
@ -178,7 +179,7 @@ public:
ATTR_HOT inline void remove_at(const int pos)
{
nl_assert((pos>=0) && (pos<m_count));
//nl_assert((pos>=0) && (pos<m_count));
m_count--;
for (int i = pos; i < m_count; i++)
{
@ -188,8 +189,8 @@ public:
ATTR_HOT inline void swap(const int pos1, const int pos2)
{
nl_assert((pos1>=0) && (pos1<m_count));
nl_assert((pos2>=0) && (pos2<m_count));
//nl_assert((pos1>=0) && (pos1<m_count));
//nl_assert((pos2>=0) && (pos2<m_count));
_ListClass tmp = m_list[pos1];
m_list[pos1] = m_list[pos2];
m_list[pos2] =tmp;
@ -227,7 +228,7 @@ public:
{
for (_ListClass *i = m_list; i < m_list + m_count; i++)
{
nl_free(*i);
pfree(*i);
}
clear();
}
@ -238,7 +239,7 @@ private:
int cnt = count();
if (new_capacity > 0)
{
_ListClass *m_new = nl_alloc_array(_ListClass, new_capacity);
_ListClass *m_new = palloc_array(_ListClass, new_capacity);
_ListClass *pd = m_new;
if (cnt > new_capacity)
@ -246,14 +247,14 @@ private:
for (_ListClass *ps = m_list; ps < m_list + cnt; ps++, pd++)
*pd = *ps;
if (m_list != NULL)
nl_free_array(m_list);
pfree_array(m_list);
m_list = m_new;
m_count = cnt;
}
else
{
if (m_list != NULL)
nl_free_array(m_list);
pfree_array(m_list);
m_list = NULL;
m_count = 0;
}
@ -402,7 +403,8 @@ public:
}
p = p->m_next;
}
nl_assert_always(false, "element not found");
//FXIME: throw a standard exception
//nl_assert_always(false, "element not found");
}
}
@ -428,7 +430,7 @@ public:
_ListClass **p = &m_head;
while (*p != &elem)
{
nl_assert(*p != NULL);
//nl_assert(*p != NULL);
p = &((*p)->m_next);
}
(*p) = elem.m_next;

View File

@ -30,7 +30,7 @@ ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pst
};
NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr));
pstate_entry_t *p = nl_alloc(pstate_entry_t, stname, dt, owner, size, count, ptr, is_ptr);
pstate_entry_t *p = palloc(pstate_entry_t, stname, dt, owner, size, count, ptr, is_ptr);
m_save.add(p);
}
@ -67,7 +67,8 @@ ATTR_COLD void pstate_manager_t::post_load()
template<> ATTR_COLD 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);
pstate_entry_t *p = nl_alloc(pstate_entry_t, stname, owner, &state);
pstate_callback_t *state_p = &state;
pstate_entry_t *p = palloc(pstate_entry_t, stname, owner, state_p);
m_save.add(p);
state.register_state(*this, stname);
}

View File

@ -8,8 +8,6 @@
#ifndef PSTATE_H_
#define PSTATE_H_
//#include "nl_config.h"
//#include "nl_time.h"
#include "plists.h"
#include "pstring.h"

View File

@ -5,10 +5,13 @@
*
*/
#include "pstring.h"
#include <new>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
//FIXME:: pstring should be locale free
#include <cctype>
#include "pstring.h"
// The following will work on linux, however not on Windows ....
@ -51,9 +54,9 @@ 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());
std::memcpy(n->str(), m_ptr->str(), m_ptr->len());
if (slen > 0)
memcpy(n->str() + m_ptr->len(), s, slen);
std::memcpy(n->str() + m_ptr->len(), s, slen);
*(n->str() + n->len()) = 0;
sfree(m_ptr);
m_ptr = n;
@ -63,7 +66,7 @@ void pstring::pcopy(const char *from, int size)
{
str_t *n = salloc(size);
if (size > 0)
memcpy(n->str(), from, size);
std::memcpy(n->str(), from, size);
*(n->str() + size) = 0;
sfree(m_ptr);
m_ptr = n;
@ -118,7 +121,7 @@ int pstring::find_last_not_of(const pstring no) const
return -1;
}
pstring pstring::replace(const pstring &search, const pstring &replace)
pstring pstring::replace(const pstring &search, const pstring &replace) const
{
pstring ret = "";
@ -158,6 +161,11 @@ pstring pstring::rtrim(const pstring ws) const
return "";
}
void pstring::pcopy(const char *from)
{
pcopy(from, strlen(from));
}
//-------------------------------------------------
// pcmpi - compare a character array to an nstring
//-------------------------------------------------
@ -167,20 +175,20 @@ int pstring::pcmpi(const char *lhs, const char *rhs, int count) const
// loop while equal until we hit the end of strings
int index;
for (index = 0; index < count; index++)
if (lhs[index] == 0 || tolower(lhs[index]) != tolower(rhs[index]))
if (lhs[index] == 0 || std::tolower(lhs[index]) != std::tolower(rhs[index]))
break;
// determine the final result
if (index < count)
return tolower(lhs[index]) - tolower(rhs[index]);
return std::tolower(lhs[index]) - std::tolower(rhs[index]);
if (lhs[index] == 0)
return 0;
return 1;
}
nl_double pstring::as_double(bool *error) const
double pstring::as_double(bool *error) const
{
nl_double ret;
double ret;
char *e = NULL;
if (error != NULL)
@ -194,7 +202,7 @@ nl_double pstring::as_double(bool *error) const
long pstring::as_long(bool *error) const
{
nl_double ret;
long ret;
char *e = NULL;
if (error != NULL)
@ -213,7 +221,7 @@ pstring pstring::vprintf(va_list args) const
{
// sprintf into the temporary buffer
char tempbuf[4096];
vsprintf(tempbuf, cstr(), args);
std::vsprintf(tempbuf, cstr(), args);
return pstring(tempbuf);
}
@ -235,6 +243,17 @@ pstring::str_t *pstring::salloc(int n)
return ret;
}
void pstring::resetmem()
{
// Release the 0 string
m_pool.m_shutdown = true;
m_pool.resetmem();
}
// ----------------------------------------------------------------------------------------
// pstring ...
// ----------------------------------------------------------------------------------------
pstring pstring::sprintf(const char *format, ...)
{
va_list ap;
@ -245,11 +264,31 @@ pstring pstring::sprintf(const char *format, ...)
}
void pstring::resetmem()
int pstring::find(const char *search, int start) const
{
// Release the 0 string
m_pool.m_shutdown = true;
m_pool.resetmem();
int alen = len();
const char *result = std::strstr(cstr() + std::min(start, alen), search);
return (result != NULL) ? (result - cstr()) : -1;
}
int pstring::find(const char search, int start) const
{
int alen = len();
const char *result = std::strchr(cstr() + std::min(start, alen), search);
return (result != NULL) ? (result - cstr()) : -1;
}
bool pstring::startsWith(const char *arg) const
{
return (pcmp(cstr(), arg, std::strlen(arg)) == 0);
}
int pstring::pcmp(const char *left, const char *right, int count) const
{
if (count < 0)
return std::strcmp(left, right);
else
return std::strncmp(left, right, count);
}
// ----------------------------------------------------------------------------------------
@ -276,8 +315,8 @@ void *pblockpool::alloc(const std::size_t n)
return (char *) malloc(n);
else
{
int memsize = ((n + m_align - 1) / m_align) * m_align;
int min_alloc = MAX(m_blocksize, memsize+sizeof(memblock)-MINDATASIZE);
std::size_t memsize = ((n + m_align - 1) / m_align) * m_align;
std::size_t min_alloc = std::max(m_blocksize, memsize+sizeof(memblock)-MINDATASIZE);
char *ret = NULL;
//std::printf("m_first %p\n", m_first);
for (memblock *p = m_first; p != NULL && ret == NULL; p = p->next)
@ -374,3 +413,4 @@ void pblockpool::resetmem()
std::printf("Freed %d out of total %d blocks\n", freedblocks, totalblocks);
}
}

View File

@ -7,16 +7,18 @@
#ifndef _PSTRING_H_
#define _PSTRING_H_
#include "nl_config.h"
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#include <cstdarg>
#define ATTR_PRINTF(x,y) __attribute__((format(printf, x, y)))
#define ATTR_UNUSED __attribute__((__unused__))
// ----------------------------------------------------------------------------------------
// pblockbool: allocate small memory more efficiently at the expense of some overhead
// ----------------------------------------------------------------------------------------
struct pblockpool {
NETLIST_PREVENT_COPYING(pblockpool)
public:
static const int MINDATASIZE = 8;
@ -48,7 +50,7 @@ private:
};
memblock *m_first;
int m_blocksize;
std::size_t m_blocksize;
int m_align;
};
@ -128,26 +130,16 @@ public:
inline int cmp(const pstring &string) const { return pcmp(string.cstr()); }
inline int cmpi(const pstring &string) const { return pcmpi(cstr(), string.cstr()); }
inline 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;
}
int find(const char *search, int start = 0) const;
inline int find(const char search, int start = 0) const
{
int alen = len();
const char *result = strchr(cstr() + MIN(start, alen), search);
return (result != NULL) ? (result - cstr()) : -1;
}
int find(const char search, int start = 0) const;
// various
inline bool startsWith(const pstring &arg) const { return (pcmp(cstr(), arg.cstr(), arg.len()) == 0); }
inline bool startsWith(const char *arg) const { return (pcmp(cstr(), arg, strlen(arg)) == 0); }
bool startsWith(const char *arg) const;
pstring replace(const pstring &search, const pstring &replace);
pstring replace(const pstring &search, const pstring &replace) const;
// these return nstring ...
inline pstring cat(const pstring &s) const { return *this + s; }
@ -171,7 +163,7 @@ public:
// conversions
nl_double as_double(bool *error = NULL) const;
double as_double(bool *error = NULL) const;
long as_long(bool *error = NULL) const;
@ -214,22 +206,13 @@ private:
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);
}
int pcmp(const char *left, const char *right, int count = -1) const;
int pcmpi(const char *lhs, const char *rhs, int count = -1) const;
void pcopy(const char *from, int size);
inline void pcopy(const char *from)
{
pcopy(from, strlen(from));
}
void pcopy(const char *from);
inline void pcopy(const pstring &from)
{

View File

@ -148,7 +148,7 @@ public:
void init()
{
m_setup = nl_alloc(netlist_setup_t, *this);
m_setup = palloc(netlist_setup_t, *this);
this->init_object(*this, "netlist");
m_setup->init();
}
@ -313,16 +313,20 @@ static void listdevices()
convert - convert a spice netlist
-------------------------------------------------*/
static const char *PSTR_RES = "RES";
static const char *PSTR_CAP = "CAP";
class convert_t
{
public:
void convert(pstring contents)
void convert(const pstring &contents)
{
nl_util::pstring_list spnl = nl_util::split(contents, "\n");
// Add gnd net
nets.add(nl_alloc(sp_net_t, "0"), false);
nets.add(palloc(sp_net_t, "0"), false);
nets[0]->terminals().add("GND");
pstring line = "";
@ -364,15 +368,15 @@ protected:
struct sp_dev_t
{
public:
sp_dev_t(const pstring atype, const pstring aname, const pstring amodel)
sp_dev_t(const pstring &atype, const pstring &aname, const pstring &amodel)
: m_type(atype), m_name(aname), m_model(amodel), m_val(0), m_has_val(false)
{}
sp_dev_t(const pstring atype, const pstring aname, double aval)
sp_dev_t(const pstring &atype, const pstring &aname, double aval)
: m_type(atype), m_name(aname), m_model(""), m_val(aval), m_has_val(true)
{}
sp_dev_t(const pstring atype, const pstring aname)
sp_dev_t(const pstring &atype, const pstring &aname)
: m_type(atype), m_name(aname), m_model(""), m_val(0.0), m_has_val(false)
{}
@ -404,7 +408,7 @@ protected:
sp_net_t * net = nets.find(netname);
if (net == NULL)
{
net = nl_alloc(sp_net_t, netname);
net = palloc(sp_net_t, netname);
nets.add(net, false);
}
net->terminals().add(termname);
@ -497,6 +501,7 @@ protected:
if (line != "")
{
nl_util::pstring_list tt = nl_util::split(line, " ", true);
double val = 0.0;
switch (tt[0].cstr()[0])
{
case ';':
@ -529,21 +534,23 @@ protected:
// FIXME: we need a is_long method ..
ATTR_UNUSED int nval =tt[4].as_long(&cerr);
if ((!cerr || tt[4].startsWith("N")) && tt.count() > 5)
devs.add(nl_alloc(sp_dev_t, "QBJT", tt[0], tt[5]), false);
devs.add(palloc(sp_dev_t, "QBJT", tt[0], tt[5]), false);
else
devs.add(nl_alloc(sp_dev_t, "QBJT", tt[0], tt[4]), false);
devs.add(palloc(sp_dev_t, "QBJT", tt[0], tt[4]), false);
add_term(tt[1], tt[0] + ".C");
add_term(tt[2], tt[0] + ".B");
add_term(tt[3], tt[0] + ".E");
}
break;
case 'R':
devs.add(nl_alloc(sp_dev_t, "RES", tt[0], get_sp_val(tt[3])), false);
val = get_sp_val(tt[3]);
devs.add(palloc(sp_dev_t, "RES", tt[0], val), false);
add_term(tt[1], tt[0] + ".1");
add_term(tt[2], tt[0] + ".2");
break;
case 'C':
devs.add(nl_alloc(sp_dev_t, "CAP", tt[0], get_sp_val(tt[3])), false);
val = get_sp_val(tt[3]);
devs.add(palloc(sp_dev_t, "CAP", tt[0], val), false);
add_term(tt[1], tt[0] + ".1");
add_term(tt[2], tt[0] + ".2");
break;
@ -551,7 +558,8 @@ protected:
// just simple Voltage sources ....
if (tt[2].equals("0"))
{
devs.add(nl_alloc(sp_dev_t, "ANALOG_INPUT", tt[0], get_sp_val(tt[3])), false);
val = get_sp_val(tt[3]);
devs.add(palloc(sp_dev_t, "ANALOG_INPUT", tt[0], val), false);
add_term(tt[1], tt[0] + ".Q");
//add_term(tt[2], tt[0] + ".2");
}
@ -560,20 +568,23 @@ protected:
break;
case 'D':
// FIXME: Rewrite resistor value
devs.add(nl_alloc(sp_dev_t, "DIODE", tt[0], tt[3]), false);
devs.add(palloc(sp_dev_t, "DIODE", tt[0], tt[3]), false);
add_term(tt[1], tt[0] + ".A");
add_term(tt[2], tt[0] + ".K");
break;
case 'X':
{
// FIXME: specific code for KICAD exports
// last element is component type
devs.add(nl_alloc(sp_dev_t, "TTL_" + tt[tt.count()-1] + "_DIP", tt[0]), false);
pstring tname = "TTL_" + tt[tt.count()-1] + "_DIP";
devs.add(palloc(sp_dev_t, tname, tt[0]), false);
for (int i=1; i < tt.count() - 1; i++)
{
pstring term = pstring::sprintf("%s.%d", tt[0].cstr(), i);
add_term(tt[i], term);
}
break;
}
default:
printf("// IGNORED %s: %s\n", tt[0].cstr(), line.cstr());
}