mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
netlist: bug fixes and nltool validation.
nltool now supports a validate command which acts similar to MAME's validation.
This commit is contained in:
parent
6b96f7ba60
commit
7adbce9b66
@ -280,7 +280,8 @@ namespace analog
|
||||
}
|
||||
|
||||
m_vto = m_model.m_VTO;
|
||||
nl_assert_always(m_vto != 0.0, "Threshold voltage not specified for " + m_model.name());
|
||||
if(m_vto != 0.0)
|
||||
log().info("Threshold voltage not specified for {1}", m_model.name());
|
||||
|
||||
/* FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models
|
||||
* specify VTO so skip this here.
|
||||
|
@ -105,7 +105,7 @@ namespace netlist
|
||||
register_subalias("13", m_D.m_OUT);
|
||||
register_subalias("14", m_D.m_RC);
|
||||
register_subalias("15", m_D.m_IN);
|
||||
register_subalias("8", "VSS");
|
||||
register_subalias("16", "VSS");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define NLTOOL_VERSION 20190202
|
||||
#define NLTOOL_VERSION 20190420
|
||||
|
||||
class tool_app_t : public plib::app
|
||||
{
|
||||
@ -25,7 +25,7 @@ public:
|
||||
tool_app_t() :
|
||||
plib::app(),
|
||||
opt_grp1(*this, "General options", "The following options apply to all commands."),
|
||||
opt_cmd (*this, "c", "cmd", 0, std::vector<pstring>({"run","convert","listdevices","static","header","docheader"}), "run|convert|listdevices|static|header|docheader"),
|
||||
opt_cmd (*this, "c", "cmd", 0, std::vector<pstring>({"run","validate","convert","listdevices","static","header","docheader"}), "run|validate|convert|listdevices|static|header|docheader"),
|
||||
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
|
||||
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
|
||||
opt_rfolders(*this, "r", "rom", "where to look for data files"),
|
||||
@ -56,7 +56,10 @@ public:
|
||||
opt_ex2(*this, "nltool --cmd=listdevices",
|
||||
"List all known devices."),
|
||||
opt_ex3(*this, "nltool --cmd=header --tab-width=8 --line-width=80",
|
||||
"Create the header file needed for including netlists as code.")
|
||||
"Create the header file needed for including netlists as code."),
|
||||
|
||||
m_warnings(0),
|
||||
m_errors(0)
|
||||
{}
|
||||
|
||||
plib::option_group opt_grp1;
|
||||
@ -88,12 +91,16 @@ public:
|
||||
int execute() override;
|
||||
pstring usage() override;
|
||||
|
||||
int m_warnings;
|
||||
int m_errors;
|
||||
private:
|
||||
void run();
|
||||
void validate();
|
||||
void convert();
|
||||
void static_compile();
|
||||
|
||||
void mac_out(const pstring &s, const bool cont = true);
|
||||
void cmac(const netlist::factory::element_t *e);
|
||||
void header_entry(const netlist::factory::element_t *e);
|
||||
void mac(const netlist::factory::element_t *e);
|
||||
|
||||
void create_header();
|
||||
@ -126,13 +133,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
plib::unique_ptr<plib::pistream> stream(const pstring &file) override;
|
||||
|
||||
private:
|
||||
pstring m_folder;
|
||||
};
|
||||
|
||||
plib::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &file)
|
||||
plib::unique_ptr<plib::pistream> stream(const pstring &file) override
|
||||
{
|
||||
pstring name = m_folder + "/" + file;
|
||||
try
|
||||
@ -148,6 +149,10 @@ plib::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &fi
|
||||
return plib::unique_ptr<plib::pistream>(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
pstring m_folder;
|
||||
};
|
||||
|
||||
class netlist_tool_callbacks_t : public netlist::callbacks_t
|
||||
{
|
||||
public:
|
||||
@ -196,8 +201,6 @@ public:
|
||||
|
||||
// start devices
|
||||
setup().prepare_to_run();
|
||||
// reset
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void create_dynamic_logs(const std::vector<pstring> &logs)
|
||||
@ -266,11 +269,18 @@ private:
|
||||
void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls) const
|
||||
{
|
||||
pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str());
|
||||
// FIXME: ...
|
||||
m_app.pout("{}", err);
|
||||
if (l == plib::plog_level::WARNING)
|
||||
m_app.m_warnings++;
|
||||
if (l == plib::plog_level::ERROR)
|
||||
m_app.m_errors++;
|
||||
if (l == plib::plog_level::FATAL)
|
||||
{
|
||||
m_app.m_errors++;
|
||||
throw netlist::nl_exception(err);
|
||||
}
|
||||
else
|
||||
m_app.pout("{}", err);
|
||||
}
|
||||
|
||||
struct input_t
|
||||
{
|
||||
@ -346,12 +356,14 @@ void tool_app_t::run()
|
||||
if (!opt_verb())
|
||||
nt.log().verbose.set_enabled(false);
|
||||
if (opt_quiet())
|
||||
nt.log().warning.set_enabled(false);
|
||||
nt.log().info.set_enabled(false);
|
||||
|
||||
nt.read_netlist(opt_file(), opt_name(),
|
||||
opt_logs(),
|
||||
m_options, opt_rfolders());
|
||||
|
||||
nt.reset();
|
||||
|
||||
inps = read_input(nt.setup(), opt_inp());
|
||||
ttr = netlist::netlist_time::from_double(opt_ttr());
|
||||
}
|
||||
@ -416,6 +428,47 @@ void tool_app_t::run()
|
||||
(ttr - nlt).as_double() / emutime * 100.0);
|
||||
}
|
||||
|
||||
void tool_app_t::validate()
|
||||
{
|
||||
std::vector<input_t> inps;
|
||||
netlist::netlist_time ttr;
|
||||
netlist_tool_t nt(*this, "netlist");
|
||||
|
||||
if (!opt_verb())
|
||||
nt.log().verbose.set_enabled(false);
|
||||
if (opt_quiet())
|
||||
nt.log().info.set_enabled(false);
|
||||
|
||||
m_errors = 0;
|
||||
m_warnings = 0;
|
||||
|
||||
nt.setup().enable_validation();
|
||||
|
||||
try
|
||||
{
|
||||
nt.init();
|
||||
|
||||
nt.read_netlist(opt_file(), opt_name(),
|
||||
opt_logs(),
|
||||
m_options, opt_rfolders());
|
||||
}
|
||||
catch (netlist::nl_exception &e)
|
||||
{
|
||||
pout("Netlist exception caught: {}\n", e.text());
|
||||
}
|
||||
catch (plib::pexception &e)
|
||||
{
|
||||
pout("plib exception caught: {}\n", e.text());
|
||||
}
|
||||
|
||||
//pout("Validation warnings: {}\n", m_warnings);
|
||||
//pout("Validation errors: {}\n", m_errors);
|
||||
|
||||
if (m_warnings + m_errors > 0)
|
||||
throw netlist::nl_exception("validation: {1} errors {2} warnings", m_errors, m_warnings);
|
||||
|
||||
}
|
||||
|
||||
void tool_app_t::static_compile()
|
||||
{
|
||||
netlist_tool_t nt(*this, "netlist");
|
||||
@ -423,12 +476,14 @@ void tool_app_t::static_compile()
|
||||
nt.init();
|
||||
|
||||
nt.log().verbose.set_enabled(false);
|
||||
nt.log().warning.set_enabled(false);
|
||||
nt.log().info.set_enabled(false);
|
||||
|
||||
nt.read_netlist(opt_file(), opt_name(),
|
||||
opt_logs(),
|
||||
m_options, opt_rfolders());
|
||||
|
||||
// no reset needed ...
|
||||
|
||||
plib::putf8_writer w(&pout_strm);
|
||||
std::map<pstring, pstring> mp;
|
||||
|
||||
@ -470,20 +525,23 @@ void tool_app_t::mac_out(const pstring &s, const bool cont)
|
||||
pout("{1}\n", s);
|
||||
}
|
||||
|
||||
void tool_app_t::cmac(const netlist::factory::element_t *e)
|
||||
void tool_app_t::header_entry(const netlist::factory::element_t *e)
|
||||
{
|
||||
auto v = plib::psplit(e->param_desc(), ",");
|
||||
pstring vs;
|
||||
for (const auto &s : v)
|
||||
if (!plib::startsWith(s, "@"))
|
||||
vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
|
||||
mac_out("#define " + e->name() + "(name" + vs + ")");
|
||||
mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)");
|
||||
|
||||
for (const auto &s : v)
|
||||
{
|
||||
pstring r(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"));
|
||||
pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@",""));
|
||||
if (plib::startsWith(s, "+"))
|
||||
mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")");
|
||||
else if (plib::startsWith(s, "@"))
|
||||
mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")");
|
||||
else
|
||||
mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")");
|
||||
}
|
||||
@ -495,18 +553,20 @@ void tool_app_t::mac(const netlist::factory::element_t *e)
|
||||
auto v = plib::psplit(e->param_desc(), ",");
|
||||
pstring vs;
|
||||
for (const auto &s : v)
|
||||
{
|
||||
if (!plib::startsWith(s, "@"))
|
||||
vs += ", " + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
|
||||
}
|
||||
|
||||
pout("{1}(name{2})\n", e->name(), vs);
|
||||
if (v.size() > 0)
|
||||
{
|
||||
pout("/*\n");
|
||||
for (const auto &s : v)
|
||||
{
|
||||
pstring r(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"));
|
||||
pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@",""));
|
||||
if (plib::startsWith(s, "+"))
|
||||
pout("{1:10}: Terminal\n",r);
|
||||
else if (plib::startsWith(s, "@"))
|
||||
pout("{1:10}: Power terminal - automatically connected\n", r);
|
||||
else
|
||||
pout("{1:10}: Parameter\n", r);
|
||||
}
|
||||
@ -521,7 +581,7 @@ void tool_app_t::create_header()
|
||||
nt.init();
|
||||
|
||||
nt.log().verbose.set_enabled(false);
|
||||
nt.log().warning.set_enabled(false);
|
||||
nt.log().info.set_enabled(false);
|
||||
|
||||
nt.setup().register_source(plib::make_unique<netlist::source_proc_t>("dummy", &netlist_dummy));
|
||||
nt.setup().include("dummy");
|
||||
@ -550,7 +610,7 @@ void tool_app_t::create_header()
|
||||
pout("{1}{2}\n", pstring("// Source: "), plib::replace_all(e->sourcefile(), "../", ""));
|
||||
pout("{1}\n", plib::rpad(pstring("// "), pstring("-"), opt_linewidth()));
|
||||
}
|
||||
cmac(e.get());
|
||||
header_entry(e.get());
|
||||
}
|
||||
pout("#endif // __PLIB_PREPROCESSOR__\n");
|
||||
pout("#endif\n");
|
||||
@ -565,7 +625,7 @@ void tool_app_t::create_docheader()
|
||||
nt.init();
|
||||
|
||||
nt.log().verbose.set_enabled(false);
|
||||
nt.log().warning.set_enabled(false);
|
||||
nt.log().info.set_enabled(false);
|
||||
|
||||
nt.setup().register_source(plib::make_unique<netlist::source_proc_t>("dummy", &netlist_dummy));
|
||||
nt.setup().include("dummy");
|
||||
@ -594,7 +654,7 @@ void tool_app_t::create_docheader()
|
||||
for (auto &e : nt.setup().factory())
|
||||
{
|
||||
pout("//! [{1} csynopsis]\n", e->name());
|
||||
cmac(e.get());
|
||||
header_entry(e.get());
|
||||
pout("//! [{1} csynopsis]\n", e->name());
|
||||
pout("//! [{1} synopsis]\n", e->name());
|
||||
mac(e.get());
|
||||
@ -612,9 +672,9 @@ void tool_app_t::listdevices()
|
||||
{
|
||||
netlist_tool_t nt(*this, "netlist");
|
||||
nt.init();
|
||||
if (!opt_verb())
|
||||
|
||||
nt.log().verbose.set_enabled(false);
|
||||
if (opt_quiet())
|
||||
nt.log().info.set_enabled(false);
|
||||
nt.log().warning.set_enabled(false);
|
||||
|
||||
netlist::factory::list_t &list = nt.setup().factory();
|
||||
@ -658,7 +718,48 @@ void tool_app_t::listdevices()
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
convert - convert spice et al to netlist
|
||||
-------------------------------------------------*/
|
||||
|
||||
void tool_app_t::convert()
|
||||
{
|
||||
pstring contents;
|
||||
plib::postringstream ostrm;
|
||||
if (opt_file() == "-")
|
||||
{
|
||||
plib::pstdin f;
|
||||
plib::copystream(ostrm, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
plib::pifilestream f(opt_file());
|
||||
plib::copystream(ostrm, f);
|
||||
}
|
||||
contents = ostrm.str();
|
||||
|
||||
pstring result;
|
||||
if (opt_type.as_string() == "spice")
|
||||
{
|
||||
nl_convert_spice_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
else if (opt_type.as_string() == "eagle")
|
||||
{
|
||||
nl_convert_eagle_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
else if (opt_type.as_string() == "rinf")
|
||||
{
|
||||
nl_convert_rinf_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
/* present result */
|
||||
pout.write(result);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
main - primary entry point
|
||||
@ -717,6 +818,8 @@ int tool_app_t::execute()
|
||||
listdevices();
|
||||
else if (cmd == "run")
|
||||
run();
|
||||
else if (cmd == "validate")
|
||||
validate();
|
||||
else if (cmd == "static")
|
||||
static_compile();
|
||||
else if (cmd == "header")
|
||||
@ -724,43 +827,7 @@ int tool_app_t::execute()
|
||||
else if (cmd == "docheader")
|
||||
create_docheader();
|
||||
else if (cmd == "convert")
|
||||
{
|
||||
pstring contents;
|
||||
plib::postringstream ostrm;
|
||||
if (opt_file() == "-")
|
||||
{
|
||||
plib::pstdin f;
|
||||
plib::copystream(ostrm, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
plib::pifilestream f(opt_file());
|
||||
plib::copystream(ostrm, f);
|
||||
}
|
||||
contents = ostrm.str();
|
||||
|
||||
pstring result;
|
||||
if (opt_type.as_string() == "spice")
|
||||
{
|
||||
nl_convert_spice_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
else if (opt_type.as_string() == "eagle")
|
||||
{
|
||||
nl_convert_eagle_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
else if (opt_type.as_string() == "rinf")
|
||||
{
|
||||
nl_convert_rinf_t c;
|
||||
c.convert(contents);
|
||||
result = c.result();
|
||||
}
|
||||
/* present result */
|
||||
pout.write(result);
|
||||
}
|
||||
convert();
|
||||
else
|
||||
{
|
||||
perr("Unknown command {}\n", cmd.c_str());
|
||||
@ -772,10 +839,12 @@ int tool_app_t::execute()
|
||||
catch (netlist::nl_exception &e)
|
||||
{
|
||||
perr("Netlist exception caught: {}\n", e.text());
|
||||
return 2;
|
||||
}
|
||||
catch (plib::pexception &e)
|
||||
{
|
||||
perr("plib exception caught: {}\n", e.text());
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user