summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/nl_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/nl_parser.cpp')
-rw-r--r--src/lib/netlist/nl_parser.cpp857
1 files changed, 504 insertions, 353 deletions
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index dfae907fe96..4d4638bea21 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -1,437 +1,588 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * nl_parser.c
- *
- */
#include "nl_parser.h"
-#include "nl_base.h"
+
#include "nl_errstr.h"
#include "nl_factory.h"
+#include "nl_setup.h"
namespace netlist
{
-// ----------------------------------------------------------------------------------------
-// A netlist parser
-// ----------------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
+ // A netlist parser
+ // -------------------------------------------------------------------------
-void parser_t::verror(const pstring &msg, int line_num, const pstring &line)
-{
- m_setup.log().fatal("line {1}: error: {2}\n\t\t{3}\n", line_num,
- msg, line);
+ void parser_t::verror(const pstring &msg)
+ {
+ m_setup.log().fatal("{1}", msg);
+ throw nl_exception(plib::pfmt("{1}")(msg));
+ }
- //throw error;
-}
+ parser_t::parser_t(nlparse_t &setup)
+ : m_setup(setup)
+ , m_cur_local(nullptr)
+ {
+ m_tokenizer
+ .identifier_chars(
+ "abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-$@")
+ .number_chars(".0123456789", "0123456789eE-.") // FIXME: processing
+ // of numbers
+ .whitespace(pstring("") + ' ' + static_cast<char>(9)
+ + static_cast<char>(10) + static_cast<char>(13))
+ .comment("/*", "*/", "//");
+ m_tok_paren_left = m_tokenizer.register_token("(");
+ m_tok_paren_right = m_tokenizer.register_token(")");
+ m_tok_brace_left = m_tokenizer.register_token("{");
+ m_tok_brace_right = m_tokenizer.register_token("}");
+ m_tok_comma = m_tokenizer.register_token(",");
+
+ m_tok_static = m_tokenizer.register_token("static");
+ m_tok_ALIAS = m_tokenizer.register_token("ALIAS");
+ m_tok_DIPPINS = m_tokenizer.register_token("DIPPINS");
+ m_tok_NET_C = m_tokenizer.register_token("NET_C");
+ m_tok_FRONTIER = m_tokenizer.register_token("OPTIMIZE_FRONTIER");
+ m_tok_PARAM = m_tokenizer.register_token("PARAM");
+ m_tok_DEFPARAM = m_tokenizer.register_token("DEFPARAM");
+ m_tok_HINT = m_tokenizer.register_token("HINT");
+ m_tok_NET_MODEL = m_tokenizer.register_token("NET_MODEL");
+ m_tok_NET_REGISTER_DEV = m_tokenizer.register_token("NET_REGISTER_DEV");
+ m_tok_INCLUDE = m_tokenizer.register_token("INCLUDE");
+ m_tok_LOCAL_SOURCE = m_tokenizer.register_token("LOCAL_SOURCE");
+ m_tok_LOCAL_LIB_ENTRY = m_tokenizer.register_token("LOCAL_LIB_ENTRY");
+ m_tok_EXTERNAL_LIB_ENTRY = m_tokenizer.register_token(
+ "EXTERNAL_LIB_ENTRY");
+ m_tok_SUBMODEL = m_tokenizer.register_token("SUBMODEL");
+ m_tok_NETLIST_START = m_tokenizer.register_token("NETLIST_START");
+ m_tok_NETLIST_EXTERNAL = m_tokenizer.register_token("NETLIST_EXTERNAL");
+ m_tok_EXTERNAL_SOURCE = m_tokenizer.register_token("EXTERNAL_SOURCE");
+ m_tok_TRUTH_TABLE = m_tokenizer.register_token("TRUTH_TABLE");
+ m_tok_TRUTHTABLE_ENTRY = m_tokenizer.register_token("TRUTHTABLE_ENTRY");
+ m_tok_TT_HEAD = m_tokenizer.register_token("TT_HEAD");
+ m_tok_TT_LINE = m_tokenizer.register_token("TT_LINE");
+ m_tok_TT_FAMILY = m_tokenizer.register_token("TT_FAMILY");
+
+ m_tokenizer.register_token("RES_R");
+ m_tokenizer.register_token("RES_K");
+ m_tokenizer.register_token("RES_M");
+ m_tokenizer.register_token("CAP_U");
+ m_tokenizer.register_token("CAP_N");
+ m_tokenizer.register_token("CAP_P");
+ }
-bool parser_t::parse(const pstring &nlname)
-{
- this->identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-")
- .number_chars(".0123456789", "0123456789eE-.") //FIXME: processing of numbers
- //set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
- .whitespace(pstring("") + ' ' + static_cast<char>(9) + static_cast<char>(10) + static_cast<char>(13))
- .comment("/*", "*/", "//");
- m_tok_param_left = register_token("(");
- m_tok_param_right = register_token(")");
- m_tok_comma = register_token(",");
-
- m_tok_ALIAS = register_token("ALIAS");
- m_tok_DIPPINS = register_token("DIPPINS");
- m_tok_NET_C = register_token("NET_C");
- m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
- m_tok_PARAM = register_token("PARAM");
- m_tok_HINT = register_token("HINT");
- m_tok_NET_MODEL = register_token("NET_MODEL");
- m_tok_INCLUDE = register_token("INCLUDE");
- m_tok_LOCAL_SOURCE = register_token("LOCAL_SOURCE");
- m_tok_LOCAL_LIB_ENTRY = register_token("LOCAL_LIB_ENTRY");
- m_tok_SUBMODEL = register_token("SUBMODEL");
- m_tok_NETLIST_START = register_token("NETLIST_START");
- 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");
- m_tok_TT_FAMILY = register_token("TT_FAMILY");
-
- bool in_nl = false;
-
- while (true)
+ bool parser_t::parse(plib::istream_uptr &&strm, const pstring &nlname)
{
- token_t token = get_token();
- if (token.is_type(ENDOFFILE))
- {
- return false;
- }
+ token_store_t tokstor;
+ parse_tokens(std::move(strm), tokstor);
+ return parse(tokstor, nlname);
+ }
+
+ void
+ parser_t::parse_tokens(plib::istream_uptr &&strm, token_store_t &tokstor)
+ {
+ plib::putf8_reader u8reader(strm.release_stream());
+ m_tokenizer.append_to_store(&u8reader, tokstor);
+ }
- if (token.is(m_tok_NETLIST_END))
+ bool parser_t::parse(const token_store_t &store, const pstring &nlname)
+ {
+ set_token_source(&store);
+
+ bool in_nl = false;
+
+ while (true)
{
- require_token(m_tok_param_left);
- if (!in_nl)
- error (MF_UNEXPECTED_NETLIST_END());
- else
+ // FIXME: line numbers in cached local netlists are wrong
+ // need to process raw tokens here.
+ token_t token = get_token_raw();
+ if (token.is_type(token_type::ENDOFFILE))
{
- in_nl = false;
+ return false;
}
- require_token(m_tok_param_right);
- }
- else if (token.is(m_tok_NETLIST_START))
- {
- if (in_nl)
- error (MF_UNEXPECTED_NETLIST_START());
- require_token(m_tok_param_left);
- token_t name = get_token();
- require_token(m_tok_param_right);
- if (name.str() == nlname || nlname == "")
+
+ if (token.is(m_tok_brace_right)) // Netlist ended?
+ {
+ if (!in_nl)
+ error(MF_PARSER_UNEXPECTED_1(token.str()));
+ else
+ in_nl = false;
+ m_cur_local->push_back(token);
+ }
+ else if (token.is(m_tok_NETLIST_START)
+ || token.is(m_tok_TRUTH_TABLE))
{
- parse_netlist(name.str());
- return true;
- } else
+ if (in_nl)
+ error(MF_PARSER_UNEXPECTED_1(token.str()));
+ require_token(m_tok_paren_left);
+ token_t name = get_token();
+ if (token.is(m_tok_NETLIST_START)
+ && (name.str() == nlname || nlname.empty()))
+ {
+ parse_netlist();
+ return true;
+ }
+ if (token.is(m_tok_TRUTH_TABLE))
+ {
+ if (name.str() == nlname)
+ {
+ net_truth_table_start(nlname);
+ return true;
+ }
+ }
+
+ // create a new cached local store
+ m_local.emplace(name.str(), token_store_t());
+ m_cur_local = &m_local[name.str()];
+ auto sl = location();
+ auto li = plib::pfmt("# {1} \"{2}\"")(sl.line(),
+ sl.file_name());
+
+ m_cur_local->push_back(token_t(token_type::LINEMARKER, li));
+ m_cur_local->push_back(token);
+ m_cur_local->push_back(token_t(m_tok_paren_left));
+ m_cur_local->push_back(name);
+ // m_cur_local->push_back(token_t(m_tok_paren_right));
in_nl = true;
+ }
+ else if (token.is(m_tok_brace_left))
+ {
+ // FIXME - do nothing for now
+ if (!in_nl)
+ printf("FIXME\n");
+ else
+ m_cur_local->push_back(token);
+ }
+ // FIXME: do we really need this going forward ? there should be no
+ // need
+ // for NETLIST_EXTERNAL in netlist files
+ 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)
+ && !token.is_type(token_type::SOURCELINE)
+ && !token.is_type(token_type::LINEMARKER))
+ error(MF_EXPECTED_NETLIST_START_1(token.str()));
+ }
+ else
+ {
+ m_cur_local->push_back(token);
+ }
}
}
-}
-void parser_t::parse_netlist(const pstring &nlname)
-{
- while (true)
+ void parser_t::parse_netlist()
{
- token_t token = get_token();
-
- if (token.is_type(ENDOFFILE))
- return;
-
- require_token(m_tok_param_left);
- m_setup.log().debug("Parser: Device: {1}\n", token.str());
-
- if (token.is(m_tok_ALIAS))
- net_alias();
- else if (token.is(m_tok_DIPPINS))
- dippins();
- else if (token.is(m_tok_NET_C))
- net_c();
- else if (token.is(m_tok_FRONTIER))
- frontier();
- else if (token.is(m_tok_PARAM))
- netdev_param();
- else if (token.is(m_tok_HINT))
- netdev_hint();
- else if (token.is(m_tok_NET_MODEL))
- net_model();
- else if (token.is(m_tok_SUBMODEL))
- net_submodel();
- else if (token.is(m_tok_INCLUDE))
- net_include();
- else if (token.is(m_tok_LOCAL_SOURCE))
- net_local_source();
- else if (token.is(m_tok_TRUTHTABLE_START))
- net_truthtable_start(nlname);
- else if (token.is(m_tok_LOCAL_LIB_ENTRY))
- {
- m_setup.register_lib_entry(get_identifier(), "parser: " + nlname);
- require_token(m_tok_param_right);
- }
- else if (token.is(m_tok_NETLIST_END))
+ require_token(m_tok_paren_right);
+ require_token(m_tok_brace_left);
+
+ while (true)
{
- netdev_netlist_end();
- return;
+ token_t token = get_token();
+
+ if (token.is_type(token_type::ENDOFFILE))
+ error(MF_UNEXPECTED_END_OF_FILE());
+
+ m_setup.log().debug("Parser: Device: {1}\n", token.str());
+
+ if (token.is(m_tok_ALIAS))
+ net_alias();
+ else if (token.is(m_tok_DIPPINS))
+ dip_pins();
+ else if (token.is(m_tok_NET_C))
+ net_c();
+ else if (token.is(m_tok_FRONTIER))
+ frontier();
+ else if (token.is(m_tok_PARAM))
+ netdev_param();
+ else if (token.is(m_tok_DEFPARAM))
+ netdev_default_param();
+ else if (token.is(m_tok_HINT))
+ netdev_hint();
+ else if (token.is(m_tok_NET_MODEL))
+ net_model();
+ else if (token.is(m_tok_SUBMODEL))
+ net_sub_model();
+ else if (token.is(m_tok_INCLUDE))
+ 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_LOCAL_LIB_ENTRY))
+ net_lib_entry(true);
+ else if (token.is(m_tok_EXTERNAL_LIB_ENTRY))
+ net_lib_entry(false);
+ else if (token.is(m_tok_TRUTHTABLE_ENTRY))
+ {
+ require_token(m_tok_paren_left);
+ pstring name(get_identifier());
+ register_local_as_source(name);
+ m_setup.include(name);
+ require_token(m_tok_paren_right);
+ }
+ else if (token.is(m_tok_NET_REGISTER_DEV))
+ net_register_dev();
+ else if (token.is(m_tok_brace_right))
+ return;
+ else if (!token.is_type(token_type::IDENTIFIER))
+ error(MF_EXPECTED_IDENTIFIER_GOT_1(token.str()));
+ else
+ device(token.str());
}
- else
- device(token.str());
}
-}
-void parser_t::net_truthtable_start(const pstring &nlname)
-{
- pstring name = get_identifier();
- require_token(m_tok_comma);
- long ni = get_number_long();
- require_token(m_tok_comma);
- long no = get_number_long();
- require_token(m_tok_comma);
- pstring def_param = get_string();
- require_token(m_tok_param_right);
-
- netlist::tt_desc desc;
- desc.classname = name;
- desc.name = name;
- desc.ni = static_cast<unsigned long>(ni);
- desc.no = static_cast<unsigned long>(no);
- desc.def_param = "+" + def_param;
- desc.family = "";
-
- while (true)
+ void parser_t::net_lib_entry(bool is_local)
{
- token_t token = get_token();
+ require_token(m_tok_paren_left);
+ pstring name(get_identifier());
+
+ if (is_local)
+ register_local_as_source(name);
+ else if (m_local.find(name) != m_local.end())
+ error(MF_EXTERNAL_SOURCE_IS_LOCAL_1(name));
+
+ // FIXME: Need to pass in parameter definition FIXME: get line number
+ // right
+ m_setup.register_lib_entry(name, "", location());
+ require_token(m_tok_paren_right);
+ }
- if (token.is(m_tok_TT_HEAD))
- {
- require_token(m_tok_param_left);
- desc.desc.push_back(get_string());
- require_token(m_tok_param_right);
- }
- else if (token.is(m_tok_TT_LINE))
- {
- require_token(m_tok_param_left);
- desc.desc.push_back(get_string());
- require_token(m_tok_param_right);
- }
- else if (token.is(m_tok_TT_FAMILY))
- {
- require_token(m_tok_param_left);
- desc.family = get_string();
- require_token(m_tok_param_right);
- }
- else
+ void parser_t::net_truth_table_start(const pstring &nlname)
+ {
+ bool head_found(false);
+
+ // parse remaining parameters
+ require_token(m_tok_comma);
+ long ni = get_number_long();
+ require_token(m_tok_comma);
+ long no = get_number_long();
+ require_token(m_tok_comma);
+ pstring def_param = get_string();
+ require_token(m_tok_paren_right);
+ require_token(m_tok_brace_left);
+
+ netlist::tt_desc desc;
+ desc.name = nlname;
+ desc.ni = gsl::narrow<unsigned long>(ni);
+ desc.no = gsl::narrow<unsigned long>(no);
+ desc.family = "";
+
+ while (true)
{
- require_token(token, m_tok_TRUTHTABLE_END);
- require_token(m_tok_param_left);
- require_token(m_tok_param_right);
- m_setup.tt_factory_create(desc, nlname);
- return;
+ token_t token = get_token();
+
+ if (token.is(m_tok_TT_HEAD))
+ {
+ require_token(m_tok_paren_left);
+ desc.desc.push_back(get_string());
+ require_token(m_tok_paren_right);
+ head_found = true;
+ }
+ else if (token.is(m_tok_TT_LINE))
+ {
+ if (!head_found)
+ error(MF_TT_LINE_WITHOUT_HEAD());
+ require_token(m_tok_paren_left);
+ desc.desc.push_back(get_string());
+ require_token(m_tok_paren_right);
+ }
+ else if (token.is(m_tok_TT_FAMILY))
+ {
+ require_token(m_tok_paren_left);
+ desc.family = get_string();
+ require_token(m_tok_paren_right);
+ }
+ else
+ {
+ require_token(token, m_tok_brace_right);
+ // FIXME: proper location
+ m_setup.truth_table_create(desc, def_param, location());
+ return;
+ }
}
}
-}
+ void parser_t::net_model()
+ {
+ require_token(m_tok_paren_left);
+ pstring model = get_string();
+ m_setup.register_model(model);
+ require_token(m_tok_paren_right);
+ }
-void parser_t::netdev_netlist_start()
-{
- // don't do much
- token_t name = get_token();
- require_token(m_tok_param_right);
-}
+ void parser_t::net_sub_model()
+ {
+ require_token(m_tok_paren_left);
+ pstring model(get_identifier());
+ require_token(m_tok_comma);
+ pstring name = get_identifier();
+ require_token(m_tok_paren_right);
+
+ m_setup.namespace_push(name);
+ m_setup.include(model);
+ m_setup.namespace_pop();
+ }
-void parser_t::netdev_netlist_end()
-{
- // don't do much
- require_token(m_tok_param_right);
-}
+ void parser_t::frontier()
+ {
+ require_token(m_tok_paren_left);
+ // don't do much
+ pstring attach_at = get_identifier();
+ require_token(m_tok_comma);
+ auto tok = get_token();
+ auto r_IN = stringify_expression(tok);
+ require_token(tok, m_tok_comma);
+ tok = get_token();
+ auto r_OUT = stringify_expression(tok);
+ require_token(tok, m_tok_paren_right);
+
+ m_setup.register_frontier(attach_at, r_IN, r_OUT);
+ }
-void parser_t::net_model()
-{
- // don't do much
- pstring model = get_string();
- m_setup.register_model(model);
- require_token(m_tok_param_right);
-}
+ void parser_t::net_include()
+ {
+ require_token(m_tok_paren_left);
+ pstring name(get_identifier());
+ require_token(m_tok_paren_right);
-void parser_t::net_submodel()
-{
- // don't do much
- pstring model = get_identifier();
- require_token(m_tok_comma);
- pstring name = get_identifier();
- require_token(m_tok_param_right);
-
- m_setup.namespace_push(name);
- m_setup.include(model);
- m_setup.namespace_pop();
-}
-
-void parser_t::frontier()
-{
- // don't do much
- pstring attachat = get_identifier();
- require_token(m_tok_comma);
- double r_IN = eval_param(get_token());
- require_token(m_tok_comma);
- double r_OUT = eval_param(get_token());
- require_token(m_tok_param_right);
-
- m_setup.register_frontier(attachat, r_IN, r_OUT);
-}
-
-void parser_t::net_include()
-{
- // don't do much
- pstring name = get_identifier();
- require_token(m_tok_param_right);
+ m_setup.include(name);
+ }
- m_setup.include(name);
-}
+ 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);
-void parser_t::net_local_source()
-{
- // This directive is only for hardcoded netlists. Ignore it here.
- pstring name = get_identifier();
- require_token(m_tok_param_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())
+ m_setup.register_source<source_token_t>(name, p->second);
+ else
+ error(MF_LOCAL_SOURCE_NOT_FOUND_1(name));
+ }
-void parser_t::net_alias()
-{
- pstring alias = get_identifier_or_number();
+ void parser_t::net_external_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);
+ }
- require_token(m_tok_comma);
+ void parser_t::net_alias()
+ {
+ require_token(m_tok_paren_left);
+ pstring alias = get_identifier_or_number();
- pstring out = get_identifier();
+ require_token(m_tok_comma);
- require_token(m_tok_param_right);
+ pstring out = get_identifier();
- m_setup.log().debug("Parser: Alias: {1} {2}\n", alias, out);
- m_setup.register_alias(alias, out);
-}
+ require_token(m_tok_paren_right);
-void parser_t::net_c()
-{
- pstring first = get_identifier();
- require_token(m_tok_comma);
+ m_setup.log().debug("Parser: Alias: {1} {2}\n", alias, out);
+ m_setup.register_alias(alias, out);
+ }
- while (true)
+ void parser_t::net_c()
{
- pstring t1 = get_identifier();
- m_setup.register_link(first , t1);
- m_setup.log().debug("Parser: Connect: {1} {2}\n", first, t1);
- token_t n = get_token();
- if (n.is(m_tok_param_right))
- break;
- if (!n.is(m_tok_comma))
- error(plib::pfmt("expected a comma, found <{1}>")(n.str()) );
+ require_token(m_tok_paren_left);
+ pstring first = get_identifier();
+ require_token(m_tok_comma);
+
+ while (true)
+ {
+ pstring t1 = get_identifier();
+ m_setup.register_connection(first, t1);
+ m_setup.log().debug("Parser: Connect: {1} {2}\n", first, t1);
+ token_t n = get_token();
+ if (n.is(m_tok_paren_right))
+ break;
+ if (!n.is(m_tok_comma))
+ error(MF_EXPECTED_COMMA_OR_RP_1(n.str()));
+ }
}
-}
+ void parser_t::dip_pins()
+ {
+ std::vector<pstring> pins;
-void parser_t::dippins()
-{
- std::vector<pstring> pins;
+ require_token(m_tok_paren_left);
+ pins.push_back(get_identifier());
+ require_token(m_tok_comma);
- pins.push_back(get_identifier());
- require_token(m_tok_comma);
+ while (true)
+ {
+ pstring t1 = get_identifier();
+ pins.push_back(t1);
+ token_t n = get_token();
+ if (n.is(m_tok_paren_right))
+ break;
+ if (!n.is(m_tok_comma))
+ error(MF_EXPECTED_COMMA_OR_RP_1(n.str()));
+ }
+ if ((pins.size() % 2) == 1)
+ error(MF_DIPPINS_EQUAL_NUMBER_1(pins[0]));
+ std::size_t n = pins.size();
+ for (std::size_t i = 0; i < n / 2; i++)
+ {
+ m_setup.register_alias(detail::alias_type::PACKAGE_PIN,
+ plib::pfmt("{1}")(i + 1), pins[i * 2]);
+ m_setup.register_alias(detail::alias_type::PACKAGE_PIN,
+ plib::pfmt("{1}")(n - i), pins[i * 2 + 1]);
+ }
+ }
- while (true)
+ void parser_t::netdev_param()
{
- pstring t1 = get_identifier();
- pins.push_back(t1);
- token_t n = get_token();
- if (n.is(m_tok_param_right))
- break;
- if (!n.is(m_tok_comma))
- error(plib::pfmt("expected a comma, found <{1}>")(n.str()) );
+ require_token(m_tok_paren_left);
+ pstring param(get_identifier());
+ require_token(m_tok_comma);
+ token_t tok = get_token();
+ if (tok.is_type(token_type::STRING))
+ {
+ m_setup.log().debug("Parser: Param: {1} {2}\n", param, tok.str());
+ m_setup.register_param(param, tok.str());
+ require_token(m_tok_paren_right);
+ }
+ else
+ {
+ auto val = stringify_expression(tok);
+ m_setup.log().debug("Parser: Param: {1} {2}\n", param, val);
+ m_setup.register_param(param, val);
+ require_token(tok, m_tok_paren_right);
+ }
}
- if ((pins.size() % 2) == 1)
- error(plib::pfmt("You must pass an equal number of pins to DIPPINS, first pin is {}")(pins[0]));
- std::size_t n = pins.size();
- for (std::size_t i = 0; i < n / 2; i++)
+
+ void parser_t::netdev_default_param()
{
- m_setup.register_alias(plib::pfmt("{1}")(i+1), pins[i*2]);
- m_setup.register_alias(plib::pfmt("{1}")(n-i), pins[i*2 + 1]);
+ require_token(m_tok_paren_left);
+ pstring param(get_identifier());
+ require_token(m_tok_comma);
+ token_t tok = get_token();
+ if (tok.is_type(token_type::STRING))
+ {
+ m_setup.log().debug("Parser: DefParam: {1} {2}\n", param,
+ tok.str());
+ m_setup.register_default_param(param, tok.str());
+ require_token(m_tok_paren_right);
+ }
+ else
+ {
+ auto val = stringify_expression(tok);
+ m_setup.log().debug("Parser: Param: {1} {2}\n", param, val);
+ m_setup.register_default_param(param, val);
+ require_token(tok, m_tok_paren_right);
+ }
}
-}
-void parser_t::netdev_param()
-{
- pstring param;
- param = get_identifier();
- require_token(m_tok_comma);
- token_t tok = get_token();
- if (tok.is_type(STRING))
+ void parser_t::netdev_hint()
{
- m_setup.log().debug("Parser: Param: {1} {2}\n", param, tok.str());
- m_setup.register_param(param, tok.str());
+ require_token(m_tok_paren_left);
+ pstring id(get_identifier());
+ require_token(m_tok_comma);
+ pstring hint(get_identifier());
+ m_setup.register_hint(id, ".HINT_" + hint);
+ require_token(m_tok_paren_right);
}
- else
+
+ void parser_t::net_register_dev()
{
- nl_double val = eval_param(tok);
- m_setup.log().debug("Parser: Param: {1} {2}\n", param, val);
- m_setup.register_param(param, val);
- }
- require_token(m_tok_param_right);
-}
+ require_token(m_tok_paren_left);
+ pstring type(get_identifier());
+ require_token(m_tok_comma);
+ pstring name(get_identifier());
+ require_token(m_tok_paren_right);
-void parser_t::netdev_hint()
-{
- pstring dev(get_identifier());
- require_token(m_tok_comma);
- pstring hint(get_identifier());
- m_setup.register_param(dev + ".HINT_" + hint, 1);
- require_token(m_tok_param_right);
-}
-
-void parser_t::device(const pstring &dev_type)
-{
- factory::element_t *f = m_setup.factory().factory_by_name(dev_type);
- auto paramlist = plib::psplit(f->param_desc(), ",");
+ m_setup.register_dev(type, name);
+ }
- pstring devname = get_identifier();
+ void parser_t::device(const pstring &dev_type)
+ {
+ std::vector<pstring> params;
- m_setup.register_dev(dev_type, devname);
- m_setup.log().debug("Parser: IC: {1}\n", devname);
+ require_token(m_tok_paren_left);
+ pstring devname(get_identifier());
- for (const pstring &tp : paramlist)
- {
- if (plib::startsWith(tp, "+"))
- {
- require_token(m_tok_comma);
- pstring output_name = get_identifier();
- m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
+ m_setup.log().debug("Parser: IC: {1}\n", devname);
- m_setup.register_link(devname + "." + tp.substr(1), output_name);
- }
- else if (plib::startsWith(tp, "@"))
- {
- pstring term = tp.substr(1);
- m_setup.log().debug("Link: {1} {2}\n", tp, term);
+ auto tok(get_token());
- //FIXME
- if (term == "VCC")
- m_setup.register_link(devname + "." + term, "V5");
- else
- m_setup.register_link(devname + "." + term, term);
- }
- else
+ while (tok.is(m_tok_comma))
{
- require_token(m_tok_comma);
- pstring paramfq = devname + "." + tp;
-
- m_setup.log().debug("Defparam: {1}\n", paramfq);
- token_t tok = get_token();
- if (tok.is_type(STRING))
+ tok = get_token();
+ if (tok.is_type(token_type::STRING))
{
- m_setup.register_param(paramfq, tok.str());
+ params.push_back(tok.str());
+ tok = get_token();
}
else
{
- nl_double val = eval_param(tok);
- m_setup.register_param(paramfq, val);
+ auto value = stringify_expression(tok);
+ params.push_back(value);
}
}
- }
- // error(plib::pfmt("Input count mismatch for {1} - expected {2} found {3}")(devname)(termlist.size())(cnt));
- require_token(m_tok_param_right);
-}
+ require_token(tok, m_tok_paren_right);
+ m_setup.register_dev(dev_type, devname, params);
+ }
+ // -------------------------------------------------------------------------
+ // private
+ // -------------------------------------------------------------------------
-// ----------------------------------------------------------------------------------------
-// private
-// ----------------------------------------------------------------------------------------
+ pstring parser_t::stringify_expression(token_t &tok)
+ {
+ int pc(0);
+ pstring ret;
+ while (!tok.is(m_tok_comma))
+ {
+ if (tok.is(m_tok_paren_left))
+ pc++;
+ else if (tok.is(m_tok_paren_right))
+ {
+ if (pc <= 0)
+ break;
+ pc--;
+ }
+ ret += tok.str();
+ tok = get_token();
+ }
+ return ret;
+ }
+ // -------------------------------------------------------------------------
+ // source_token_t
+ // -------------------------------------------------------------------------
-nl_double parser_t::eval_param(const token_t &tok)
-{
- static std::array<pstring, 6> macs = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
- static std::array<nl_double, 6> facs = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
- std::size_t f=0;
- nl_double ret;
-
- for (std::size_t i=1; i<macs.size();i++)
- if (tok.str() == macs[i])
- f = i;
- if (f>0)
+ bool source_token_t::parse(nlparse_t &setup, const pstring &name)
{
- require_token(m_tok_param_left);
- ret = get_number_double();
- require_token(m_tok_param_right);
+ if (name == m_name)
+ {
+ auto ret = setup.parse_tokens(m_store, name);
+ return ret;
+ }
+
+ return false;
}
- else
+
+ plib::istream_uptr
+ source_token_t::stream([[maybe_unused]] const pstring &name)
{
- bool err;
- ret = plib::pstonum_ne<nl_double, true>(tok.str(), err);
- if (err)
- error(plib::pfmt("Parameter value <{1}> not double \n")(tok.str()));
+ return plib::istream_uptr();
}
- return ret * facs[f];
-
-}
} // namespace netlist