Got truthtable parsing working in the parser. The plib preprocessor now

defines __PLIB_PREPROCESSOR__. This can be checked in netlist code and
allows even more sharing code between compiled (embedded) netlists and
external netlists. (nw)
This commit is contained in:
couriersud 2015-05-28 01:49:52 +02:00
parent 1d99211b55
commit b67b9ff917
9 changed files with 147 additions and 16 deletions

View File

@ -156,7 +156,7 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets
break; break;
} }
} }
NL_VERBOSE_OUT(("added net with %d populated connections\n", net->m_core_terms.size())); NL_VERBOSE_OUT(("added net with %" SIZETFMT " populated connections\n", net->m_core_terms.size()));
} }
} }

View File

@ -101,7 +101,7 @@
#if (NL_VERBOSE) #if (NL_VERBOSE)
#define NL_VERBOSE_OUT(x) printf x #define NL_VERBOSE_OUT(x) printf x
#else #else
#define NL_VERBOSE_OUT(x) do { } while (0) #define NL_VERBOSE_OUT(x) do { if(0) printf x ; } while (0)
#endif #endif
//============================================================ //============================================================

View File

@ -7,6 +7,7 @@
#include "nl_parser.h" #include "nl_parser.h"
#include "nl_factory.h" #include "nl_factory.h"
#include "devices/nld_truthtable.h"
//#undef NL_VERBOSE_OUT //#undef NL_VERBOSE_OUT
//#define NL_VERBOSE_OUT(x) printf x //#define NL_VERBOSE_OUT(x) printf x
@ -33,7 +34,7 @@ bool netlist_parser::parse(const char *buf, const pstring nlname)
reset(m_buf); reset(m_buf);
set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-"); set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
set_number_chars("01234567890eE-."); //FIXME: processing of numbers set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
char ws[5]; char ws[5];
ws[0] = ' '; ws[0] = ' ';
ws[1] = 9; ws[1] = 9;
@ -54,6 +55,10 @@ bool netlist_parser::parse(const char *buf, const pstring nlname)
m_tok_SUBMODEL = register_token("SUBMODEL"); m_tok_SUBMODEL = register_token("SUBMODEL");
m_tok_NETLIST_START = register_token("NETLIST_START"); m_tok_NETLIST_START = register_token("NETLIST_START");
m_tok_NETLIST_END = register_token("NETLIST_END"); m_tok_NETLIST_END = register_token("NETLIST_END");
m_tok_TRUTHTABLE_START = register_token("TRUTHTABLE_START");
m_tok_TRUTHTABLE_END = register_token("TRUTHTABLE_END");
m_tok_TT_HEAD = register_token("TT_HEAD");
m_tok_TT_LINE = register_token("TT_LINE");
bool in_nl = false; bool in_nl = false;
@ -119,6 +124,8 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname)
net_submodel(); net_submodel();
else if (token.is(m_tok_INCLUDE)) else if (token.is(m_tok_INCLUDE))
net_include(); net_include();
else if (token.is(m_tok_TRUTHTABLE_START))
net_truthtable_start();
else if (token.is(m_tok_NETLIST_END)) else if (token.is(m_tok_NETLIST_END))
{ {
netdev_netlist_end(); netdev_netlist_end();
@ -129,6 +136,49 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname)
} }
} }
void netlist_parser::net_truthtable_start()
{
pstring name = get_identifier();
require_token(m_tok_comma);
unsigned ni = get_number_long();
require_token(m_tok_comma);
unsigned no = get_number_long();
require_token(m_tok_comma);
unsigned hs = get_number_long();
require_token(m_tok_comma);
pstring def_param = get_string();
require_token(m_tok_param_right);
netlist_base_factory_truthtable_t *ttd = nl_tt_factory_create(ni, no, hs,
name, name, "+" + def_param);
while (true)
{
token_t token = get_token();
if (token.is(m_tok_TT_HEAD))
{
require_token(m_tok_param_left);
ttd->m_desc.add(get_string());
require_token(m_tok_param_right);
}
else if (token.is(m_tok_TT_LINE))
{
require_token(m_tok_param_left);
ttd->m_desc.add(get_string());
require_token(m_tok_param_right);
}
else
{
require_token(token, m_tok_TRUTHTABLE_END);
require_token(m_tok_param_left);
require_token(m_tok_param_right);
m_setup.factory().register_device(ttd);
return;
}
}
}
void netlist_parser::netdev_netlist_start() void netlist_parser::netdev_netlist_start()
{ {
@ -198,7 +248,7 @@ void netlist_parser::net_c()
{ {
pstring t1 = get_identifier(); pstring t1 = get_identifier();
m_setup.register_link(first , t1); m_setup.register_link(first , t1);
NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", last.cstr(), t1.cstr())); NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", first.cstr(), t1.cstr()));
token_t n = get_token(); token_t n = get_token();
if (n.is(m_tok_param_right)) if (n.is(m_tok_param_right))
break; break;
@ -293,6 +343,23 @@ nl_double netlist_parser::eval_param(const token_t tok)
for (i=1; i<6;i++) for (i=1; i<6;i++)
if (tok.str().equals(macs[i])) if (tok.str().equals(macs[i]))
f = i; f = i;
#if 1
if (f>0)
{
require_token(m_tok_param_left);
ret = get_number_double();
require_token(m_tok_param_right);
}
else
{
val = tok.str();
ret = val.as_double(&e);
if (e)
error("Error with parameter ...\n");
}
return ret * facs[f];
#else
if (f>0) if (f>0)
{ {
require_token(m_tok_param_left); require_token(m_tok_param_left);
@ -308,4 +375,5 @@ nl_double netlist_parser::eval_param(const token_t tok)
if (f>0) if (f>0)
require_token(m_tok_param_right); require_token(m_tok_param_right);
return ret * facs[f]; return ret * facs[f];
#endif
} }

View File

@ -31,6 +31,7 @@ public:
void net_model(); void net_model();
void net_submodel(); void net_submodel();
void net_include(); void net_include();
void net_truthtable_start();
protected: protected:
virtual void verror(pstring msg, int line_num, pstring line); virtual void verror(pstring msg, int line_num, pstring line);
@ -49,6 +50,10 @@ private:
token_id_t m_tok_NETLIST_END; token_id_t m_tok_NETLIST_END;
token_id_t m_tok_SUBMODEL; token_id_t m_tok_SUBMODEL;
token_id_t m_tok_INCLUDE; token_id_t m_tok_INCLUDE;
token_id_t m_tok_TRUTHTABLE_START;
token_id_t m_tok_TRUTHTABLE_END;
token_id_t m_tok_TT_HEAD;
token_id_t m_tok_TT_LINE;
netlist_setup_t &m_setup; netlist_setup_t &m_setup;

View File

@ -777,7 +777,7 @@ void netlist_setup_t::start_devices()
{ {
NL_VERBOSE_OUT(("Creating dynamic logs ...\n")); NL_VERBOSE_OUT(("Creating dynamic logs ...\n"));
pstring_list_t ll(env, ":"); pstring_list_t ll(env, ":");
for (std::size_t i=0; i < ll.size(); i++) for (unsigned i=0; i < ll.size(); i++)
{ {
NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr())); NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr()));
NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr())); NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr()));

