netlist: improve parsing performance

* preparational work for easier device addition.
This commit is contained in:
couriersud 2020-08-10 21:13:27 +02:00
parent 4985e1e9b9
commit 167da15753
9 changed files with 132 additions and 21 deletions

View File

@ -333,6 +333,25 @@ namespace netlist
pstring m_setup_func_name;
};
class source_token_t : public source_netlist_t
{
public:
source_token_t(const pstring &name, const parser_t::token_store &store)
: m_store(store)
, m_name(name)
{
}
bool parse(nlparse_t &setup, const pstring &name) override;
protected:
stream_ptr stream(const pstring &name) override;
private:
parser_t::token_store m_store;
pstring m_name;
};
} // namespace netlist

View File

@ -29,11 +29,6 @@
#endif
NETLIST_EXTERNAL(base_lib)
NETLIST_EXTERNAL(cd4xxx_lib)
NETLIST_EXTERNAL(opamp_lib)
NETLIST_EXTERNAL(otheric_lib)
NETLIST_EXTERNAL(ttl74xx_lib)
NETLIST_EXTERNAL(roms_lib)
#if NL_AUTO_DEVICES
#include "nld_devinc.h"

View File

@ -2,6 +2,16 @@
// copyright-holders:Couriersud
#include "netlist/devices/net_lib.h"
/* ----------------------------------------------------------------------------
* External declarations
* ---------------------------------------------------------------------------*/
NETLIST_EXTERNAL(cd4xxx_lib)
NETLIST_EXTERNAL(opamp_lib)
NETLIST_EXTERNAL(otheric_lib)
NETLIST_EXTERNAL(ttl74xx_lib)
NETLIST_EXTERNAL(roms_lib)
/* ----------------------------------------------------------------------------
* Diode Models
* ---------------------------------------------------------------------------*/
@ -107,11 +117,11 @@ NETLIST_START(base_lib)
LOCAL_SOURCE(mosfet_models)
LOCAL_SOURCE(family_models)
LOCAL_SOURCE(ttl74xx_lib)
LOCAL_SOURCE(cd4xxx_lib)
LOCAL_SOURCE(opamp_lib)
LOCAL_SOURCE(otheric_lib)
LOCAL_SOURCE(roms_lib)
EXTERNAL_SOURCE(ttl74xx_lib)
EXTERNAL_SOURCE(cd4xxx_lib)
EXTERNAL_SOURCE(opamp_lib)
EXTERNAL_SOURCE(otheric_lib)
EXTERNAL_SOURCE(roms_lib)
INCLUDE(diode_models)
INCLUDE(bjt_models)

View File

@ -144,17 +144,18 @@ namespace netlist
NETLIST_NAME(base_lib)(m_setup->parser());
#else
// FIXME: This is very slow - need optimized parsing scanning
#if 0
m_setup->parser().register_source<source_pattern_t>("src/lib/netlist/macro/nlm_{}.cpp");
#if 1
m_setup->parser().register_source<source_pattern_t>("src/lib/netlist/macro/nlm_{1}.cpp");
m_setup->parser().include("base_lib");
#else
pstring dir = "src/lib/netlist/macro/";
//m_setup->parser().register_source<source_pattern_t>("src/lib/netlist/macro/nlm_{}.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_base.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_opamp.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_roms.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_cd4xxx.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_other.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_ttl74xx.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_base_lib.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_opamp_lib.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_roms_lib.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_cd4xxx_lib.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_otheric_lib.cpp");
m_setup->parser().register_source<source_file_t>(dir + "nlm_ttl74xx_lib.cpp");
m_setup->parser().include("base_lib");
#endif
#endif

View File

