void nl_convert_spice_t::process_line(const pstring &line) { if (line != "") { pstring_vector_t tt(line, " ", true); double val = 0.0; switch (tt[0].code_at(0)) { case ';': out("// {}\n", line.substr(1).cstr()); break; case '*': out("// {}\n", line.substr(1).cstr()); break; case '.': if (tt[0].equals(".SUBCKT")) { out("NETLIST_START({})\n", tt[1].cstr()); for (std::size_t i=2; i<tt.size(); i++) add_ext_alias(tt[i]); } else if (tt[0].equals(".ENDS")) { dump_nl(); out("NETLIST_END()\n"); } else out("// {}\n", line.cstr()); break; case 'Q': { bool cerr = false; /* check for fourth terminal ... should be numeric net * including "0" or start with "N" (ltspice) */ ATTR_UNUSED int nval =tt[4].as_long(&cerr); pstring model; pstring pins ="CBE"; if ((!cerr || tt[4].startsWith("N")) && tt.size() > 5) model = tt[5]; else model = tt[4]; pstring_vector_t m(model,"{"); if (m.size() == 2) { if (m[1].len() != 4) fprintf(stderr, "error with model desc %s\n", model.cstr()); pins = m[1].left(3); } add_device("QBJT_EB", tt[0], m[0]); add_term(tt[1], tt[0] + "." + pins.code_at(0)); add_term(tt[2], tt[0] + "." + pins.code_at(1)); add_term(tt[3], tt[0] + "." + pins.code_at(2)); } break; case 'R': if (tt[0].startsWith("RV")) { val = get_sp_val(tt[4]); add_device("POT", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); add_term(tt[3], tt[0] + ".3"); } else { val = get_sp_val(tt[3]); add_device("RES", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); } break; case 'C': val = get_sp_val(tt[3]); add_device("CAP", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); break; case 'V': // just simple Voltage sources .... if (tt[2].equals("0")) { val = get_sp_val(tt[3]); add_device("ANALOG_INPUT", tt[0], val); add_term(tt[1], tt[0] + ".Q"); //add_term(tt[2], tt[0] + ".2"); } else fprintf(stderr, "Voltage Source %s not connected to GND\n", tt[0].cstr()); break; case 'I': // Input pin special notation { val = get_sp_val(tt[2]); add_device("ANALOG_INPUT", tt[0], val); add_term(tt[1], tt[0] + ".Q"); } break; case 'D': add_device("DIODE", tt[0], tt[3]); /* FIXME ==> does Kicad use different notation from LTSPICE */ add_term(tt[1], tt[0] + ".K"); add_term(tt[2], tt[0] + ".A"); break; case 'U': case 'X': { // FIXME: specific code for KICAD exports // last element is component type // FIXME: Parameter pstring xname = tt[0].replace(".", "_"); pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP"; add_device(tname, xname); for (std::size_t i=1; i < tt.size() - 1; i++) { pstring term = pfmt("{1}.{2}")(xname)(i); add_term(tt[i], term); } break; } default: out("// IGNORED {}: {}\n", tt[0].cstr(), line.cstr()); } } }
void nl_convert_spice_t::process_line(const pstring &line) { if (line != "") { //printf("// %s\n", line.c_str()); std::vector<pstring> tt(plib::psplit(line, " ", true)); double val = 0.0; switch (tt[0].at(0)) { case ';': out("// {}\n", line.substr(1)); break; case '*': out("// {}\n", line.substr(1).c_str()); break; case '.': if (tt[0] == ".SUBCKT") { m_subckt = tt[1] + "_"; out("NETLIST_START({})\n", tt[1]); for (std::size_t i=2; i<tt.size(); i++) add_ext_alias(tt[i]); } else if (tt[0] == ".ENDS") { dump_nl(); out("NETLIST_END()\n"); m_subckt = ""; } else if (tt[0] == ".MODEL") { out("NET_MODEL(\"{} {}\")\n", m_subckt + tt[1], rem(tt,2)); } else out("// {}\n", line.c_str()); break; case 'Q': { /* check for fourth terminal ... should be numeric net * including "0" or start with "N" (ltspice) */ pstring model; pstring pins ="CBE"; bool err; auto nval = plib::pstonum_ne<long, true>(tt[4], err); plib::unused_var(nval); if ((!err || plib::startsWith(tt[4], "N")) && tt.size() > 5) model = tt[5]; else model = tt[4]; std::vector<pstring> m(plib::psplit(model,"{")); if (m.size() == 2) { if (m[1].length() != 4) plib::perrlogger("error with model desc {}\n", model); pins = plib::left(m[1], 3); } add_device("QBJT_EB", tt[0], m_subckt + m[0]); add_term(tt[1], tt[0] + "." + pins.at(0)); add_term(tt[2], tt[0] + "." + pins.at(1)); add_term(tt[3], tt[0] + "." + pins.at(2)); } break; case 'R': if (plib::startsWith(tt[0], "RV")) { val = get_sp_val(tt[4]); add_device("POT", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); add_term(tt[3], tt[0] + ".3"); } else { val = get_sp_val(tt[3]); add_device("RES", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); } break; case 'C': val = get_sp_val(tt[3]); add_device("CAP", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); break; case 'B': // arbitrary behavioural current source - needs manual work afterwords add_device("CS", tt[0], "/*" + rem(tt, 3) + "*/"); add_term(tt[1], tt[0] + ".P"); add_term(tt[2], tt[0] + ".N"); break; case 'E': add_device("VCVS", tt[0]); add_term(tt[1], tt[0] + ".OP"); add_term(tt[2], tt[0] + ".ON"); add_term(tt[3], tt[0] + ".IP"); add_term(tt[4], tt[0] + ".IN"); out("PARAM({}, {})\n", tt[0] + ".G", tt[5]); break; case 'V': // just simple Voltage sources .... if (tt[2] == "0") { val = get_sp_val(tt[3]); add_device("ANALOG_INPUT", tt[0], val); add_term(tt[1], tt[0] + ".Q"); //add_term(tt[2], tt[0] + ".2"); } else plib::perrlogger("Voltage Source {} not connected to GND\n", tt[0]); break; #if 0 // This is wrong ... Need to use something else for inputs! case 'I': // Input pin special notation { val = get_sp_val(tt[2]); add_device("ANALOG_INPUT", tt[0], val); add_term(tt[1], tt[0] + ".Q"); } break; #else case 'I': { val = get_sp_val(tt[3]); add_device("CS", tt[0], val); add_term(tt[1], tt[0] + ".1"); add_term(tt[2], tt[0] + ".2"); } break; #endif case 'D': add_device("DIODE", tt[0], tt[3]); /* FIXME ==> does Kicad use different notation from LTSPICE */ add_term(tt[1], tt[0] + ".K"); add_term(tt[2], tt[0] + ".A"); break; case 'U': case 'X': { // FIXME: specific code for KICAD exports // last element is component type // FIXME: Parameter pstring xname = plib::replace_all(tt[0], pstring("."), pstring("_")); pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP"; add_device(tname, xname); for (std::size_t i=1; i < tt.size() - 1; i++) { pstring term = plib::pfmt("{1}.{2}")(xname)(i); add_term(tt[i], term); } break; } default: out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str()); } } }