Added a simple preprocessor to the netlist parsing pipeline.

This preprpcessor understands defines and nested if/else/endif

#define MYMACRO 0

#if (MYMACRO)
....
#else

#endif

One can now run 

./nltool -c run -f src/mame/drivers/nl_pong.c -t 10

without removing preprocessor elements first. This does not work with
netlist originating from DICE currently. These have to be converted
first.

In addition, cleaned up __attribute__ madness in the code. Specifically
removed ATTR_COLD from virtual definitions to avoid the vtable being
declared as cold.
This commit is contained in:
couriersud 2015-05-25 18:28:03 +02:00
parent 784410e9c9
commit d68fe923a1
21 changed files with 684 additions and 419 deletions

View File

@ -18,11 +18,13 @@ files {
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/pparser.c",
MAME_DIR .. "src/emu/netlist/pparser.h",
MAME_DIR .. "src/emu/netlist/pstate.c",
MAME_DIR .. "src/emu/netlist/pstate.h",
MAME_DIR .. "src/emu/netlist/pstring.c",
MAME_DIR .. "src/emu/netlist/pstring.h",
MAME_DIR .. "src/emu/netlist/analog/nld_bjt.c",
MAME_DIR .. "src/emu/netlist/analog/nld_bjt.h",
MAME_DIR .. "src/emu/netlist/analog/nld_fourterm.c",

View File

@ -46,8 +46,8 @@ public:
inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
inline void set_qtype(q_type atype) { m_qtype = atype; }
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
ATTR_HOT void update();
netlist_param_model_t m_model;
@ -110,9 +110,9 @@ public:
protected:
ATTR_COLD virtual void start();
/* ATTR_COLD */ virtual void start();
ATTR_HOT virtual void update_param();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void reset();
NETLIB_UPDATE_TERMINALSI();
nl_double m_gB; // base conductance / switch on
@ -142,8 +142,8 @@ public:
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
ATTR_HOT void update_param();
ATTR_HOT void virtual update();
NETLIB_UPDATE_TERMINALSI();

View File

@ -56,9 +56,9 @@ public:
: netlist_device_t(afamily), m_gfac(1.0) { }
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
/* ATTR_COLD */ virtual void update_param();
ATTR_HOT void update();
ATTR_COLD void start_internal(const nl_double def_RI);
@ -112,9 +112,9 @@ public:
//: netlist_device_t(afamily), m_gfac(1.0) { }
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
/* ATTR_COLD */ virtual void update_param();
ATTR_HOT void update();
nl_double m_gfac;
@ -156,9 +156,9 @@ public:
: NETLIB_NAME(VCCS)(VCVS) { }
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
/* ATTR_COLD */ virtual void update_param();
//ATTR_HOT void update();
netlist_terminal_t m_OP2;

View File

@ -20,15 +20,15 @@ public:
virtual ~netlist_matrix_solver_direct_t();
ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets);
ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); }
/* ATTR_COLD */ virtual void vsetup(netlist_analog_net_t::list_t &nets);
/* ATTR_COLD */ virtual void reset() { netlist_matrix_solver_t::reset(); }
ATTR_HOT inline int N() const { return (m_N == 0 ? m_dim : m_N); }
ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
protected:
ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term);
/* ATTR_COLD */ virtual void add_term(int net_idx, netlist_terminal_t *term);
ATTR_HOT virtual nl_double vsolve();

View File

@ -31,7 +31,7 @@ public:
virtual ~netlist_matrix_solver_SOR_t() {}
ATTR_COLD virtual void log_stats();
/* ATTR_COLD */ virtual void log_stats();
ATTR_HOT inline int vsolve_non_dynamic();
protected:

View File

@ -30,7 +30,7 @@ public:
virtual ~netlist_matrix_solver_SOR_t() {}
ATTR_COLD virtual void log_stats();
/* ATTR_COLD */ virtual void log_stats();
ATTR_HOT virtual int vsolve_non_dynamic(const bool newton_raphson);
protected:

View File

@ -36,7 +36,7 @@ public:
virtual ~netlist_matrix_solver_SOR_mat_t() {}
ATTR_COLD virtual void log_stats();
/* ATTR_COLD */ virtual void log_stats();
ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
protected:

View File

