netlist: Code symplification and bugfixes. (nw)

- Fixes performance regression and net_splitter struct.
- Fixes nltool time measurements
- pstream simplification
This commit is contained in:
couriersud 2020-01-31 20:23:40 +01:00
parent 72f86082aa
commit 84e3eb1deb
8 changed files with 111 additions and 102 deletions

View File

@ -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);
}

View File

@ -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") + "(";

View File

@ -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;

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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());

View File

@ -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>());

View File

@ -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;
};

View File

@ -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);