summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/prg
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2020-10-09 10:31:51 -0700
committer Aaron Giles <aaron@aarongiles.com>2020-10-09 10:31:51 -0700
commite9c8f1c6d79d7d4bd5e8387f948b8fcf53d2370a (patch)
treecce599858a20cb92adb36d836f0d33f652df3112 /src/lib/netlist/prg
parent63dc4b41edae9a16c81895cccd2d6b9e68002839 (diff)
nltool: Improvements to static solver generation:nltool-updates
* sort entries by module/hash to produce more stable output * add --split option to split the code for each module (not enabled for now)
Diffstat (limited to 'src/lib/netlist/prg')
-rw-r--r--src/lib/netlist/prg/nltool.cpp75
1 files changed, 65 insertions, 10 deletions
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 21f1f0725fa..c85413e0441 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -65,7 +65,8 @@ public:
opt_grp3(*this, "Options for static command", "These options apply to static command."),
opt_dir(*this, "d", "dir", "", "output directory for the generated files."),
- opt_out(*this, "o", "output", "", "single output file for the generated code.\nEither --dir or --output can be specificied"),
+ opt_out(*this, "o", "output", "", "single output file for the generated code.\nEither --dir or --output can be specified"),
+ opt_split(*this, "s", "split", "split the generated output into files by source"),
opt_grp4(*this, "Options for run command", "These options are only used by the run command."),
opt_ttr (*this, "t", "time_to_run", 1, "time to run the emulation (seconds)"),
@@ -137,6 +138,7 @@ private:
plib::option_group opt_grp3;
plib::option_str opt_dir;
plib::option_str opt_out;
+ plib::option_bool opt_split;
plib::option_group opt_grp4;
plib::option_num<netlist::nl_fptype> opt_ttr;
@@ -164,10 +166,11 @@ private:
struct compile_map_entry
{
- compile_map_entry(const pstring &mod, const pstring &code)
- : m_module(mod), m_code(code) { }
+ compile_map_entry(const pstring &mod, const pstring &code, const pstring &hash)
+ : m_module(mod), m_code(code), m_hash(hash) { }
pstring m_module;
pstring m_code;
+ pstring m_hash;
};
using compile_map = std::map<pstring, compile_map_entry>;
@@ -596,7 +599,7 @@ void tool_app_t::compile_one_and_add_to_map(const pstring &file,
{
auto it = map.find(e.first);
if (it == map.end())
- map.insert({e.first, compile_map_entry(name, e.second)});
+ map.insert({e.first, compile_map_entry(name, e.second, e.first)});
else
{
if (it->second.m_code != e.second)
@@ -685,25 +688,77 @@ void tool_app_t::static_compile()
compile_one_and_add_to_map(f, name, target, map);
}
}
+
+ std::vector<compile_map_entry *> sorted;
+ for (auto &e : map)
+ sorted.push_back(&e.second);
+
+ std::sort(sorted.begin(), sorted.end(),
+ [](compile_map_entry *a, compile_map_entry *b) -> bool
+ {
+ return (a->m_module < b->m_module) || (a->m_module == b->m_module && a->m_hash < b->m_hash);
+ });
+
+ std::vector<pstring> split_include_list;
+ if (opt_split())
+ {
+ // I'm sure the filename manipulation can be made better
+ char dirsep = (opt_out().find('\\') != pstring::npos) ? '\\' : '/';
+ std::vector<pstring> dirparts = plib::psplit(opt_out(), dirsep);
+ pstring basedir;
+ for (int i = 0; i < dirparts.size() - 1; i++)
+ basedir += dirparts[i] + dirsep;
+
+ std::vector<pstring> nameparts = plib::psplit(dirparts[dirparts.size() - 1], '.');
+ pstring basename = nameparts[0];
+
+ plib::ofstream *curout = nullptr;
+ pstring prev_module;
+ for (auto e : sorted)
+ {
+ if (e->m_module != prev_module)
+ {
+ delete curout;
+ pstring filename = basename + "_" + e->m_module + ".hpp";
+ split_include_list.push_back(filename);
+ curout = new plib::ofstream(basedir + filename);
+ if (curout->fail())
+ throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(basedir + filename));
+ prev_module = e->m_module;
+ }
+ *curout << putf8string(e->m_code);
+ }
+ delete curout;
+ }
+
plib::ofstream sout(opt_out());
if (sout.fail())
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(opt_out()));
sout << "#include \"plib/pdynlib.h\"\n\n";
sout << "#if !defined(__EMSCRIPTEN__)\n\n";
- for (auto &e : map)
+ pstring prev_module;
+ if (opt_split())
{
- sout << "// " << putf8string(e.second.m_module) << "\n";
- sout << putf8string(e.second.m_code);
+ for (auto &e : split_include_list)
+ sout << "#include \"" << e << "\"\n";
+ }
+ else
+ {
+ for (auto e : sorted)
+ {
+ sout << "// " << putf8string(e->m_module) << "\n";
+ sout << putf8string(e->m_code);
+ }
}
sout << "#endif\n\n";
sout << "extern const plib::dynlib_static_sym nl_static_solver_syms[];\n";
sout << "const plib::dynlib_static_sym nl_static_solver_syms[] = {\n";
sout << "#if !defined(__EMSCRIPTEN__)\n\n";
- for (auto &e : map)
+ for (auto e : sorted)
{
- sout << "// " << putf8string(e.second.m_module) << "\n";
- sout << "\t{\"" << putf8string(e.first) << "\", reinterpret_cast<void *>(&" << putf8string(e.first) << ")}, // NOLINT\n";
+ sout << "// " << putf8string(e->m_module) << "\n";
+ sout << "\t{\"" << putf8string(e->m_hash) << "\", reinterpret_cast<void *>(&" << putf8string(e->m_hash) << ")}, // NOLINT\n";
}
sout << "#endif\n\n";
sout << "{\"\", nullptr}\n";