netlist: code maintenance. (nw)

Remove dead code, fix lint warnings, make spice netlist conversion more
flexible, implement changes to controlled sources.
This commit is contained in:
couriersud 2020-02-03 20:21:40 +01:00
parent c2ca6e6369
commit 636315be5f
5 changed files with 92 additions and 50 deletions

View File

@ -39,22 +39,17 @@ public:
COPYASSIGN(putf8_reader, delete) COPYASSIGN(putf8_reader, delete)
virtual ~putf8_reader() = default; virtual ~putf8_reader() = default;
putf8_reader(putf8_reader &&rhs) putf8_reader(putf8_reader &&rhs) noexcept
: m_strm(std::move(rhs.m_strm)) : m_strm(std::move(rhs.m_strm))
, m_linebuf(std::move(rhs.m_linebuf)) , m_linebuf(std::move(rhs.m_linebuf))
{ {
} }
putf8_reader(plib::unique_ptr<std::istream> &&rhs) putf8_reader(plib::unique_ptr<std::istream> &&rhs) noexcept
: m_strm(std::move(rhs)) : m_strm(std::move(rhs))
{ {
} }
#if 0
template<typename T, typename... Args>
putf8_reader(Args&&... args)
: m_strm(plib::make_unique<T>(std::forward<Args>(args)...))
{}
#endif
bool eof() const { return m_strm->eof(); } bool eof() const { return m_strm->eof(); }
bool readline(pstring &line) bool readline(pstring &line)

View File