View File

@ -96,6 +96,34 @@ pstring ptokenizer::get_identifier()
return tok.str(); return tok.str();
} }
double ptokenizer::get_number_double()
{
token_t tok = get_token();
if (!tok.is_type(NUMBER))
{
error("Error: expected a number, got <%s>\n", tok.str().cstr());
}
bool err = false;
double ret = tok.str().as_double(&err);
if (err)
error("Error: expected a number, got <%s>\n", tok.str().cstr());
return ret;
}
long ptokenizer::get_number_long()
{
token_t tok = get_token();
if (!tok.is_type(NUMBER))
{
error("Error: expected a long int, got <%s>\n", tok.str().cstr());
}
bool err = false;
long ret = tok.str().as_long(&err);
if (err)
error("Error: expected a long int, got <%s>\n", tok.str().cstr());
return ret;
}
ptokenizer::token_t ptokenizer::get_token() ptokenizer::token_t ptokenizer::get_token()
{ {
while (true) while (true)
@ -135,7 +163,26 @@ ptokenizer::token_t ptokenizer::get_token_internal()
return token_t(ENDOFFILE); return token_t(ENDOFFILE);
} }
} }
if (m_identifier_chars.find(c)>=0) if (m_number_chars_start.find(c)>=0)
{
/* read number while we receive number or identifier chars
* treat it as an identifier when there are identifier chars in it
*
*/
token_type ret = NUMBER;
pstring tokstr = "";
while (true) {
if (m_identifier_chars.find(c)>=0 && m_number_chars.find(c)<0)
ret = IDENTIFIER;
else if (m_number_chars.find(c)<0)
break;
tokstr += c;
c = getc();
}
ungetc();
return token_t(ret, tokstr);
}
else if (m_identifier_chars.find(c)>=0)
{ {
/* read identifier till non identifier char */ /* read identifier till non identifier char */
pstring tokstr = ""; pstring tokstr = "";
@ -218,6 +265,8 @@ ppreprocessor::ppreprocessor()
m_expr_sep.add("=="); m_expr_sep.add("==");
m_expr_sep.add(" "); m_expr_sep.add(" ");
m_expr_sep.add("\t"); m_expr_sep.add("\t");
m_defines.add(define_t("__PLIB_PREPROCESSOR__", "1"));
} }
void ppreprocessor::error(const pstring &err) void ppreprocessor::error(const pstring &err)
@ -336,7 +385,7 @@ pstring ppreprocessor::process(const pstring &contents)
{ {
pstring line = lines[i]; pstring line = lines[i];
pstring lt = line.replace("\t"," ").trim(); pstring lt = line.replace("\t"," ").trim();
lt = replace_macros(lt); // FIXME ... revise and extend macro handling
if (lt.startsWith("#")) if (lt.startsWith("#"))
{ {
pstring_list_t lti(lt, " ", true); pstring_list_t lti(lt, " ", true);
@ -344,6 +393,7 @@ pstring ppreprocessor::process(const pstring &contents)
{ {
level++; level++;
std::size_t start = 0; std::size_t start = 0;
lt = replace_macros(lt);
pstring_list_t t = pstring_list_t::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep); pstring_list_t t = pstring_list_t::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep);
int val = expr(t, start, 0); int val = expr(t, start, 0);
if (val == 0) if (val == 0)
@ -398,9 +448,10 @@ pstring ppreprocessor::process(const pstring &contents)
{ {
//if (ifflag == 0 && level > 0) //if (ifflag == 0 && level > 0)
// fprintf(stderr, "conditional: %s\n", line.cstr()); // fprintf(stderr, "conditional: %s\n", line.cstr());
lt = replace_macros(lt);
if (ifflag == 0) if (ifflag == 0)
{ {
ret.cat(line); ret.cat(lt);
ret.cat("\n"); ret.cat("\n");
} }
} }

View File

@ -86,6 +86,8 @@ public:
token_t get_token(); token_t get_token();
pstring get_string(); pstring get_string();
pstring get_identifier(); pstring get_identifier();
double get_number_double();
long get_number_long();
void require_token(const token_id_t &token_num); void require_token(const token_id_t &token_num);
void require_token(const token_t tok, const token_id_t &token_num); void require_token(const token_t tok, const token_id_t &token_num);
@ -97,7 +99,7 @@ public:
} }
void set_identifier_chars(pstring s) { m_identifier_chars = s; } void set_identifier_chars(pstring s) { m_identifier_chars = s; }
void set_number_chars(pstring s) { m_number_chars = s; } void set_number_chars(pstring st, pstring rem) { m_number_chars_start = st; m_number_chars = rem; }
void set_whitespace(pstring s) { m_whitespace = s; } void set_whitespace(pstring s) { m_whitespace = s; }
void set_comment(pstring start, pstring end, pstring line) void set_comment(pstring start, pstring end, pstring line)
{ {
@ -129,6 +131,7 @@ private:
pstring m_identifier_chars; pstring m_identifier_chars;
pstring m_number_chars; pstring m_number_chars;
pstring m_number_chars_start;
plist_t<pstring> m_tokens; plist_t<pstring> m_tokens;
pstring m_whitespace; pstring m_whitespace;
char m_string; char m_string;

View File

@ -11,13 +11,15 @@
#define FAST_CLOCK (1) #define FAST_CLOCK (1)
#ifndef __PLIB_PREPROCESSOR__
#define TTL_7400A_NAND(_name, _A, _B) \ #define TTL_7400A_NAND(_name, _A, _B) \
NET_REGISTER_DEV_X(TTL_7400A_NAND, _name) \ NET_REGISTER_DEV_X(TTL_7400A_NAND, _name) \
NET_CONNECT(_name, A, _A) \ NET_CONNECT(_name, A, _A) \
NET_CONNECT(_name, B, _B) NET_CONNECT(_name, B, _B)
#endif
NETLIST_START(lib) NETLIST_START(lib)
TRUTHTABLE_START(TTL_7400A_NAND, 2, 1, 0, "+A,B") TRUTHTABLE_START(TTL_7400A_NAND, 2, 1, 0, "A,B")
TT_HEAD(" A , B | Q ") TT_HEAD(" A , B | Q ")
TT_LINE(" 0 , X | 1 |22") TT_LINE(" 0 , X | 1 |22")
TT_LINE(" X , 0 | 1 |22") TT_LINE(" X , 0 | 1 |22")
@ -398,7 +400,7 @@ NETLIST_START(pong_fast)
NET_C(ic_b9_RPRE.2, ic_b9.CONT) NET_C(ic_b9_RPRE.2, ic_b9.CONT)
RES(ic_b9_R, RES_K(81)) // Adjustment pot RES(ic_b9_R, RES_K(81)) // Adjustment pot
CAP(ic_b9_C, CAP_U(.1)) CAP(ic_b9_C, CAP_U(0.1))
DIODE(ic_b9_D, "1N914") DIODE(ic_b9_D, "1N914")
NE555(ic_b9) NE555(ic_b9)
@ -438,7 +440,7 @@ NETLIST_START(pong_fast)
NET_C(ic_a9_RPRE.2, ic_a9.CONT) NET_C(ic_a9_RPRE.2, ic_a9.CONT)
RES(ic_a9_R, RES_K(81)) // Adjustment pot RES(ic_a9_R, RES_K(81)) // Adjustment pot
CAP(ic_a9_C, CAP_U(.1)) CAP(ic_a9_C, CAP_U(0.1))
DIODE(ic_a9_D, "1N914") DIODE(ic_a9_D, "1N914")
NE555(ic_a9) NE555(ic_a9)

View File

@ -97,7 +97,8 @@ class tool_options_t : public poptions
public: public:
tool_options_t() : tool_options_t() :
poptions(), poptions(),
opt_ttr ("t", "time_to_run", 1.0, "time to run the emulation (seconds)", this), opt_ttr ("t", "time_to_run", 1.0, "time to run the emulation (seconds)", this),
opt_name("n", "name", "", "netlist in file to run; default is first one", this),
opt_logs("l", "logs", "", "colon separated list of terminals to log", this), opt_logs("l", "logs", "", "colon separated list of terminals to log", this),
opt_file("f", "file", "-", "file to process (default is stdin)", this), opt_file("f", "file", "-", "file to process (default is stdin)", this),
opt_cmd ("c", "cmd", "run", "run|convert|listdevices", this), opt_cmd ("c", "cmd", "run", "run|convert|listdevices", this),
@ -106,6 +107,7 @@ public:
{} {}
poption_double opt_ttr; poption_double opt_ttr;
poption_str opt_name;
poption_str opt_logs; poption_str opt_logs;
poption_str opt_file; poption_str opt_file;
poption_str opt_cmd; poption_str opt_cmd;
@ -183,14 +185,14 @@ public:
m_setup->init(); m_setup->init();
} }
void read_netlist(const char *buffer) void read_netlist(const char *buffer, pstring name)
{ {
// read the netlist ... // read the netlist ...
netlist_sources_t sources; netlist_sources_t sources;
sources.add(netlist_source_t(buffer)); sources.add(netlist_source_t(buffer));
sources.parse(*m_setup,""); sources.parse(*m_setup, name);
//m_setup->parse(buffer); //m_setup->parse(buffer);
log_setup(); log_setup();
@ -266,7 +268,7 @@ static void run(tool_options_t &opts)
nt.init(); nt.init();
nt.m_logs = opts.opt_logs(); nt.m_logs = opts.opt_logs();
nt.m_verbose = opts.opt_verb(); nt.m_verbose = opts.opt_verb();
nt.read_netlist(filetobuf(opts.opt_file())); nt.read_netlist(filetobuf(opts.opt_file()), opts.opt_name());
double ttr = opts.opt_ttr(); double ttr = opts.opt_ttr();
printf("startup time ==> %5.3f\n", (double) (osd_ticks() - t) / (double) osd_ticks_per_second() ); printf("startup time ==> %5.3f\n", (double) (osd_ticks() - t) / (double) osd_ticks_per_second() );