@ -97,9 +97,9 @@ public:
};
ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t &params);
ATTR_COLD virtual ~netlist_matrix_solver_t();
/* ATTR_COLD */ virtual ~netlist_matrix_solver_t();
ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0;
/* ATTR_COLD */ virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0;
template<class C>
void solve_base(C *p);
@ -117,11 +117,11 @@ public:
/* netdevice functions */
ATTR_HOT virtual void update();
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
ATTR_COLD int get_net_idx(netlist_net_t *net);
ATTR_COLD virtual void log_stats() {};
/* ATTR_COLD */ virtual void log_stats() {};
inline eSolverType type() const { return m_type; }
@ -133,7 +133,7 @@ protected:
// should return next time step
ATTR_HOT virtual nl_double vsolve() = 0;
ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term) = 0;
/* ATTR_COLD */ virtual void add_term(int net_idx, netlist_terminal_t *term) = 0;
plist_t<netlist_analog_net_t *> m_nets;
plist_t<netlist_analog_output_t *> m_inps;
@ -170,7 +170,7 @@ public:
NETLIB_NAME(solver)()
: netlist_device_t() { }
ATTR_COLD virtual ~NETLIB_NAME(solver)();
/* ATTR_COLD */ virtual ~NETLIB_NAME(solver)();
ATTR_COLD void post_start();
ATTR_COLD void stop();

View File

@ -122,8 +122,8 @@ public:
}
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
ATTR_HOT void update();
private:
@ -144,8 +144,8 @@ public:
}
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
ATTR_HOT void update();
};
@ -193,9 +193,9 @@ public:
}
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void reset();
ATTR_COLD virtual void update_param();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void reset();
/* ATTR_COLD */ virtual void update_param();
ATTR_HOT void update();
netlist_param_double_t m_C;
@ -282,8 +282,8 @@ public:
NETLIB_UPDATE_TERMINALSI();
protected:
ATTR_COLD virtual void start();
ATTR_COLD virtual void update_param();
/* ATTR_COLD */ virtual void start();
/* ATTR_COLD */ virtual void update_param();
ATTR_HOT void update();
netlist_param_model_t m_model;

View File

@ -138,7 +138,7 @@ public:
ATTR_COLD NETLIB_NAME(gnd)()
: netlist_device_t(GND) { }
ATTR_COLD virtual ~NETLIB_NAME(gnd)() {}
/* ATTR_COLD */ virtual ~NETLIB_NAME(gnd)() {}
protected:
@ -171,7 +171,7 @@ public:
ATTR_COLD NETLIB_NAME(dummy_input)()
: netlist_device_t(DUMMY) { }
ATTR_COLD virtual ~NETLIB_NAME(dummy_input)() {}
/* ATTR_COLD */ virtual ~NETLIB_NAME(dummy_input)() {}
protected:
@ -203,7 +203,7 @@ public:
ATTR_COLD NETLIB_NAME(frontier)()
: netlist_device_t(DUMMY) { }
ATTR_COLD virtual ~NETLIB_NAME(frontier)() {}
/* ATTR_COLD */ virtual ~NETLIB_NAME(frontier)() {}
protected:
@ -238,7 +238,7 @@ public:
ATTR_COLD NETLIB_NAME(res_sw)()
: netlist_device_t() { }
ATTR_COLD virtual ~NETLIB_NAME(res_sw)() {}
/* ATTR_COLD */ virtual ~NETLIB_NAME(res_sw)() {}
netlist_param_double_t m_RON;
netlist_param_double_t m_ROFF;
@ -271,14 +271,14 @@ public:
m_proxy_term = &proxy_inout;
}
ATTR_COLD virtual ~nld_base_proxy() {}
/* ATTR_COLD */ virtual ~nld_base_proxy() {}
ATTR_COLD netlist_logic_t &term_proxied() const { return *m_term_proxied; }
ATTR_COLD netlist_core_terminal_t &proxy_term() const { return *m_proxy_term; }
protected:
ATTR_COLD virtual const netlist_logic_family_desc_t &logic_family() const
/* ATTR_COLD */ virtual const netlist_logic_family_desc_t &logic_family() const
{
return *m_logic_family;
}
@ -301,7 +301,7 @@ public:
{
}
ATTR_COLD virtual ~nld_a_to_d_proxy() {}
/* ATTR_COLD */ virtual ~nld_a_to_d_proxy() {}
netlist_analog_input_t m_I;
netlist_logic_output_t m_Q;
@ -343,12 +343,12 @@ public:
{
}
ATTR_COLD virtual ~nld_base_d_to_a_proxy() {}
/* ATTR_COLD */ virtual ~nld_base_d_to_a_proxy() {}
ATTR_COLD virtual netlist_logic_input_t &in() { return m_I; }
/* ATTR_COLD */ virtual netlist_logic_input_t &in() { return m_I; }
protected:
ATTR_COLD virtual void start()
/* ATTR_COLD */ virtual void start()
{
register_input("I", m_I);
}
@ -369,12 +369,12 @@ public:
{
}
ATTR_COLD virtual ~nld_d_to_a_proxy() {}
/* ATTR_COLD */ virtual ~nld_d_to_a_proxy() {}
protected:
ATTR_COLD virtual void start();
/* ATTR_COLD */ virtual void start();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void reset();
ATTR_HOT void update();

View File

