summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/prg/nltool.cpp
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2019-04-21 00:35:31 +0200
committer couriersud <couriersud@gmx.org>2019-04-21 12:05:44 +0200
commit7adbce9b667cbf7ca00295ba8e590366d3840dce (patch)
treeda09507795f2433c1abb95e5e34899636ca01f27 /src/lib/netlist/prg/nltool.cpp
parent6b96f7ba60a384ff8d219ad480b9b2dd77e2986e (diff)
netlist: bug fixes and nltool validation.
nltool now supports a validate command which acts similar to MAME's validation.
Diffstat (limited to 'src/lib/netlist/prg/nltool.cpp')
-rw-r--r--src/lib/netlist/prg/nltool.cpp227
1 files changed, 148 insertions, 79 deletions
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 4a1c8ac0315..914e2aaafe4 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -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,28 +133,26 @@ public:
{
}
- plib::unique_ptr<plib::pistream> stream(const pstring &file) override;
+ plib::unique_ptr<plib::pistream> stream(const pstring &file) override
+ {
+ pstring name = m_folder + "/" + file;
+ try
+ {
+ auto strm = plib::make_unique<plib::pifilestream>(name);
+ return std::move(strm);
+ }
+ catch (const plib::pexception &e)
+ {
+ if (dynamic_cast<const plib::file_open_e *>(&e) == nullptr )
+ throw;
+ }
+ return plib::unique_ptr<plib::pistream>(nullptr);
+ }
private:
pstring m_folder;
};
-plib::unique_ptr<plib::pistream> netlist_data_folder_t::stream(const pstring &file)
-{
- pstring name = m_folder + "/" + file;
- try
- {
- auto strm = plib::make_unique<plib::pifilestream>(name);
- return std::move(strm);
- }
- catch (const plib::pexception &e)
- {
- if (dynamic_cast<const plib::file_open_e *>(&e) == nullptr )
- throw;
- }
- return plib::unique_ptr<plib::pistream>(nullptr);
-}
-
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,10 +269,17 @@ 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)
- vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
+ 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)
- {
- vs += ", " + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
- }
+ 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,10 +672,10 @@ 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().warning.set_enabled(false);
+
+ nt.log().verbose.set_enabled(false);
+ 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;