double nl_convert_base_t::get_sp_val(const pstring &sin) { std::size_t p = 0; while (p < sin.length() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos)) ++p; pstring val = plib::left(sin, p); pstring unit = sin.substr(p); double ret = get_sp_unit(unit) * plib::pstonum<double, true>(val); return ret; }
double nl_convert_base_t::get_sp_val(const pstring &sin) { std::size_t p = 0; while (p < sin.length() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos)) ++p; pstring val = sin.left(p); pstring unit = sin.substr(p); double ret = get_sp_unit(unit) * val.as_double(); return ret; }
double nl_convert_base_t::get_sp_val(const pstring &sin) { int p = sin.len() - 1; while (p>=0 && (sin.substr(p,1) < "0" || sin.substr(p,1) > "9")) p--; pstring val = sin.substr(0,p + 1); pstring unit = sin.substr(p + 1); double ret = get_sp_unit(unit) * val.as_double(); return ret; }
void pfunction::compile(const std::vector<pstring> &inputs, const pstring &expr) { if (expr.startsWith("rpn:")) compile_postfix(inputs, expr.substr(4)); else compile_infix(inputs, expr); }
pstring ppreprocessor::process_comments(pstring line) { bool in_string = false; std::size_t e = line.size(); pstring ret = ""; for (std::size_t i=0; i < e; ) { pstring c = plib::left(line, 1); line = line.substr(1); if (!m_comment) { if (c=="\"") { in_string = !in_string; ret += c; } else if (in_string && c=="\\") { i++; ret += (c + plib::left(line, 1)); line = line.substr(1); } else if (!in_string && c=="/" && plib::left(line,1) == "*") m_comment = true; else if (!in_string && c=="/" && plib::left(line,1) == "/") break; else ret += c; } else if (c=="*" && plib::left(line,1) == "/") { i++; line = line.substr(1); m_comment = false; } i++; } return ret; }
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()); } } }