@ -93,7 +93,7 @@ public:
{
}
ATTR_COLD virtual void start()
/* ATTR_COLD */ virtual void start()
{
pstring ttline = pstring(m_desc[0]);

View File

@ -251,7 +251,7 @@ typedef void (*net_update_delegate)(netlist_core_device_t *);
, _priv)
#define NETLIB_LOGIC_FAMILY(_fam) \
ATTR_COLD virtual const netlist_logic_family_desc_t *default_logic_family() \
/* ATTR_COLD */ virtual const netlist_logic_family_desc_t *default_logic_family() \
{ \
return &netlist_family_ ## _fam; \
}
@ -412,9 +412,9 @@ public:
protected:
ATTR_COLD virtual void reset() = 0;
/* ATTR_COLD */ virtual void reset() = 0;
// must call parent save_register !
ATTR_COLD virtual void save_register() { };
/* ATTR_COLD */ virtual void save_register() { };
private:
pstring m_name;
@ -486,7 +486,7 @@ public:
ATTR_HOT inline void update_dev(const UINT32 mask);
protected:
ATTR_COLD virtual void save_register()
/* ATTR_COLD */ virtual void save_register()
{
save(NLNAME(m_state));
netlist_owned_object_t::save_register();
@ -540,9 +540,9 @@ public:
netlist_terminal_t *m_otherterm;
protected:
ATTR_COLD virtual void save_register();
/* ATTR_COLD */ virtual void save_register();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void reset();
private:
ATTR_HOT inline void set_ptr(nl_double *ptr, const nl_double val)
{
@ -616,7 +616,7 @@ public:
ATTR_HOT inline void activate_lh();
protected:
ATTR_COLD virtual void reset()
/* ATTR_COLD */ virtual void reset()
{
//netlist_core_terminal_t::reset();
set_state(STATE_INP_ACTIVE);
@ -640,7 +640,7 @@ public:
ATTR_HOT inline nl_double Q_Analog() const;
protected:
ATTR_COLD virtual void reset()
/* ATTR_COLD */ virtual void reset()
{
//netlist_core_terminal_t::reset();
set_state(STATE_INP_ACTIVE);
@ -659,7 +659,7 @@ public:
typedef plist_t<netlist_net_t *> list_t;
ATTR_COLD netlist_net_t(const family_t afamily);
ATTR_COLD virtual ~netlist_net_t();
/* ATTR_COLD */ virtual ~netlist_net_t();
ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname);
@ -708,8 +708,8 @@ public:
protected: //FIXME: needed by current solver code
ATTR_COLD virtual void save_register();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void save_register();
/* ATTR_COLD */ virtual void reset();
netlist_sig_t m_new_Q;
netlist_sig_t m_cur_Q;
@ -739,7 +739,7 @@ public:
typedef plist_t<netlist_logic_net_t *> list_t;
ATTR_COLD netlist_logic_net_t();
ATTR_COLD virtual ~netlist_logic_net_t() { };
/* ATTR_COLD */ virtual ~netlist_logic_net_t() { };
ATTR_HOT inline netlist_sig_t Q() const
{
@ -781,8 +781,8 @@ public:
protected: //FIXME: needed by current solver code
ATTR_COLD virtual void save_register();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void save_register();
/* ATTR_COLD */ virtual void reset();
private:
@ -799,7 +799,7 @@ public:
typedef plist_t<netlist_analog_net_t *> list_t;
ATTR_COLD netlist_analog_net_t();
ATTR_COLD virtual ~netlist_analog_net_t() { };
/* ATTR_COLD */ virtual ~netlist_analog_net_t() { };
ATTR_HOT inline nl_double Q_Analog() const
{
@ -818,8 +818,8 @@ public:
protected:
ATTR_COLD virtual void save_register();
ATTR_COLD virtual void reset();
/* ATTR_COLD */ virtual void save_register();
/* ATTR_COLD */ virtual void reset();
private:
@ -844,7 +844,7 @@ public:
ATTR_COLD netlist_logic_output_t();
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname);
ATTR_COLD virtual void reset()
/* ATTR_COLD */ virtual void reset()
{
set_state(STATE_OUT);
}
@ -868,7 +868,7 @@ public:
ATTR_COLD netlist_analog_output_t();
ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname);
ATTR_COLD virtual void reset()
/* ATTR_COLD */ virtual void reset()
{
set_state(STATE_OUT);
}
@ -906,7 +906,7 @@ public:
protected:
ATTR_COLD virtual void reset() { }
/* ATTR_COLD */ virtual void reset() { }
private:
const param_type_t m_param_type;
@ -923,7 +923,7 @@ public:
ATTR_HOT inline nl_double Value() const { return m_param; }
protected:
ATTR_COLD virtual void save_register()
/* ATTR_COLD */ virtual void save_register()
{
save(NLNAME(m_param));
netlist_param_t::save_register();
@ -945,7 +945,7 @@ public:
ATTR_HOT inline int Value() const { return m_param; }
protected:
ATTR_COLD virtual void save_register()
/* ATTR_COLD */ virtual void save_register()
{
save(NLNAME(m_param));
netlist_param_t::save_register();
@ -1008,9 +1008,9 @@ public:
ATTR_COLD netlist_core_device_t(const family_t afamily);
ATTR_COLD virtual ~netlist_core_device_t();
/* ATTR_COLD */ virtual ~netlist_core_device_t();
ATTR_COLD virtual void init(netlist_base_t &anetlist, const pstring &name);
/* ATTR_COLD */ virtual void init(netlist_base_t &anetlist, const pstring &name);
ATTR_HOT virtual void update_param() {}
ATTR_HOT inline void update_dev()
@ -1076,9 +1076,9 @@ public:
protected:
ATTR_HOT virtual void update() { }
ATTR_COLD virtual void start() { }
ATTR_COLD virtual void stop() { } \
ATTR_COLD virtual const netlist_logic_family_desc_t *default_logic_family()
/* ATTR_COLD */ virtual void start() { }
/* ATTR_COLD */ virtual void stop() { } \
/* ATTR_COLD */ virtual const netlist_logic_family_desc_t *default_logic_family()
{
return &netlist_family_TTL;
}
@ -1095,9 +1095,9 @@ public:
ATTR_COLD netlist_device_t();
ATTR_COLD netlist_device_t(const family_t afamily);
ATTR_COLD virtual ~netlist_device_t();
/* ATTR_COLD */ virtual ~netlist_device_t();
ATTR_COLD virtual void init(netlist_base_t &anetlist, const pstring &name);
/* ATTR_COLD */ virtual void init(netlist_base_t &anetlist, const pstring &name);
ATTR_COLD netlist_setup_t &setup();
@ -1252,12 +1252,12 @@ protected:
};
// any derived netlist must override this ...
ATTR_COLD virtual void verror(const loglevel_e level,
/* ATTR_COLD */ virtual void verror(const loglevel_e level,
const char *format, va_list ap) const = 0;
/* from netlist_object */
ATTR_COLD virtual void reset();
ATTR_COLD virtual void save_register();
/* ATTR_COLD */ virtual void reset();
/* ATTR_COLD */ virtual void save_register();
#if (NL_KEEP_STATISTICS)
// performance

View File

@ -28,9 +28,9 @@ public:
: m_name(name), m_classname(classname), m_def_param(def_param)
{}
ATTR_COLD virtual ~net_device_t_base_factory() {}
/* ATTR_COLD */ virtual ~net_device_t_base_factory() {}
ATTR_COLD virtual netlist_device_t *Create() const = 0;
/* ATTR_COLD */ virtual netlist_device_t *Create() const = 0;
ATTR_COLD const pstring &name() const { return m_name; }
ATTR_COLD const pstring &classname() const { return m_classname; }
@ -66,8 +66,8 @@ class netlist_factory_t
public:
typedef plist_t<net_device_t_base_factory *> list_t;
ATTR_COLD netlist_factory_t();
ATTR_COLD ~netlist_factory_t();
netlist_factory_t();
~netlist_factory_t();
template<class _C>
ATTR_COLD void register_device(const pstring &name, const pstring &classname,

View File

@ -11,197 +11,6 @@
//#undef NL_VERBOSE_OUT
//#define NL_VERBOSE_OUT(x) printf x
// ----------------------------------------------------------------------------------------
// A simple tokenizer
// ----------------------------------------------------------------------------------------
pstring ptokenizer::currentline_str()
{
char buf[300];
int bufp = 0;
const char *p = m_line_ptr;
while (*p && *p != 10)
buf[bufp++] = *p++;
buf[bufp] = 0;
return pstring(buf);
}
void ptokenizer::skipeol()
{
char c = getc();
while (c)
{
if (c == 10)
{
c = getc();
if (c != 13)
ungetc();
return;
}
c = getc();
}
}
unsigned char ptokenizer::getc()
{
if (*m_px == 10)
{
m_line++;
m_line_ptr = m_px + 1;
}
if (*m_px)
return *(m_px++);
else
return *m_px;
}
void ptokenizer::ungetc()
{
m_px--;
}
void ptokenizer::require_token(const token_id_t &token_num)
{
require_token(get_token(), token_num);
}
void ptokenizer::require_token(const token_t tok, const token_id_t &token_num)
{
if (!tok.is(token_num))
{
error("Error: expected token <%s> got <%s>\n", m_tokens[token_num.id()].cstr(), tok.str().cstr());
}
}
pstring ptokenizer::get_string()
{
token_t tok = get_token();
if (!tok.is_type(STRING))
{
error("Error: expected a string, got <%s>\n", tok.str().cstr());
}
return tok.str();
}
pstring ptokenizer::get_identifier()
{
token_t tok = get_token();
if (!tok.is_type(IDENTIFIER))
{
error("Error: expected an identifier, got <%s>\n", tok.str().cstr());
}
return tok.str();
}
ptokenizer::token_t ptokenizer::get_token()
{
while (true)
{
token_t ret = get_token_internal();
if (ret.is_type(ENDOFFILE))
return ret;
if (ret.is(m_tok_comment_start))
{
do {
ret = get_token_internal();
} while (ret.is_not(m_tok_comment_end));
}
else if (ret.is(m_tok_line_comment))
{
skipeol();
}
else if (ret.str() == "#")
{
skipeol();
}
else
return ret;
}
}
ptokenizer::token_t ptokenizer::get_token_internal()
{
/* skip ws */
char c = getc();
while (m_whitespace.find(c)>=0)
{
c = getc();
if (eof())
{
return token_t(ENDOFFILE);
}
}
if (m_identifier_chars.find(c)>=0)
{
/* read identifier till non identifier char */
pstring tokstr = "";
while (m_identifier_chars.find(c)>=0) {
tokstr += c;
c = getc();
}
ungetc();
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
else
{
return token_t(IDENTIFIER, tokstr);
}
}
else if (c == m_string)
{
pstring tokstr = "";
c = getc();
while (c != m_string)
{
tokstr += c;
c = getc();
}
return token_t(STRING, tokstr);
}
else
{
/* read identifier till first identifier char or ws */
pstring tokstr = "";
while ((m_identifier_chars.find(c)) < 0 && (m_whitespace.find(c) < 0)) {
tokstr += c;
/* expensive, check for single char tokens */
if (tokstr.len() == 1)
{
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
}
c = getc();
}
ungetc();
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
else
{
return token_t(UNKNOWN, tokstr);
}
}
}
ATTR_COLD void ptokenizer::error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
pstring errmsg1 = pstring(format).vprintf(ap);
va_end(ap);
verror(errmsg1, currentline_no(), currentline_str());
//throw error;
}
// ----------------------------------------------------------------------------------------
// A netlist parser
// ----------------------------------------------------------------------------------------
@ -217,9 +26,12 @@ ATTR_COLD void netlist_parser::verror(pstring msg, int line_num, pstring line)
bool netlist_parser::parse(const char *buf, const pstring nlname)
{
m_buf = buf;
ppreprocessor prepro;
reset(buf);
pstring processed = prepro.process(buf);
m_buf = processed.cstr();
reset(m_buf);
set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
set_number_chars("01234567890eE-."); //FIXME: processing of numbers
char ws[5];

View File

@ -9,132 +9,8 @@
#define NL_PARSER_H_
#include "nl_setup.h"
class ptokenizer
{
NETLIST_PREVENT_COPYING(ptokenizer)
public:
virtual ~ptokenizer() {}
ptokenizer()
: m_line(1), m_line_ptr(NULL), m_px(NULL), m_string('"')
{}
enum token_type
{
IDENTIFIER,
NUMBER,
TOKEN,
STRING,
COMMENT,
UNKNOWN,
ENDOFFILE
};
struct token_id_t
{
public:
token_id_t() : m_id(-2) {}
token_id_t(const int id) : m_id(id) {}
int id() const { return m_id; }
private:
int m_id;
};
struct token_t
{
token_t(token_type type)
{
m_type = type;
m_id = token_id_t(-1);
m_token ="";
}
token_t(token_type type, const pstring str)
{
m_type = type;
m_id = token_id_t(-1);
m_token = str;
}
token_t(const token_id_t id, const pstring str)
{
m_type = TOKEN;
m_id = id;
m_token = str;
}
bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
bool is_type(const token_type type) const { return m_type == type; }
pstring str() const { return m_token; }
private:
token_type m_type;
token_id_t m_id;
pstring m_token;
};
int currentline_no() { return m_line; }
pstring currentline_str();
/* tokenizer stuff follows ... */
token_t get_token();
pstring get_string();
pstring get_identifier();
void require_token(const token_id_t &token_num);
void require_token(const token_t tok, const token_id_t &token_num);
token_id_t register_token(pstring token)
{
m_tokens.add(token);
return token_id_t(m_tokens.count() - 1);
}
void set_identifier_chars(pstring s) { m_identifier_chars = s; }
void set_number_chars(pstring s) { m_number_chars = s; }
void set_whitespace(pstring s) { m_whitespace = s; }
void set_comment(pstring start, pstring end, pstring line)
{
m_tok_comment_start = register_token(start);
m_tok_comment_end = register_token(end);
m_tok_line_comment = register_token(line);
m_string = '"';
}
token_t get_token_internal();
void error(const char *format, ...) ATTR_PRINTF(2,3);
protected:
void reset(const char *p) { m_px = p; m_line = 1; m_line_ptr = p; }
virtual void verror(pstring msg, int line_num, pstring line) = 0;
private:
void skipeol();
unsigned char getc();
void ungetc();
bool eof() { return *m_px == 0; }
int m_line;
const char * m_line_ptr;
const char * m_px;
/* tokenizer stuff follows ... */
pstring m_identifier_chars;
pstring m_number_chars;
plist_t<pstring> m_tokens;
pstring m_whitespace;
char m_string;
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
token_id_t m_tok_line_comment;
};
#include "nl_util.h"
#include "pparser.h"
class netlist_parser : public ptokenizer
{

View File

@ -11,6 +11,7 @@
#include "pstring.h"
#include "plists.h"
#include <cmath>
#include <cstring>
class nl_util
{
@ -45,6 +46,43 @@ public:
}
return temp;
}
static pstring_list splitexpr(const pstring &str, const pstring_list &onstrl)
{
pstring_list temp;
pstring col = "";
int i = 0;
while (i<str.len())
{
int p = -1;
for (int j=0; j < onstrl.count(); j++)
{
if (std::strncmp(onstrl[j].cstr(), &(str.cstr()[i]), onstrl[j].len())==0)
{
p = j;
break;
}
}
if (p>=0)
{
if (col != "")
temp.add(col);
col = "";
temp.add(onstrl[p]);
i += onstrl[p].len();
}
else
{
col += str.cstr()[i];
i++;
}
}
if (col != "")
temp.add(col);
return temp;
}
static const pstring environment(const pstring &var, const pstring &default_val = "")
{
if (getenv(var.cstr()) == NULL)

View File

@ -33,9 +33,9 @@
/* not supported in GCC prior to 4.4.x */
/* ATTR_HOT and ATTR_COLD cause performance degration in 5.1 */
//#define ATTR_HOT
#define ATTR_COLD
//#define ATTR_COLD
#define ATTR_HOT __attribute__((hot))
//#define ATTR_COLD __attribute__((cold))
#define ATTR_COLD __attribute__((cold))
#define RESTRICT
#define EXPECTED(x) (x)

View File

@ -44,7 +44,7 @@ public:
return *this;
}
ATTR_COLD ~parray_t()
~parray_t()
{
if (m_list != NULL)
pfree_array(m_list);
@ -127,7 +127,7 @@ public:
}
ATTR_COLD ~plist_t()
~plist_t()
{
if (m_list != NULL)
pfree_array(m_list);
@ -333,7 +333,7 @@ public:
}
ATTR_COLD ~pstack_t()
~pstack_t()
{
}

354
src/emu/netlist/pparser.c Normal file
View File

@ -0,0 +1,354 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* pparser.c
*
*/
#include "pparser.h"
//#undef NL_VERBOSE_OUT
//#define NL_VERBOSE_OUT(x) printf x
// ----------------------------------------------------------------------------------------
// A simple tokenizer
// ----------------------------------------------------------------------------------------
pstring ptokenizer::currentline_str()
{
char buf[300];
int bufp = 0;
const char *p = m_line_ptr;
while (*p && *p != 10)
buf[bufp++] = *p++;
buf[bufp] = 0;
return pstring(buf);
}
void ptokenizer::skipeol()
{
char c = getc();
while (c)
{
if (c == 10)
{
c = getc();
if (c != 13)
ungetc();
return;
}
c = getc();
}
}
unsigned char ptokenizer::getc()
{
if (*m_px == 10)
{
m_line++;
m_line_ptr = m_px + 1;
}
if (*m_px)
return *(m_px++);
else
return *m_px;
}
void ptokenizer::ungetc()
{
m_px--;
}
void ptokenizer::require_token(const token_id_t &token_num)
{
require_token(get_token(), token_num);
}
void ptokenizer::require_token(const token_t tok, const token_id_t &token_num)
{
if (!tok.is(token_num))
{
error("Error: expected token <%s> got <%s>\n", m_tokens[token_num.id()].cstr(), tok.str().cstr());
}
}
pstring ptokenizer::get_string()
{
token_t tok = get_token();
if (!tok.is_type(STRING))
{
error("Error: expected a string, got <%s>\n", tok.str().cstr());
}
return tok.str();
}
pstring ptokenizer::get_identifier()
{
token_t tok = get_token();
if (!tok.is_type(IDENTIFIER))
{
error("Error: expected an identifier, got <%s>\n", tok.str().cstr());
}
return tok.str();
}
ptokenizer::token_t ptokenizer::get_token()
{
while (true)
{
token_t ret = get_token_internal();
if (ret.is_type(ENDOFFILE))
return ret;
if (ret.is(m_tok_comment_start))
{
do {
ret = get_token_internal();
} while (ret.is_not(m_tok_comment_end));
}
else if (ret.is(m_tok_line_comment))
{
skipeol();
}
else if (ret.str() == "#")
{
skipeol();
}
else
return ret;
}
}
ptokenizer::token_t ptokenizer::get_token_internal()
{
/* skip ws */
char c = getc();
while (m_whitespace.find(c)>=0)
{
c = getc();
if (eof())
{
return token_t(ENDOFFILE);
}
}
if (m_identifier_chars.find(c)>=0)
{
/* read identifier till non identifier char */
pstring tokstr = "";
while (m_identifier_chars.find(c)>=0) {
tokstr += c;
c = getc();
}
ungetc();
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
else
{
return token_t(IDENTIFIER, tokstr);
}
}
else if (c == m_string)
{
pstring tokstr = "";
c = getc();
while (c != m_string)
{
tokstr += c;
c = getc();
}
return token_t(STRING, tokstr);
}
else
{
/* read identifier till first identifier char or ws */
pstring tokstr = "";
while ((m_identifier_chars.find(c)) < 0 && (m_whitespace.find(c) < 0)) {
tokstr += c;
/* expensive, check for single char tokens */
if (tokstr.len() == 1)
{
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
}
c = getc();
}
ungetc();
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
if (id.id() >= 0)
return token_t(id, tokstr);
else
{
return token_t(UNKNOWN, tokstr);
}
}
}
ATTR_COLD void ptokenizer::error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
pstring errmsg1 = pstring(format).vprintf(ap);
va_end(ap);
verror(errmsg1, currentline_no(), currentline_str());
//throw error;
}
// ----------------------------------------------------------------------------------------
// A simple preprocessor
// ----------------------------------------------------------------------------------------
ppreprocessor::ppreprocessor()
{
m_expr_sep.add("(");
m_expr_sep.add(")");
m_expr_sep.add("+");
m_expr_sep.add("-");
m_expr_sep.add("*");
m_expr_sep.add("/");
m_expr_sep.add("==");
m_expr_sep.add(" ");
m_expr_sep.add("\t");
}
double ppreprocessor::expr(const nl_util::pstring_list &sexpr, int &start, int prio)
{
double val;
pstring tok=sexpr[start];
if (tok == "(")
{
start++;
val = expr(sexpr, start, prio);
if (sexpr[start] != ")")
error("parsing error!");
start++;
}
else
{
tok=sexpr[start];
val = tok.as_double();
start++;
}
while (start < sexpr.count())
{
tok=sexpr[start];
if (tok == ")")
{
// FIXME: catch error
return val;
}
else if (tok == "+")
{
if (prio >= 20)
return val;
start++;
val = val + expr(sexpr, start, 10);
}
else if (tok == "-")
{
if (prio >= 20)
return val;
start++;
val = val - expr(sexpr, start, 10);
}
else if (tok == "*")
{
start++;
val = val * expr(sexpr, start, 20);
}
}
return val;
}
ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
{
for (int i = 0; i<m_defines.count(); i++)
{
if (m_defines[i].m_name == name)
return &m_defines[i];
}
return NULL;
}
pstring ppreprocessor::replace_macros(const pstring &line)
{
nl_util::pstring_list elems = nl_util::splitexpr(line, m_expr_sep);
pstring ret = "";
for (int i=0; i<elems.count(); i++)
{
define_t *def = get_define(elems[i]);
if (def != NULL)
ret = ret + def->m_replace;
else
ret = ret + elems[i];
}
return ret;
}
pstring ppreprocessor::process(const pstring &contents)
{
pstring ret = "";
nl_util::pstring_list lines = nl_util::split(contents,"\n", false);
UINT32 ifflag = 0; // 31 if levels
int level = 0;
int i=0;
while (i<lines.count())
{
pstring line = lines[i];
pstring lt = line.replace("\t"," ").trim();
lt = replace_macros(lt);
if (lt.startsWith("#"))
{
nl_util::pstring_list lti = nl_util::split(lt, " ", true);
if (lti[0].equals("#if"))
{
level++;
int start = 0;
nl_util::pstring_list t = nl_util::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep);
int val = expr(t, start, 0);
if (val == 0)
ifflag |= (1 << level);
}
else if (lti[0].equals("#else"))
{
ifflag ^= (1 << level);
}
else if (lti[0].equals("#endif"))
{
ifflag &= ~(1 << level);
level--;
}
else if (lti[0].equals("#include"))
{
// ignore
}
else if (lti[0].equals("#define"))
{
if (lti.count() != 3)
error(pstring::sprintf("PREPRO: only simple defines allowed: %s", line.cstr()));
m_defines.add(define_t(lti[1], lti[2]));
}
else
error(pstring::sprintf("unknown directive on line %d: %s\n", i, line.cstr()));
}
else
{
//if (ifflag == 0 && level > 0)
// fprintf(stderr, "conditional: %s\n", line.cstr());
if (ifflag == 0)
ret = ret + line + "\n";
}
i++;
}
return ret;
}

181
src/emu/netlist/pparser.h Normal file
View File

@ -0,0 +1,181 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* pparser.h
*
*/
#ifndef PPARSER_H_
#define PPARSER_H_
#include "pconfig.h"
#include "nl_config.h" // FIXME
#include "nl_util.h"
class ptokenizer
{
NETLIST_PREVENT_COPYING(ptokenizer)
public:
virtual ~ptokenizer() {}
ptokenizer()
: m_line(1), m_line_ptr(NULL), m_px(NULL), m_string('"')
{}
enum token_type
{
IDENTIFIER,
NUMBER,
TOKEN,
STRING,
COMMENT,
UNKNOWN,
ENDOFFILE
};
struct token_id_t
{
public:
token_id_t() : m_id(-2) {}
token_id_t(const int id) : m_id(id) {}
int id() const { return m_id; }
private:
int m_id;
};
struct token_t
{
token_t(token_type type)
{
m_type = type;
m_id = token_id_t(-1);
m_token ="";
}
token_t(token_type type, const pstring str)
{
m_type = type;
m_id = token_id_t(-1);
m_token = str;
}
token_t(const token_id_t id, const pstring str)
{
m_type = TOKEN;
m_id = id;
m_token = str;
}
bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
bool is_type(const token_type type) const { return m_type == type; }
pstring str() const { return m_token; }
private:
token_type m_type;
token_id_t m_id;
pstring m_token;
};
int currentline_no() { return m_line; }
pstring currentline_str();
/* tokenizer stuff follows ... */
token_t get_token();
pstring get_string();
pstring get_identifier();
void require_token(const token_id_t &token_num);
void require_token(const token_t tok, const token_id_t &token_num);
token_id_t register_token(pstring token)
{
m_tokens.add(token);
return token_id_t(m_tokens.count() - 1);
}
void set_identifier_chars(pstring s) { m_identifier_chars = s; }
void set_number_chars(pstring s) { m_number_chars = s; }
void set_whitespace(pstring s) { m_whitespace = s; }
void set_comment(pstring start, pstring end, pstring line)
{
m_tok_comment_start = register_token(start);
m_tok_comment_end = register_token(end);
m_tok_line_comment = register_token(line);
m_string = '"';
}
token_t get_token_internal();
void error(const char *format, ...) ATTR_PRINTF(2,3);
protected:
void reset(const char *p) { m_px = p; m_line = 1; m_line_ptr = p; }
virtual void verror(pstring msg, int line_num, pstring line) = 0;
private:
void skipeol();
unsigned char getc();
void ungetc();
bool eof() { return *m_px == 0; }
int m_line;
const char * m_line_ptr;
const char * m_px;
/* tokenizer stuff follows ... */
pstring m_identifier_chars;
pstring m_number_chars;
plist_t<pstring> m_tokens;
pstring m_whitespace;
char m_string;
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
token_id_t m_tok_line_comment;
};
class ppreprocessor
{
NETLIST_PREVENT_COPYING(ppreprocessor)
public:
struct define_t
{
define_t() { };
define_t(const pstring &name, const pstring &replace)
: m_name(name), m_replace(replace)
{}
pstring m_name;
pstring m_replace;
};
ppreprocessor();
virtual ~ppreprocessor() {}
pstring process(const pstring &contents);
protected:
double expr(const nl_util::pstring_list &sexpr, int &start, int prio);
define_t *get_define(const pstring &name);
pstring replace_macros(const pstring &line);
virtual void error(const pstring &err)
{
fprintf(stderr, "PREPRO ERROR: %s\n", err.cstr());
}
private:
plist_t<define_t> m_defines;
nl_util::pstring_list m_expr_sep;
};
#endif /* PPARSER_H_ */

View File

@ -9,6 +9,8 @@
#include "netlist/devices/net_lib.h"
#define FAST_CLOCK (1)
NETLIST_START(pong_fast)
SOLVER(Solver, 48000)
PARAM(Solver.PARALLEL, 0) // Don't do parallel solvers
@ -22,15 +24,15 @@ NETLIST_START(pong_fast)
TTL_INPUT(low, 0)
#if 1
#if 0
/* this is the clock circuit in schematics. */
MAINCLOCK(xclk, 7159000.0*2)
TTL_74107(ic_f6a, xclk, high, high, high)
ALIAS(clk, ic_f6a.Q)
#else
#if (FAST_CLOCK)
/* abstracting this, performance increases by 60%
* No surprise, the clock is extremely expensive */
MAINCLOCK(clk, 7159000.0)
#else
/* this is the clock circuit in schematics. */
MAINCLOCK(xclk, 14318000.0) //7159000.0*2
TTL_74107(ic_f6a, xclk, high, high, high)
ALIAS(clk, ic_f6a.Q)
#endif
#else
// benchmarking ...