netlist: spice-to-netlis conversion sync with mame/discrete. (nw)

This is work in progress. The aim is to remove all hacks in netlist
conversion going forward.
This commit is contained in:
couriersud 2020-02-02 02:23:16 +01:00
parent 2a07d19872
commit 4c7e687f5e
2 changed files with 58 additions and 22 deletions

View File

@ -91,6 +91,8 @@ nl_convert_base_t::nl_convert_base_t()
{ "CCCS", {"OP", "ON", "IP", "IN"} }, { "CCCS", {"OP", "ON", "IP", "IN"} },
{ "CCVS", {"OP", "ON", "IP", "IN"} }, { "CCVS", {"OP", "ON", "IP", "IN"} },
{ "VS", {"1", "2"} }, { "VS", {"1", "2"} },
{ "TTL_INPUT", {"Q", "VCC", "GND"} },
{ "DIODE", {"A", "K"} },
}; };
} }
@ -138,6 +140,10 @@ void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname) void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname)
{ {
// Ignore NC nets!
if (plib::startsWith(netname,"NC_"))
return;
net_t * net = nullptr; net_t * net = nullptr;
auto idx = m_nets.find(netname); auto idx = m_nets.find(netname);
if (idx != m_nets.end()) if (idx != m_nets.end())
@ -254,7 +260,7 @@ void nl_convert_base_t::dump_nl()
for (auto & i : m_nets) for (auto & i : m_nets)
{ {
net_t * net = i.second.get(); net_t * net = i.second.get();
if (!net->is_no_export()) 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].c_str() );
for (std::size_t j=1; j<net->terminals().size(); j++) for (std::size_t j=1; j<net->terminals().size(); j++)
@ -276,8 +282,16 @@ pstring nl_convert_base_t::get_nl_val(double val)
for (auto &e : m_units) for (auto &e : m_units)
{ {
if (e.m_mult <= plib::abs(val)) if (e.m_mult <= plib::abs(val))
return plib::pfmt(e.m_func)(val / e.m_mult); {
double v = val / e.m_mult;
if (plib::abs(v - std::round(v)) <= 1e-6)
return plib::pfmt(e.m_func)(static_cast<int>(std::round(v)));
return plib::pfmt(e.m_func)(v);
} }
}
if (plib::abs(val - std::round(val)) <= 1e-6)
return plib::pfmt("{1}")(static_cast<int>(std::round(val)));
return plib::pfmt("{1}")(val); return plib::pfmt("{1}")(val);
} }
@ -334,6 +348,7 @@ void nl_convert_spice_t::convert(const pstring &contents)
// FIXME: Parameter // FIXME: Parameter
out("NETLIST_START(dummy)\n"); out("NETLIST_START(dummy)\n");
add_term("0", "GND"); add_term("0", "GND");
add_term("GND", "GND"); // For Kicad
pstring line = ""; pstring line = "";
@ -412,6 +427,10 @@ void nl_convert_spice_t::process_line(const pstring &line)
{ {
out("NET_MODEL(\"{} {}\")\n", m_subckt + tt[1], rem(tt,2)); out("NET_MODEL(\"{} {}\")\n", m_subckt + tt[1], rem(tt,2));
} }
else if (tt[0] == ".TITLE" && tt[1] == "KICAD")
{
m_is_kicad = true;
}
else else
out("// {}\n", line.c_str()); out("// {}\n", line.c_str());
break; break;
@ -572,16 +591,6 @@ void nl_convert_spice_t::process_line(const pstring &line)
add_term(tt[1], tt[0] + ".1"); add_term(tt[1], tt[0] + ".1");
add_term(tt[2], tt[0] + ".2"); add_term(tt[2], tt[0] + ".2");
break; 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': case 'I':
{ {
val = get_sp_val(tt[3] == "DC" ? tt[4] : tt[3]); val = get_sp_val(tt[3] == "DC" ? tt[4] : tt[3]);
@ -590,13 +599,12 @@ void nl_convert_spice_t::process_line(const pstring &line)
add_term(tt[2], tt[0] + ".2"); add_term(tt[2], tt[0] + ".2");
} }
break; break;
#endif
case 'D': case 'D':
add_device("DIODE", tt[0], m_subckt + tt[3]); add_device("DIODE", tt[0], m_subckt + tt[3]);
// Spice D Anode Kathode model // Spice D Anode Kathode model
// FIXME ==> does Kicad use different notation from LTSPICE ? // Kicad outputs K first and D as second net
add_term(tt[1], tt[0] + ".A"); add_term(tt[1], tt[0], is_kicad() ? 1 : 0);
add_term(tt[2], tt[0] + ".K"); add_term(tt[2], tt[0], is_kicad() ? 0 : 1);
break; break;
case 'U': case 'U':
case 'X': case 'X':
@ -606,15 +614,44 @@ void nl_convert_spice_t::process_line(const pstring &line)
// FIXME: Parameter // FIXME: Parameter
pstring xname = plib::replace_all(tt[0], pstring("."), pstring("_")); pstring xname = plib::replace_all(tt[0], pstring("."), pstring("_"));
pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP"; pstring modname = tt[tt.size()-1];
pstring tname = modname;
if (plib::startsWith(modname, "7"))
tname = "TTL_" + modname + "_DIP";
else if (plib::startsWith(modname, "4"))
tname = "CD" + modname + "_DIP";
add_device(tname, xname); add_device(tname, xname);
for (std::size_t i=1; i < tt.size() - 1; i++) for (std::size_t i=1; i < tt.size() - 1; i++)
{ {
pstring term = plib::pfmt("{1}.{2}")(xname)(i); pstring term = plib::pfmt("X{1}.{2}")(xname)(i);
add_term(tt[i], term); add_term(tt[i], term);
} }
break; break;
} }
case 'Y':
{
auto st=tt[0].substr(0,3);
if (st == "YT_")
{
auto yname=pstring("I_") + tt[0].substr(3);
val = get_sp_val(tt[4]);
add_device("TTL_INPUT", yname, val);
add_term(tt[1], yname, 0);
add_term(tt[2], yname, 1);
add_term(tt[3], yname, 2);
}
else if (st == "YA_")
{
auto yname=pstring("I_") + tt[0].substr(3);
val = get_sp_val(tt[2]);
add_device("ANALOG_INPUT", yname, val);
add_term(tt[1], yname + ".Q");
}
else
out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str());
break;
}
default: default:
out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str()); out("// IGNORED {}: {}\n", tt[0].c_str(), line.c_str());
} }

View File

@ -155,9 +155,6 @@ private:
pstring m_alias; pstring m_alias;
}; };
private:
void add_device(plib::unique_ptr<dev_t> dev); void add_device(plib::unique_ptr<dev_t> dev);
dev_t *get_device(const pstring &name) dev_t *get_device(const pstring &name)
{ {
@ -185,16 +182,18 @@ class nl_convert_spice_t : public nl_convert_base_t
{ {
public: public:
nl_convert_spice_t() = default; nl_convert_spice_t() : m_is_kicad(false) { }
void convert(const pstring &contents) override; void convert(const pstring &contents) override;
protected: protected:
bool is_kicad() const { return m_is_kicad; }
void process_line(const pstring &line); void process_line(const pstring &line);
private: private:
pstring m_subckt; pstring m_subckt;
bool m_is_kicad;
}; };
class nl_convert_eagle_t : public nl_convert_base_t class nl_convert_eagle_t : public nl_convert_base_t