From 167da15753419aceb58cc3dea4abc042f9be0185 Mon Sep 17 00:00:00 2001 From: couriersud Date: Mon, 10 Aug 2020 21:13:27 +0200 Subject: [PATCH] netlist: improve parsing performance * preparational work for easier device addition. --- src/lib/netlist/core/setup.h | 19 ++++++++++++ src/lib/netlist/devices/net_lib.h | 5 ---- src/lib/netlist/macro/nlm_base_lib.cpp | 20 +++++++++---- src/lib/netlist/nl_base.cpp | 17 +++++------ src/lib/netlist/nl_errstr.h | 1 + src/lib/netlist/nl_parser.cpp | 40 ++++++++++++++++++++++++-- src/lib/netlist/nl_parser.h | 8 +++++- src/lib/netlist/nl_setup.cpp | 39 +++++++++++++++++++++++++ src/lib/netlist/nl_setup.h | 4 +++ 9 files changed, 132 insertions(+), 21 deletions(-) diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h index 5048c2ae765..20fc9cb3678 100644 --- a/src/lib/netlist/core/setup.h +++ b/src/lib/netlist/core/setup.h @@ -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 diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h index a5779cf162e..a891b8f1b0b 100644 --- a/src/lib/netlist/devices/net_lib.h +++ b/src/lib/netlist/devices/net_lib.h @@ -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" diff --git a/src/lib/netlist/macro/nlm_base_lib.cpp b/src/lib/netlist/macro/nlm_base_lib.cpp index 04676fc5338..51969930564 100644 --- a/src/lib/netlist/macro/nlm_base_lib.cpp +++ b/src/lib/netlist/macro/nlm_base_lib.cpp @@ -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) diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 532a3f98f47..c8684baccbf 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -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("src/lib/netlist/macro/nlm_{}.cpp"); +#if 1 + m_setup->parser().register_source("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("src/lib/netlist/macro/nlm_{}.cpp"); - m_setup->parser().register_source(dir + "nlm_base.cpp"); - m_setup->parser().register_source(dir + "nlm_opamp.cpp"); - m_setup->parser().register_source(dir + "nlm_roms.cpp"); - m_setup->parser().register_source(dir + "nlm_cd4xxx.cpp"); - m_setup->parser().register_source(dir + "nlm_other.cpp"); - m_setup->parser().register_source(dir + "nlm_ttl74xx.cpp"); + m_setup->parser().register_source(dir + "nlm_base_lib.cpp"); + m_setup->parser().register_source(dir + "nlm_opamp_lib.cpp"); + m_setup->parser().register_source(dir + "nlm_roms_lib.cpp"); + m_setup->parser().register_source(dir + "nlm_cd4xxx_lib.cpp"); + m_setup->parser().register_source(dir + "nlm_otheric_lib.cpp"); + m_setup->parser().register_source(dir + "nlm_ttl74xx_lib.cpp"); m_setup->parser().include("base_lib"); #endif #endif diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h index 67510fbf453..c0097cadb15 100644 --- a/src/lib/netlist/nl_errstr.h +++ b/src/lib/netlist/nl_errstr.h @@ -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}>") diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 8edecb84a3a..f86b3d129eb 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -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(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); diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h index c552663af6a..5e00c7c8470 100644 --- a/src/lib/netlist/nl_parser.h +++ b/src/lib/netlist/nl_parser.h @@ -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; diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index aed7a509d5e..32ccfb5725f 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -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(); + 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::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 diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 31fad70a746..964cb0d19d2 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -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 void add_include(Args&&... args)