mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
netlist: Code symplification and bugfixes. (nw)
- Fixes performance regression and net_splitter struct. - Fixes nltool time measurements - pstream simplification
This commit is contained in:
parent
72f86082aa
commit
84e3eb1deb
@ -149,6 +149,15 @@ namespace analog
|
||||
, nlconst::magic(300.0));
|
||||
}
|
||||
|
||||
// Basic math
|
||||
//
|
||||
// I(V) = f(V)
|
||||
//
|
||||
// G(V) = df/dV(V)
|
||||
//
|
||||
// Ieq(V) = I(V) - V * G(V)
|
||||
//
|
||||
//
|
||||
void update_diode(nl_fptype nVd) noexcept
|
||||
{
|
||||
if (TYPE == diode_e::BIPOLAR)
|
||||
@ -163,11 +172,9 @@ namespace analog
|
||||
const nl_fptype d = std::min(+fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd - old);
|
||||
const nl_fptype a = plib::abs(d) * m_VtInv;
|
||||
m_Vd = old + nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(a) * m_Vt;
|
||||
//printf("new VD: %g\n", (nl_fptype)m_Vd);
|
||||
}
|
||||
else
|
||||
m_Vd = std::max(-fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd);
|
||||
//m_Vd = nVd;
|
||||
|
||||
if (m_Vd < m_Vmin)
|
||||
{
|
||||
@ -183,15 +190,14 @@ namespace analog
|
||||
}
|
||||
else if (TYPE == diode_e::MOS)
|
||||
{
|
||||
m_Vd = nVd;
|
||||
if (nVd < nlconst::zero())
|
||||
{
|
||||
m_Vd = nVd;
|
||||
m_G = m_Is * m_VtInv + m_gmin;
|
||||
m_Id = m_G * m_Vd;
|
||||
}
|
||||
else // log stepping should already be done in mosfet
|
||||
{
|
||||
m_Vd = nVd;
|
||||
const auto IseVDVt = plib::exp(std::min(+fp_constants<nl_fptype>::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv));
|
||||
m_Id = IseVDVt - m_Is;
|
||||
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||
@ -209,9 +215,9 @@ namespace analog
|
||||
|
||||
m_Vmin = nlconst::magic(-5.0) * m_Vt;
|
||||
|
||||
// Vcrit : f(V) has smallest radius of curvature rho(V) == min(rho(v))
|
||||
m_Vcrit = m_Vt * plib::log(m_Vt / m_Is / nlconst::sqrt2());
|
||||
m_VtInv = plib::reciprocal(m_Vt);
|
||||
//printf("%g %g\n", m_Vmin, m_Vcrit);
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,9 +313,9 @@ namespace netlist
|
||||
|
||||
bool nlparse_t::parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name)
|
||||
{
|
||||
plib::ppreprocessor y(m_includes, &m_defines);
|
||||
plib::ppreprocessor &x(y.process(std::move(istrm)));
|
||||
return parser_t(std::move(x), *this).parse(name);
|
||||
auto y = plib::make_unique<plib::ppreprocessor>(m_includes, &m_defines);
|
||||
y->process(std::move(istrm));
|
||||
return parser_t(std::move(y), *this).parse(name);
|
||||
//return parser_t(std::move(plib::ppreprocessor(&m_defines).process(std::move(istrm))), *this).parse(name);
|
||||
}
|
||||
|
||||
@ -1057,7 +1057,7 @@ void models_t::model_parse(const pstring &model_in, model_map_t &map)
|
||||
}
|
||||
}
|
||||
|
||||
pstring models_t::model_string(const model_map_t &map) const
|
||||
pstring models_t::model_string(const model_map_t &map)
|
||||
{
|
||||
// operator [] has no const implementation
|
||||
pstring ret = map.at("COREMODEL") + "(";
|
||||
|
@ -224,7 +224,7 @@ namespace netlist
|
||||
using model_map_t = std::unordered_map<pstring, pstring>;
|
||||
|
||||
void model_parse(const pstring &model, model_map_t &map);
|
||||
pstring model_string(const model_map_t &map) const;
|
||||
static pstring model_string(const model_map_t &map);
|
||||
|
||||
std::unordered_map<pstring, pstring> m_models;
|
||||
std::unordered_map<pstring, model_map_t> m_cache;
|
||||
|
@ -26,12 +26,6 @@
|
||||
|
||||
namespace plib {
|
||||
|
||||
template <typename T>
|
||||
struct constructor_helper
|
||||
{
|
||||
plib::unique_ptr<std::istream> operator()(T &&s) { return std::move(plib::make_unique<T>(std::move(s))); }
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief: putf8reader_t: reader on top of istream.
|
||||
///
|
||||
@ -43,17 +37,24 @@ class putf8_reader
|
||||
public:
|
||||
|
||||
COPYASSIGN(putf8_reader, delete)
|
||||
putf8_reader &operator=(putf8_reader &&src) = delete;
|
||||
virtual ~putf8_reader() = default;
|
||||
|
||||
template <typename T>
|
||||
friend struct constructor_helper;
|
||||
putf8_reader(putf8_reader &&rhs)
|
||||
: m_strm(std::move(rhs.m_strm))
|
||||
, m_linebuf(std::move(rhs.m_linebuf))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
putf8_reader(T &&strm) // NOLINT(cppcoreguidelines-special-member-functions, misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
|
||||
: m_strm(std::move(constructor_helper<T>()(std::move(strm)))) // NOLINT(bugprone-move-forwarding-reference)
|
||||
putf8_reader(plib::unique_ptr<std::istream> &&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 readline(pstring &line)
|
||||
@ -111,19 +112,6 @@ private:
|
||||
putf8string m_linebuf;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct constructor_helper<putf8_reader>
|
||||
{
|
||||
plib::unique_ptr<std::istream> operator()(putf8_reader &&s) const { return std::move(s.m_strm); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct constructor_helper<plib::unique_ptr<std::istream>>
|
||||
{
|
||||
plib::unique_ptr<std::istream> operator()(plib::unique_ptr<std::istream> &&s) const { return std::move(s); }
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// putf8writer_t: writer on top of ostream
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -368,7 +368,7 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstr
|
||||
std::vector<input_t> ret;
|
||||
if (fname != "")
|
||||
{
|
||||
plib::putf8_reader r = plib::putf8_reader(std::ifstream(plib::filesystem::u8path(fname)));
|
||||
plib::putf8_reader r = plib::putf8_reader(plib::make_unique<std::ifstream>(plib::filesystem::u8path(fname)));
|
||||
if (r.stream().fail())
|
||||
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(fname));
|
||||
r.stream().imbue(std::locale::classic());
|
||||
@ -416,28 +416,31 @@ void tool_app_t::run()
|
||||
|
||||
pout("startup time ==> {1:5.3f}\n", t.as_seconds<nl_fptype>() );
|
||||
|
||||
// FIXME: error handling
|
||||
if (opt_loadstate.was_specified())
|
||||
{
|
||||
std::ifstream strm(plib::filesystem::u8path(opt_loadstate()));
|
||||
if (strm.fail())
|
||||
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(opt_loadstate()));
|
||||
strm.imbue(std::locale::classic());
|
||||
plib::pbinary_reader reader(strm);
|
||||
std::vector<char> loadstate;
|
||||
reader.read(loadstate);
|
||||
nt.load_state(loadstate);
|
||||
pout("Loaded state, run will continue at {1:.6f}\n", nt.exec().time().as_double());
|
||||
}
|
||||
|
||||
t.reset();
|
||||
|
||||
netlist::netlist_time_ext nlt = nt.exec().time();
|
||||
netlist::netlist_time_ext nlstart = nt.exec().time();
|
||||
{
|
||||
auto t_guard(t.guard());
|
||||
|
||||
// FIXME: error handling
|
||||
if (opt_loadstate.was_specified())
|
||||
{
|
||||
std::ifstream strm(plib::filesystem::u8path(opt_loadstate()));
|
||||
if (strm.fail())
|
||||
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(opt_loadstate()));
|
||||
strm.imbue(std::locale::classic());
|
||||
plib::pbinary_reader reader(strm);
|
||||
std::vector<char> loadstate;
|
||||
reader.read(loadstate);
|
||||
nt.load_state(loadstate);
|
||||
pout("Loaded state, run will continue at {1:.6f}\n", nt.exec().time().as_double());
|
||||
}
|
||||
pout("runnning ...\n");
|
||||
|
||||
unsigned pos = 0;
|
||||
|
||||
netlist::netlist_time_ext nlt = nlstart;
|
||||
|
||||
while (pos < inps.size()
|
||||
&& inps[pos].m_time < ttr
|
||||
@ -449,8 +452,6 @@ void tool_app_t::run()
|
||||
pos++;
|
||||
}
|
||||
|
||||
pout("runnning ...\n");
|
||||
|
||||
if (ttr > nlt)
|
||||
nt.exec().process_queue(ttr - nlt);
|
||||
else
|
||||
@ -460,24 +461,25 @@ void tool_app_t::run()
|
||||
ttr = nlt;
|
||||
}
|
||||
|
||||
if (opt_savestate.was_specified())
|
||||
{
|
||||
auto savestate = nt.save_state();
|
||||
std::ofstream strm(plib::filesystem::u8path(opt_savestate()), std::ios_base::binary);
|
||||
if (strm.fail())
|
||||
throw plib::file_open_e(opt_savestate());
|
||||
strm.imbue(std::locale::classic());
|
||||
|
||||
plib::pbinary_writer writer(strm);
|
||||
writer.write(savestate);
|
||||
}
|
||||
nt.exec().stop();
|
||||
}
|
||||
|
||||
if (opt_savestate.was_specified())
|
||||
{
|
||||
auto savestate = nt.save_state();
|
||||
std::ofstream strm(plib::filesystem::u8path(opt_savestate()), std::ios_base::binary);
|
||||
if (strm.fail())
|
||||
throw plib::file_open_e(opt_savestate());
|
||||
strm.imbue(std::locale::classic());
|
||||
|
||||
plib::pbinary_writer writer(strm);
|
||||
writer.write(savestate);
|
||||
}
|
||||
nt.exec().stop();
|
||||
|
||||
auto emutime(t.as_seconds<nl_fptype>());
|
||||
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n",
|
||||
(ttr - nlt).as_fp<nl_fptype>(), emutime,
|
||||
(ttr - nlt).as_fp<nl_fptype>() / emutime * netlist::nlconst::magic(100.0));
|
||||
(ttr - nlstart).as_fp<nl_fptype>(), emutime,
|
||||
(ttr - nlstart).as_fp<nl_fptype>() / emutime * netlist::nlconst::magic(100.0));
|
||||
}
|
||||
|
||||
void tool_app_t::validate()
|
||||
@ -578,7 +580,7 @@ struct doc_ext
|
||||
static doc_ext read_docsrc(const pstring &fname, const pstring &id)
|
||||
{
|
||||
//printf("file %s\n", fname.c_str());
|
||||
plib::putf8_reader r = plib::putf8_reader(std::ifstream(plib::filesystem::u8path(fname)));
|
||||
plib::putf8_reader r = plib::putf8_reader(plib::make_unique<std::ifstream>(plib::filesystem::u8path(fname)));
|
||||
if (r.stream().fail())
|
||||
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(fname));
|
||||
r.stream().imbue(std::locale::classic());
|
||||
|
@ -138,6 +138,7 @@ public:
|
||||
|
||||
bool readmore(std::vector<plib::putf8_reader> &r)
|
||||
{
|
||||
fprintf(stderr, "%d %d\n", (int) m_e.size(), (int) r.size());
|
||||
bool success = false;
|
||||
for (std::size_t i = 0; i< r.size(); i++)
|
||||
{
|
||||
@ -145,11 +146,13 @@ public:
|
||||
{
|
||||
pstring line;
|
||||
m_e[i].eof = !r[i].readline(line);
|
||||
//fprintf(stderr, "bla: <%s>\n", line.c_str());
|
||||
if (!m_e[i].eof)
|
||||
{
|
||||
// sscanf is very fast ...
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
||||
std::sscanf(line.c_str(), "%lf %lf", &m_e[i].t, &m_e[i].v);
|
||||
if (2 != std::sscanf(line.c_str(), "%lf %lf", &m_e[i].t, &m_e[i].v))
|
||||
fprintf(stderr, "arg: <%s>\n", line.c_str());
|
||||
m_e[i].need_more = false;
|
||||
}
|
||||
}
|
||||
@ -515,7 +518,7 @@ int nlwav_app::execute()
|
||||
for (auto &oi: opt_args())
|
||||
{
|
||||
plib::unique_ptr<std::istream> fin;
|
||||
|
||||
printf("%s\n", oi.c_str());
|
||||
if (oi == "-")
|
||||
{
|
||||
auto temp(plib::make_unique<std::stringstream>());
|
||||
|
@ -252,8 +252,45 @@ namespace devices
|
||||
|
||||
struct net_splitter
|
||||
{
|
||||
void run(netlist_state_t &netlist)
|
||||
{
|
||||
for (auto & net : netlist.nets())
|
||||
{
|
||||
netlist.log().verbose("processing {1}", net->name());
|
||||
if (!net->isRailNet() && net->num_cons() > 0)
|
||||
{
|
||||
netlist.log().verbose(" ==> not a rail net");
|
||||
// Must be an analog net
|
||||
auto &n = *static_cast<analog_net_t *>(net.get());
|
||||
if (!already_processed(n))
|
||||
{
|
||||
groupspre.emplace_back(analog_net_t::list_t());
|
||||
process_net(netlist, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &g : groupspre)
|
||||
if (!g.empty())
|
||||
groups.push_back(g);
|
||||
}
|
||||
|
||||
bool already_processed(const analog_net_t &n)
|
||||
std::vector<analog_net_t::list_t> groups;
|
||||
|
||||
private:
|
||||
|
||||
bool already_processed(const analog_net_t &n) const
|
||||
{
|
||||
// no need to process rail nets - these are known variables
|
||||
if (n.isRailNet())
|
||||
return true;
|
||||
// if it's already processed - no need to continue
|
||||
for (auto & grp : groups)
|
||||
if (plib::container::contains(grp, &n))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_if_processed_and_join(const analog_net_t &n)
|
||||
{
|
||||
// no need to process rail nets - these are known variables
|
||||
if (n.isRailNet())
|
||||
@ -297,41 +334,14 @@ namespace devices
|
||||
{
|
||||
auto *pt = static_cast<terminal_t *>(term);
|
||||
// check the connected terminal
|
||||
// analog_net_t &connected_net = pt->connected_terminal()->net();
|
||||
analog_net_t &connected_net = netlist.setup().get_connected_terminal(*pt)->net();
|
||||
netlist.log().verbose(" Connected net {}", connected_net.name());
|
||||
if (!already_processed(connected_net))
|
||||
if (!check_if_processed_and_join(connected_net))
|
||||
process_net(netlist, connected_net);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run(netlist_state_t &netlist)
|
||||
{
|
||||
for (auto & net : netlist.nets())
|
||||
{
|
||||
netlist.log().debug("processing {1}", net->name());
|
||||
netlist.log().verbose("processing {1}", net->name());
|
||||
if (!net->isRailNet() && net->num_cons() > 0)
|
||||
{
|
||||
netlist.log().debug(" ==> not a rail net");
|
||||
netlist.log().verbose(" ==> not a rail net");
|
||||
// Must be an analog net
|
||||
auto &n = *static_cast<analog_net_t *>(net.get());
|
||||
if (!already_processed(n))
|
||||
{
|
||||
groupspre.emplace_back(analog_net_t::list_t());
|
||||
process_net(netlist, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &g : groupspre)
|
||||
if (!g.empty())
|
||||
groups.push_back(g);
|
||||
}
|
||||
|
||||
std::vector<analog_net_t::list_t> groups;
|
||||
private:
|
||||
std::vector<analog_net_t::list_t> groupspre;
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ using lib_map_t = std::unordered_map<pstring, lib_map_entry>;
|
||||
|
||||
static lib_map_t read_lib_map(const pstring &lm)
|
||||
{
|
||||
auto reader = plib::putf8_reader(std::istringstream(lm));
|
||||
auto reader = plib::putf8_reader(plib::make_unique<std::istringstream>(lm));
|
||||
reader.stream().imbue(std::locale::classic());
|
||||
lib_map_t m;
|
||||
pstring line;
|
||||
@ -653,7 +653,7 @@ void nl_convert_eagle_t::tokenizer::verror(const pstring &msg)
|
||||
void nl_convert_eagle_t::convert(const pstring &contents)
|
||||
{
|
||||
|
||||
tokenizer tok(*this, plib::putf8_reader(std::istringstream(contents)));
|
||||
tokenizer tok(*this, plib::putf8_reader(plib::make_unique<std::istringstream>(contents)));
|
||||
tok.stream().stream().imbue(std::locale::classic());
|
||||
|
||||
out("NETLIST_START(dummy)\n");
|
||||
@ -800,7 +800,7 @@ void nl_convert_rinf_t::tokenizer::verror(const pstring &msg)
|
||||
|
||||
void nl_convert_rinf_t::convert(const pstring &contents)
|
||||
{
|
||||
tokenizer tok(*this, plib::putf8_reader(std::istringstream(contents)));
|
||||
tokenizer tok(*this, plib::putf8_reader(plib::make_unique<std::istringstream>(contents)));
|
||||
tok.stream().stream().imbue(std::locale::classic());
|
||||
auto lm = read_lib_map(s_lib_map);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user