@ -43,6 +43,7 @@ namespace netlist
PERRMSGV(MF_UNEXPECTED_NETLIST_END, 0, "Unexpected NETLIST_END")
PERRMSGV(MF_UNEXPECTED_END_OF_FILE, 0, "Unexpected end of file, missing NETLIST_END")
PERRMSGV(MF_UNEXPECTED_NETLIST_START, 0, "Unexpected NETLIST_START")
PERRMSGV(MF_UNEXPECTED_NETLIST_EXTERNAL, 0, "Unexpected NETLIST_EXTERNAL within a netlist")
PERRMSGV(MF_EXPECTED_NETLIST_START_1, 1, "Expected NETLIST_START but got {1}")
PERRMSGV(MF_EXPECTED_IDENTIFIER_GOT_1, 1, "Expected an identifier, but got {1}")
PERRMSGV(MF_EXPECTED_COMMA_OR_RP_1, 1, "Expected comma or right parenthesis but found <{1}>")

View File

@ -47,6 +47,8 @@ parser_t::parser_t(nlparse_t &setup)
m_tok_SUBMODEL = m_tokenizer.register_token("SUBMODEL");
m_tok_NETLIST_START = m_tokenizer.register_token("NETLIST_START");
m_tok_NETLIST_END = m_tokenizer.register_token("NETLIST_END");
m_tok_NETLIST_EXTERNAL = m_tokenizer.register_token("NETLIST_EXTERNAL");
m_tok_EXTERNAL_SOURCE = m_tokenizer.register_token("EXTERNAL_SOURCE");
m_tok_TRUTHTABLE_START = m_tokenizer.register_token("TRUTHTABLE_START");
m_tok_TRUTHTABLE_END = m_tokenizer.register_token("TRUTHTABLE_END");
m_tok_TT_HEAD = m_tokenizer.register_token("TT_HEAD");
@ -75,7 +77,7 @@ void parser_t::parse_tokens(plib::psource_t::stream_ptr &&strm, token_store &tok
m_tokenizer.append_to_store(&u8reader, tokstor);
}
bool parser_t::parse(token_store &tokstor, const pstring &nlname)
bool parser_t::parse(const token_store &tokstor, const pstring &nlname)
{
set_token_source(&tokstor);
@ -134,6 +136,14 @@ bool parser_t::parse(token_store &tokstor, const pstring &nlname)
m_cur_local->push_back(token_t(m_tok_paren_right));
in_nl = true;
}
else if (token.is(m_tok_NETLIST_EXTERNAL))
{
if (in_nl)
error (MF_UNEXPECTED_NETLIST_EXTERNAL());
require_token(m_tok_paren_left);
token_t name = get_token();
require_token(m_tok_paren_right);
}
else if (!in_nl)
{
if (!token.is(m_tok_static))
@ -179,13 +189,17 @@ void parser_t::parse_netlist(const pstring &nlname)
net_include();
else if (token.is(m_tok_LOCAL_SOURCE))
net_local_source();
else if (token.is(m_tok_EXTERNAL_SOURCE))
net_external_source();
else if (token.is(m_tok_TRUTHTABLE_START))
net_truthtable_start(nlname);
else if (token.is(m_tok_LOCAL_LIB_ENTRY))
{
require_token(m_tok_paren_left);
pstring name(get_identifier());
register_local_as_source(name);
// FIXME: Need to pass in parameter definition FIXME: get line number right
m_setup.register_lib_entry(get_identifier(), "", plib::source_location("parser: " + nlname, 1));
m_setup.register_lib_entry(name, "", plib::source_location("parser: " + nlname, 1));
require_token(m_tok_paren_right);
}
else if (token.is(m_tok_NET_REGISTER_DEV))
@ -315,6 +329,28 @@ void parser_t::net_include()
}
void parser_t::net_local_source()
{
// This directive is only for hardcoded netlists. Ignore it here.
require_token(m_tok_paren_left);
pstring name(get_identifier());
require_token(m_tok_paren_right);
register_local_as_source(name);
}
void parser_t::register_local_as_source(const pstring &name)
{
auto p = m_local.find(name);
if (p != m_local.end())
{
printf("found %s\n", name.c_str());
m_setup.register_source<source_token_t>(name, p->second);
}
else
printf("argh %s\n", name.c_str());
}
void parser_t::net_external_source()
{
// This directive is only for hardcoded netlists. Ignore it here.
require_token(m_tok_paren_left);

View File

@ -26,7 +26,7 @@ namespace netlist
parser_t(nlparse_t &setup);
bool parse(plib::psource_t::stream_ptr &&strm, const pstring &nlname);
bool parse(token_store &tokstor, const pstring &nlname);
bool parse(const token_store &tokstor, const pstring &nlname);
void parse_tokens(plib::psource_t::stream_ptr &&strm, token_store &tokstor);
protected:
@ -44,12 +44,16 @@ namespace netlist
void net_submodel();
void net_include();
void net_local_source();
void net_external_source();
void net_register_dev();
void net_truthtable_start(const pstring &nlname);
void verror(const pstring &msg) override;
private:
void register_local_as_source(const pstring &name);
pstring stringify_expression(token_t &tok);
token_id_t m_tok_paren_left;
token_id_t m_tok_paren_right;
token_id_t m_tok_comma;
@ -65,8 +69,10 @@ namespace netlist
token_id_t m_tok_NET_REGISTER_DEV;
token_id_t m_tok_NETLIST_START;
token_id_t m_tok_NETLIST_END;
token_id_t m_tok_NETLIST_EXTERNAL;
token_id_t m_tok_SUBMODEL;
token_id_t m_tok_INCLUDE;
token_id_t m_tok_EXTERNAL_SOURCE;
token_id_t m_tok_LOCAL_SOURCE;
token_id_t m_tok_LOCAL_LIB_ENTRY;
token_id_t m_tok_TRUTHTABLE_START;

View File

@ -352,8 +352,15 @@ namespace netlist
return false;
}
bool nlparse_t::parse_tokens(const parser_t::token_store &tokens, const pstring &name)
{
parser_t parser(*this);
return parser.parse(tokens, name);
}
bool nlparse_t::parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name)
{
#if 0
auto key = istrm.filename();
if (m_source_cache.find(key) != m_source_cache.end())
@ -374,6 +381,18 @@ namespace netlist
parser.parse_tokens(plib::psource_t::stream_ptr(std::move(abc), key), st);
return parser.parse(st, name);
}
#else
plib::ppreprocessor y(m_includes, &m_defines);
y.process(std::move(istrm), istrm.filename());
auto abc = std::make_unique<std::stringstream>();
plib::copystream(*abc, y);
parser_t::token_store st;
parser_t parser(*this);
parser.parse_tokens(plib::psource_t::stream_ptr(std::move(abc), istrm.filename()), st);
return parser.parse(st, name);
#endif
}
void nlparse_t::add_define(const pstring &defstr)
@ -1712,8 +1731,10 @@ source_file_t::stream_ptr source_pattern_t::stream(const pstring &name)
{
pstring filename = plib::pfmt(m_pattern)(name);
auto f = std::make_unique<plib::ifstream>(plib::filesystem::u8path(filename));
printf("checking <%s> %s\n", name.c_str(), filename.c_str());
if (f->is_open())
{
printf("found\n");
return stream_ptr(std::move(f), filename);
}
else
@ -1738,5 +1759,23 @@ source_proc_t::stream_ptr source_proc_t::stream(const pstring &name)
return stream_ptr();
}
bool source_token_t::parse(nlparse_t &setup, const pstring &name)
{
if (name == m_name)
{
auto ret = setup.parse_tokens(m_store, name);
printf("parsed tokens: %s %d\n", name.c_str(), (int) ret);
return ret;
}
return false;
}
source_proc_t::stream_ptr source_token_t::stream(const pstring &name)
{
plib::unused_var(name);
return stream_ptr();
}
} // namespace netlist

View File

@ -83,6 +83,9 @@ void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
#define LOCAL_SOURCE(name) \
setup.register_source_proc(# name, &NETLIST_NAME(name));
#define EXTERNAL_SOURCE(name) \
setup.register_source_proc(# name, &NETLIST_NAME(name));
// FIXME: Need to pass in parameter definition
#define LOCAL_LIB_ENTRY_1(name) \
LOCAL_SOURCE(name) \
@ -230,6 +233,7 @@ namespace netlist
// FIXME: used by source_t - need a different approach at some time
bool parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name);
bool parse_tokens(const parser_t::token_store &tokens, const pstring &name);
template <typename S, typename... Args>
void add_include(Args&&... args)