From d0970c215f9e3dfa4a44a7627dcde675a48e006e Mon Sep 17 00:00:00 2001 From: couriersud Date: Wed, 10 Aug 2016 23:08:20 +0200 Subject: [PATCH] Add a preliminary parser for RINF netlist format. (nw) --- src/lib/netlist/plib/pparser.cpp | 8 +- src/lib/netlist/prg/nltool.cpp | 10 +- src/lib/netlist/tools/nl_convert.cpp | 251 ++++++++++++++++++++++++++- src/lib/netlist/tools/nl_convert.h | 69 ++++++++ 4 files changed, 332 insertions(+), 6 deletions(-) diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp index 4f41c73d6f8..0a19685316d 100644 --- a/src/lib/netlist/plib/pparser.cpp +++ b/src/lib/netlist/plib/pparser.cpp @@ -106,7 +106,7 @@ pstring ptokenizer::get_identifier_or_number() token_t tok = get_token(); if (!(tok.is_type(IDENTIFIER) || tok.is_type(NUMBER))) { - error(pfmt("Expected an identifier, got <{1}>")(tok.str()) ); + error(pfmt("Expected an identifier or number, got <{1}>")(tok.str()) ); } return tok.str(); } @@ -203,7 +203,8 @@ ptokenizer::token_t ptokenizer::get_token_internal() { /* read identifier till non identifier char */ pstring tokstr = ""; - while (m_identifier_chars.find(c) != m_identifier_chars.end()) { + while (m_identifier_chars.find(c) != m_identifier_chars.end()) + { tokstr += c; c = getc(); } @@ -229,7 +230,8 @@ ptokenizer::token_t ptokenizer::get_token_internal() { /* read identifier till first identifier char or ws */ pstring tokstr = ""; - while ((m_identifier_chars.find(c)) == m_identifier_chars.end() && (m_whitespace.find(c) == m_whitespace.end())) { + while ((m_identifier_chars.find(c) == m_identifier_chars.end()) && (m_whitespace.find(c) == m_whitespace.end())) + { tokstr += c; /* expensive, check for single char tokens */ if (tokstr.len() == 1) diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 92057688954..b095a081f81 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -41,7 +41,7 @@ public: opt_logs(*this, "l", "log" , "define terminal to log. This option may be specified repeatedly."), opt_inp(*this, "i", "input", "", "input file to process (default is none)"), opt_grp4(*this, "Options for convert command", "These options are only used by the convert command."), - opt_type(*this, "y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle"), + opt_type(*this, "y", "type", "spice", "spice:eagle:rinf", "type of file to be converted: spice,eagle,rinf"), opt_ex1(*this, "nltool -c run -t 3.5 -f nl_examples/cdelay.c -n cap_delay", "Run netlist \"cap_delay\" from file nl_examples/cdelay.c for 3.5 seconds"), @@ -465,12 +465,18 @@ int main(int argc, char *argv[]) c.convert(contents); result = c.result(); } - else + else if (opts.opt_type().equals("eagle")) { nl_convert_eagle_t c; c.convert(contents); result = c.result(); } + else if (opts.opt_type().equals("rinf")) + { + nl_convert_rinf_t c; + c.convert(contents); + result = c.result(); + } /* present result */ pout_strm.write(result.cstr()); } diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp index b0ca5fe3c0d..978be90caaf 100644 --- a/src/lib/netlist/tools/nl_convert.cpp +++ b/src/lib/netlist/tools/nl_convert.cpp @@ -8,9 +8,51 @@ #include #include #include +#include #include "nl_convert.h" #include "plib/palloc.h" +#include "plib/putil.h" +/* FIXME: temporarily defined here - should be in a file */ +/* FIXME: family logic in netlist is convoluted, create + * define a model param on core device + */ +/* Format: external name,netlist device,model */ +static const char *s_lib_map = +"SN74LS00D, TTL_7400_DIP, 74LSXX\n" +"SN74LS04D, TTL_7404_DIP, 74LSXX\n" +"SN74ALS08D, TTL_7408_DIP, 74ALSXX\n" +"SN74ALS10AD, TTL_7410_DIP, 74ALSXX\n" +"SN74LS30N, TTL_7430_DIP, 74LSXX\n" +"SN74ALS74AD, TTL_7474_DIP, 74ALSXX\n" +"SN74LS74AD, TTL_7474_DIP, 74LSXX\n" +"SN74LS86AD, TTL_7486_DIP, 74LSXX\n" +"SN74F153D, TTL_74153_DIP, 74FXX\n" +"SN74LS161AD, TTL_74161_DIP, 74LSXX\n" +"SN74LS164D, TTL_74164_DIP, 74LSXX\n" +"DM74LS366AN, TTL_74366_DIP, 74LSXX\n" +; + +struct lib_map_entry +{ + pstring dev; + pstring model; +}; + +using lib_map_t = std::unordered_map; + +static lib_map_t read_lib_map(const pstring lm) +{ + plib::pistringstream istrm(lm); + lib_map_t m; + pstring line; + while (istrm.readline(line)) + { + plib::pstring_vector_t split(line, ","); + m[split[0].trim()] = { split[1].trim(), split[2].trim() }; + } + return m; +} /*------------------------------------------------- convert - convert a spice netlist @@ -173,8 +215,9 @@ nl_convert_base_t::unit_t nl_convert_base_t::m_units[] = { {"M", "CAP_M({1})", 1.0e-3 }, {"u", "CAP_U({1})", 1.0e-6 }, /* eagle */ {"U", "CAP_U({1})", 1.0e-6 }, - {"??", "CAP_U({1})", 1.0e-6 }, + {"??", "CAP_U({1})", 1.0e-6 }, /* FIXME */ {"N", "CAP_N({1})", 1.0e-9 }, + {"pF", "CAP_P({1})", 1.0e-12}, {"P", "CAP_P({1})", 1.0e-12}, {"F", "{1}e-15", 1.0e-15}, @@ -448,3 +491,209 @@ void nl_convert_eagle_t::convert(const pstring &contents) } } + +/* token_id_t m_tok_HFA; + token_id_t m_tok_APP; + token_id_t m_tok_TIM; + token_id_t m_tok_TYP; + token_id_t m_tok_ADDC; + token_id_t m_tok_ATTC; + token_id_t m_tok_NET; + token_id_t m_tok_TER; + * + */ +void nl_convert_rinf_t::convert(const pstring &contents) +{ + plib::pistringstream istrm(contents); + tokenizer tok(*this, istrm); + auto lm = read_lib_map(s_lib_map); + + out("NETLIST_START(dummy)\n"); + add_term("GND", "GND"); + add_term("VCC", "VCC"); + tokenizer::token_t token = tok.get_token(); + while (true) + { + if (token.is_type(tokenizer::ENDOFFILE) || token.is(tok.m_tok_END)) + { + dump_nl(); + // FIXME: Parameter + out("NETLIST_END()\n"); + return; + } + else if (token.is(tok.m_tok_HEA)) + { + /* seems to be start token - ignore */ + token = tok.get_token(); + } + else if (token.is(tok.m_tok_APP)) + { + /* version string */ + pstring app = tok.get_string(); + out("// APP: {}\n", app); + token = tok.get_token(); + } + else if (token.is(tok.m_tok_TIM)) + { + /* time */ + out("// TIM:"); + for (int i=0; i<6; i++) + { + long x = tok.get_number_long(); + out(" {}", x); + } + out("\n"); + token = tok.get_token(); + } + else if (token.is(tok.m_tok_TYP)) + { + pstring id(tok.get_identifier()); + out("// TYP: {}\n", id); + token = tok.get_token(); + } + else if (token.is(tok.m_tok_ADDC)) + { + std::unordered_map attr; + pstring id = tok.get_identifier(); + pstring s1 = tok.get_string(); + pstring s2 = tok.get_string(); + + token = tok.get_token(); + while (token.is(tok.m_tok_ATTC)) + { + pstring tid = tok.get_identifier(); + if (tid != id) + { + out("Error: found {} expected {} in {}\n", tid, id, token.str()); + return; + } + pstring at = tok.get_string(); + pstring val = tok.get_string(); + attr[at] = val; + token = tok.get_token(); + } + pstring sim = attr["Simulation"]; + pstring val = attr["Value"]; + pstring com = attr["Comment"]; + if (val == "") + val = com; + + if (sim == "CAP") + { + add_device("CAP", id, get_sp_val(val)); + } + else if (sim == "RESISTOR") + { + add_device("RES", id, get_sp_val(val)); + } + else + { + pstring lib = attr["Library Reference"]; + auto f = lm.find(lib); + if (f != lm.end()) + add_device(f->second.dev, id); + else + add_device(lib, id); + } + } + else if (token.is(tok.m_tok_NET)) + { + pstring dev = tok.get_identifier(); + pstring pin = tok.get_identifier_or_number(); + pstring net = tok.get_string(); + add_term(net, dev + "." + pin); + token = tok.get_token(); + if (token.is(tok.m_tok_TER)) + { + token = tok.get_token(); + while (token.is_type(plib::ptokenizer::IDENTIFIER)) + { + pin = tok.get_identifier_or_number(); + add_term(net, token.str() + "." + pin); + token = tok.get_token(); + } + } + } +#if 0 + token = tok.get_token(); + /* skip to semicolon */ + do + { + token = tok.get_token(); + } while (!token.is(tok.m_tok_SEMICOLON)); + token = tok.get_token(); + pstring sval = ""; + if (token.is(tok.m_tok_VALUE)) + { + pstring vname = tok.get_string(); + sval = tok.get_string(); + tok.require_token(tok.m_tok_SEMICOLON); + token = tok.get_token(); + } + switch (name.code_at(0)) + { + case 'Q': + { + add_device("QBJT", name, sval); + } + break; + case 'R': + { + double val = get_sp_val(sval); + add_device("RES", name, val); + } + break; + case 'C': + { + double val = get_sp_val(sval); + add_device("CAP", name, val); + } + break; + case 'P': + if (sval.ucase() == "HIGH") + add_device("TTL_INPUT", name, 1); + else if (sval.ucase() == "LOW") + add_device("TTL_INPUT", name, 0); + else + add_device("ANALOG_INPUT", name, sval.as_double()); + add_pin_alias(name, "1", "Q"); + break; + case 'D': + /* Pin 1 = Anode, Pin 2 = Cathode */ + add_device("DIODE", name, sval); + add_pin_alias(name, "1", "A"); + add_pin_alias(name, "2", "K"); + break; + case 'U': + case 'X': + { + pstring tname = "TTL_" + sval + "_DIP"; + add_device(tname, name); + break; + } + default: + tok.error("// IGNORED " + name); + } + + } + else if (token.is(tok.m_tok_SIGNAL)) + { + pstring netname = tok.get_string(); + token = tok.get_token(); + while (!token.is(tok.m_tok_SEMICOLON)) + { + /* fixme: should check for string */ + pstring devname = token.str(); + pstring pin = tok.get_string(); + add_term(netname, devname + "." + pin); + token = tok.get_token(); } + } +#endif + else + { + out("Unexpected {}\n", token.str()); + return; + } + } + +} diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index 209057a06d5..fa496a092d7 100644 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -217,6 +217,75 @@ public: protected: +private: + +}; + +class nl_convert_rinf_t : public nl_convert_base_t +{ +public: + + nl_convert_rinf_t() : nl_convert_base_t() {} + ~nl_convert_rinf_t() + { + } + + class tokenizer : public plib::ptokenizer + { + public: + tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm) + : plib::ptokenizer(strm), m_convert(convert) + { + set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-"); + set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers + char ws[5]; + ws[0] = ' '; + ws[1] = 9; + ws[2] = 10; + ws[3] = 13; + ws[4] = 0; + set_whitespace(ws); + /* FIXME: gnetlist doesn't print comments */ + set_comment("","","//"); // FIXME:needs to be confirmed + set_string_char('"'); + m_tok_HEA = register_token(".HEA"); + m_tok_APP = register_token(".APP"); + m_tok_TIM = register_token(".TIM"); + m_tok_TYP = register_token(".TYP"); + m_tok_ADDC = register_token(".ADD_COM"); + m_tok_ATTC = register_token(".ATT_COM"); + m_tok_NET = register_token(".ADD_TER"); + m_tok_TER = register_token(".TER"); + m_tok_END = register_token(".END"); + } + + token_id_t m_tok_HEA; + token_id_t m_tok_APP; + token_id_t m_tok_TIM; + token_id_t m_tok_TYP; + token_id_t m_tok_ADDC; + token_id_t m_tok_ATTC; + token_id_t m_tok_NET; + token_id_t m_tok_TER; + token_id_t m_tok_END; + + protected: + + void verror(const pstring &msg, int line_num, const pstring &line) override + { + m_convert.out("{} (line {}): {}\n", msg.cstr(), line_num, line.cstr()); + } + + + private: + nl_convert_rinf_t &m_convert; + }; + + void convert(const pstring &contents) override; + +protected: + + private: };