@ -234,7 +234,9 @@ namespace plib {
ungetc(c); ungetc(c);
return token_t(ret, tokstr); return token_t(ret, tokstr);
} }
else if (m_identifier_chars.find(c) != pstring::npos)
// not a number, try identifier
if (m_identifier_chars.find(c) != pstring::npos)
{ {
// read identifier till non identifier char // read identifier till non identifier char
pstring tokstr = ""; pstring tokstr = "";

View File

@ -138,7 +138,6 @@ public:
bool readmore(std::vector<plib::putf8_reader> &r) bool readmore(std::vector<plib::putf8_reader> &r)
{ {
fprintf(stderr, "%d %d\n", (int) m_e.size(), (int) r.size());
bool success = false; bool success = false;
for (std::size_t i = 0; i< r.size(); i++) for (std::size_t i = 0; i< r.size(); i++)
{ {
@ -146,7 +145,6 @@ public:
{ {
pstring line; pstring line;
m_e[i].eof = !r[i].readline(line); m_e[i].eof = !r[i].readline(line);
//fprintf(stderr, "bla: <%s>\n", line.c_str());
if (!m_e[i].eof) if (!m_e[i].eof)
{ {
// sscanf is very fast ... // sscanf is very fast ...
@ -518,7 +516,6 @@ int nlwav_app::execute()
for (auto &oi: opt_args()) for (auto &oi: opt_args())
{ {
plib::unique_ptr<std::istream> fin; plib::unique_ptr<std::istream> fin;
printf("%s\n", oi.c_str());
if (oi == "-") if (oi == "-")
{ {
auto temp(plib::make_unique<std::stringstream>()); auto temp(plib::make_unique<std::stringstream>());

View File

@ -226,7 +226,7 @@ void nl_convert_base_t::dump_nl()
{ {
net_t *net = m_nets[alias].get(); net_t *net = m_nets[alias].get();
// use the first terminal ... // use the first terminal ...
out("ALIAS({}, {})\n", alias.c_str(), net->terminals()[0].c_str()); out("ALIAS({}, {})\n", alias, net->terminals()[0]);
// if the aliased net only has this one terminal connected ==> don't dump // if the aliased net only has this one terminal connected ==> don't dump
if (net->terminals().size() == 1) if (net->terminals().size() == 1)
net->set_no_export(); net->set_no_export();
@ -243,14 +243,17 @@ void nl_convert_base_t::dump_nl()
std::size_t j = sorted[i]; std::size_t j = sorted[i];
if (m_devs[j]->has_value()) if (m_devs[j]->has_value())
out("{}({}, {})\n", m_devs[j]->type().c_str(), {
m_devs[j]->name().c_str(), get_nl_val(m_devs[j]->value()).c_str()); pstring t = m_devs[j]->type();
pstring vals = (t == "RES" || t == "CAP") ? get_nl_val(m_devs[j]->value()) : plib::pfmt("{1:g}")(m_devs[j]->value());
out("{}({}, {})\n", t, m_devs[j]->name(), vals);
}
else if (m_devs[j]->has_model()) else if (m_devs[j]->has_model())
out("{}({}, \"{}\")\n", m_devs[j]->type().c_str(), out("{}({}, \"{}\")\n", m_devs[j]->type(),
m_devs[j]->name().c_str(), m_devs[j]->model().c_str()); m_devs[j]->name(), m_devs[j]->model());
else else
out("{}({})\n", m_devs[j]->type().c_str(), out("{}({})\n", m_devs[j]->type(),
m_devs[j]->name().c_str()); m_devs[j]->name());
for (auto &e : m_devs[j]->extra()) for (auto &e : m_devs[j]->extra())
out("{}\n", e); out("{}\n", e);
@ -261,10 +264,10 @@ void nl_convert_base_t::dump_nl()
net_t * net = i.second.get(); net_t * net = i.second.get();
if (!net->is_no_export() && !(net->terminals().size() == 1 && net->terminals()[0] == "GND" )) if (!net->is_no_export() && !(net->terminals().size() == 1 && net->terminals()[0] == "GND" ))
{ {
out("NET_C({}", net->terminals()[0].c_str() ); out("NET_C({}", net->terminals()[0] );
for (std::size_t j=1; j<net->terminals().size(); j++) for (std::size_t j=1; j<net->terminals().size(); j++)
{ {
out(", {}", net->terminals()[j].c_str() ); out(", {}", net->terminals()[j] );
} }
out(")\n"); out(")\n");
} }
@ -276,7 +279,7 @@ void nl_convert_base_t::dump_nl()
m_ext_alias.clear(); m_ext_alias.clear();
} }
pstring nl_convert_base_t::get_nl_val(double val) pstring nl_convert_base_t::get_nl_val(double val) const
{ {
for (auto &e : m_units) for (auto &e : m_units)
{ {
@ -294,7 +297,7 @@ pstring nl_convert_base_t::get_nl_val(double val)
return plib::pfmt("{1}")(val); return plib::pfmt("{1}")(val);
} }
double nl_convert_base_t::get_sp_unit(const pstring &unit) double nl_convert_base_t::get_sp_unit(const pstring &unit) const
{ {
for (auto &e : m_units) for (auto &e : m_units)
{ {
@ -305,7 +308,7 @@ double nl_convert_base_t::get_sp_unit(const pstring &unit)
return 0.0; return 0.0;
} }
double nl_convert_base_t::get_sp_val(const pstring &sin) double nl_convert_base_t::get_sp_val(const pstring &sin) const
{ {
std::size_t p = 0; std::size_t p = 0;
while (p < sin.length() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos)) while (p < sin.length() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos))
@ -316,19 +319,26 @@ double nl_convert_base_t::get_sp_val(const pstring &sin)
return ret; return ret;
} }
void nl_convert_spice_t::convert_block(const str_list &contents)
{
for (const auto &line : contents)
process_line(line);
}
void nl_convert_spice_t::convert(const pstring &contents) void nl_convert_spice_t::convert(const pstring &contents)
{ {
std::vector<pstring> spnl(plib::psplit(contents, "\n")); std::vector<pstring> spnl(plib::psplit(contents, "\n"));
std::vector<pstring> after_linecontinuation;
// Add gnd net // Add gnd net
// FIXME: Parameter // FIXME: Parameter
out("NETLIST_START(dummy)\n");
add_term("0", "GND");
add_term("GND", "GND"); // For Kicad
pstring line = ""; pstring line = "";
// process linecontinuation
for (const auto &i : spnl) for (const auto &i : spnl)
{ {
// Basic preprocessing // Basic preprocessing
@ -337,11 +347,50 @@ void nl_convert_spice_t::convert(const pstring &contents)
line += inl.substr(1); line += inl.substr(1);
else else
{ {
process_line(line); after_linecontinuation.push_back(line);
line = inl; line = inl;
} }
} }
process_line(line); after_linecontinuation.push_back(line);
spnl.clear(); // no longer needed
// Process subcircuits
std::vector<std::vector<pstring>> subckts;
std::vector<pstring> nl;
auto inp = after_linecontinuation.begin();
while (inp != after_linecontinuation.end())
{
if (plib::startsWith(*inp, ".SUBCKT"))
{
std::vector<pstring> sub;
while (inp != after_linecontinuation.end())
{
auto s(*inp);
sub.push_back(s);
inp++;
if (plib::startsWith(s, ".ENDS"))
break;
}
subckts.push_back(sub);
}
else
{
nl.push_back(*inp);
inp++;
}
}
for (const auto &sub : subckts)
{
add_term("0", "GND");
add_term("GND", "GND"); // For Kicad
convert_block(sub);
}
out("NETLIST_START(dummy)\n");
convert_block(nl);
dump_nl(); dump_nl();
// FIXME: Parameter // FIXME: Parameter
out("NETLIST_END()\n"); out("NETLIST_END()\n");
@ -381,10 +430,8 @@ void nl_convert_spice_t::process_line(const pstring &line)
switch (tt[0].at(0)) switch (tt[0].at(0))
{ {
case ';': case ';':
out("// {}\n", line.substr(1));
break;
case '*': case '*':
out("// {}\n", line.substr(1).c_str()); out("// {}\n", line.substr(1));
break; break;
case '.': case '.':
if (tt[0] == ".SUBCKT") if (tt[0] == ".SUBCKT")
@ -412,7 +459,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
m_is_kicad = true; m_is_kicad = true;
} }
else else
out("// {}\n", line.c_str()); out("// {}\n", line);
break; break;
case 'Q': case 'Q':
{ {
@ -475,12 +522,12 @@ void nl_convert_spice_t::process_line(const pstring &line)
auto n=npoly(tt[3]); auto n=npoly(tt[3]);
if (n<0) if (n<0)
{ {
add_device("VCVS", tt[0]); add_device("VCVS", tt[0], get_sp_val(tt[5]));
add_term(tt[1], tt[0], 0); add_term(tt[1], tt[0], 0);
add_term(tt[2], tt[0], 1); add_term(tt[2], tt[0], 1);
add_term(tt[3], tt[0], 2); add_term(tt[3], tt[0], 2);
add_term(tt[4], tt[0], 3); add_term(tt[4], tt[0], 3);
add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[5]); //add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[5]);
} }
else else
{ {
@ -488,7 +535,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
auto scoeff(static_cast<unsigned>(5 + n)); auto scoeff(static_cast<unsigned>(5 + n));
if ((tt.size() != 5 + 2 * static_cast<unsigned>(n)) || (tt[scoeff-1] != "0")) if ((tt.size() != 5 + 2 * static_cast<unsigned>(n)) || (tt[scoeff-1] != "0"))
{ {
out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str()); out("// IGNORED {}: {}\n", tt[0], line);
break; break;
} }
pstring lastnet = tt[1]; pstring lastnet = tt[1];
@ -497,12 +544,12 @@ void nl_convert_spice_t::process_line(const pstring &line)
pstring devname = tt[0] + plib::pfmt("{}")(i); pstring devname = tt[0] + plib::pfmt("{}")(i);
pstring nextnet = (i<static_cast<std::size_t>(n)-1) ? tt[1] + "a" + plib::pfmt("{}")(i) : tt[2]; pstring nextnet = (i<static_cast<std::size_t>(n)-1) ? tt[1] + "a" + plib::pfmt("{}")(i) : tt[2];
auto net2 = plib::psplit(plib::replace_all(plib::replace_all(tt[sce+i],")",""),"(",""),","); auto net2 = plib::psplit(plib::replace_all(plib::replace_all(tt[sce+i],")",""),"(",""),",");
add_device("VCVS", devname); add_device("VCVS", devname, get_sp_val(tt[scoeff+i]));
add_term(lastnet, devname, 0); add_term(lastnet, devname, 0);
add_term(nextnet, devname, 1); add_term(nextnet, devname, 1);
add_term(net2[0], devname, 2); add_term(net2[0], devname, 2);
add_term(net2[1], devname, 3); add_term(net2[1], devname, 3);
add_device_extra(devname, "PARAM({}, {})", devname + ".G", tt[scoeff+i]); //add_device_extra(devname, "PARAM({}, {})", devname + ".G", tt[scoeff+i]);
lastnet = nextnet; lastnet = nextnet;
} }
} }
@ -523,39 +570,39 @@ void nl_convert_spice_t::process_line(const pstring &line)
{ {
if ((tt.size() != 5 + 2 * static_cast<unsigned>(n)) || (tt[scoeff-1] != "0")) if ((tt.size() != 5 + 2 * static_cast<unsigned>(n)) || (tt[scoeff-1] != "0"))
{ {
out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str()); out("// IGNORED {}: {}\n", tt[0], line);
break; break;
} }
} }
for (std::size_t i=0; i < static_cast<std::size_t>(n); i++) for (std::size_t i=0; i < static_cast<std::size_t>(n); i++)
{ {
pstring devname = tt[0] + plib::pfmt("{}")(i); pstring devname = tt[0] + plib::pfmt("{}")(i);
add_device("CCCS", devname); add_device("CCCS", devname, get_sp_val(tt[scoeff+i]));
add_term(tt[1], devname, 0); add_term(tt[1], devname, 0);
add_term(tt[2], devname, 1); add_term(tt[2], devname, 1);
pstring extranetname = devname + "net"; pstring extranetname = devname + "net";
m_replace.push_back({tt[sce+i], devname + ".IP", extranetname }); m_replace.push_back({tt[sce+i], devname + ".IP", extranetname });
add_term(extranetname, devname + ".IN"); add_term(extranetname, devname + ".IN");
add_device_extra(devname, "PARAM({}, {})", devname + ".G", tt[scoeff+i]); //add_device_extra(devname, "PARAM({}, {})", devname + ".G", tt[scoeff+i]);
} }
} }
break; break;
case 'H': case 'H':
add_device("CCVS", tt[0]); add_device("CCVS", tt[0], get_sp_val(tt[4]));
add_term(tt[1], tt[0] + ".OP"); add_term(tt[1], tt[0] + ".OP");
add_term(tt[2], tt[0] + ".ON"); add_term(tt[2], tt[0] + ".ON");
m_replace.push_back({tt[3], tt[0] + ".IP", tt[2] + "a" }); m_replace.push_back({tt[3], tt[0] + ".IP", tt[2] + "a" });
add_term(tt[2] + "a", tt[0] + ".IN"); add_term(tt[2] + "a", tt[0] + ".IN");
add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[4]); //add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[4]);
break; break;
case 'G': case 'G':
add_device("VCCS", tt[0]); add_device("VCCS", tt[0], get_sp_val(tt[5]));
add_term(tt[1], tt[0], 0); add_term(tt[1], tt[0], 0);
add_term(tt[2], tt[0], 1); add_term(tt[2], tt[0], 1);
add_term(tt[3], tt[0], 2); add_term(tt[3], tt[0], 2);
add_term(tt[4], tt[0], 3); add_term(tt[4], tt[0], 3);
add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[5]); //add_device_extra(tt[0], "PARAM({}, {})", tt[0] + ".G", tt[5]);
break; break;
case 'V': case 'V':
// only DC Voltage sources .... // only DC Voltage sources ....
@ -634,7 +681,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
break; break;
} }
default: default:
out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str()); out("// IGNORED {}: {}\n", tt[0], line);
} }
} }
} }
@ -770,7 +817,7 @@ void nl_convert_eagle_t::convert(const pstring &contents)
} }
else else
{ {
out("Unexpected {}\n", token.str().c_str()); out("Unexpected {}\n", token.str());
return; return;
} }
} }

View File

@ -56,10 +56,10 @@ protected:
void dump_nl(); void dump_nl();
pstring get_nl_val(double val); pstring get_nl_val(double val) const;
double get_sp_unit(const pstring &unit); double get_sp_unit(const pstring &unit) const;
double get_sp_val(const pstring &sin); double get_sp_val(const pstring &sin) const;
plib::putf8_fmt_writer out; plib::putf8_fmt_writer out;
@ -189,6 +189,7 @@ public:
protected: protected:
bool is_kicad() const { return m_is_kicad; } bool is_kicad() const { return m_is_kicad; }
void convert_block(const str_list &contents);
void process_line(const pstring &line); void process_line(const pstring &line);
private: private: