diff options
author | 2019-11-13 07:41:20 +0100 | |
---|---|---|
committer | 2019-11-13 07:41:20 +0100 | |
commit | f4cf0cc86a06f07f4df18fbf521abf3126721d24 (patch) | |
tree | 49d760d161a5a3c981f7ab02c39e6101a535b92c | |
parent | 6a57025550e2898954fe10b5796ad55513a21049 (diff) |
netlist: code maintenance. (nw)
- move memory pool to netlist_state_t removing one static allocation.
- add memory allocation stats to verbose output
- nl_assert no longer throws, first step to remove NL_EXCEPT macro.
-rw-r--r-- | src/devices/machine/netlist.cpp | 134 | ||||
-rw-r--r-- | src/devices/machine/netlist.h | 6 | ||||
-rw-r--r-- | src/lib/netlist/analog/nld_mosfet.cpp | 6 | ||||
-rw-r--r-- | src/lib/netlist/devices/nlid_proxy.cpp | 10 | ||||
-rw-r--r-- | src/lib/netlist/devices/nlid_system.h | 6 | ||||
-rw-r--r-- | src/lib/netlist/devices/nlid_truthtable.cpp | 10 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.cpp | 71 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.h | 77 | ||||
-rw-r--r-- | src/lib/netlist/nl_factory.cpp | 4 | ||||
-rw-r--r-- | src/lib/netlist/nl_factory.h | 15 | ||||
-rw-r--r-- | src/lib/netlist/nl_setup.cpp | 12 | ||||
-rw-r--r-- | src/lib/netlist/nltypes.h | 6 | ||||
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 18 | ||||
-rw-r--r-- | src/lib/netlist/plib/pconfig.h | 4 | ||||
-rw-r--r-- | src/lib/netlist/plib/pexception.cpp | 27 | ||||
-rw-r--r-- | src/lib/netlist/plib/pexception.h | 11 | ||||
-rw-r--r-- | src/lib/netlist/plib/pmempool.h | 167 | ||||
-rw-r--r-- | src/lib/netlist/plib/pstate.h | 46 | ||||
-rw-r--r-- | src/lib/netlist/prg/nltool.cpp | 56 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_matrix_solver.cpp | 3 |
20 files changed, 392 insertions, 297 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 543a56faf33..8091438823b 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -137,18 +137,18 @@ private: }; -class netlist_mame_device::netlist_mame_t : public netlist::netlist_t +class netlist_mame_device::netlist_mame_t : public netlist::netlist_state_t { public: netlist_mame_t(netlist_mame_device &parent, const pstring &aname) - : netlist::netlist_t(aname, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t>(parent)) + : netlist::netlist_state_t(aname, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t>(parent)) , m_parent(parent) { } netlist_mame_t(netlist_mame_device &parent, const pstring &aname, plib::unique_ptr<netlist::callbacks_t> cbs) - : netlist::netlist_t(aname, std::move(cbs)) + : netlist::netlist_state_t(aname, std::move(cbs)) , m_parent(parent) { } @@ -176,7 +176,7 @@ public: , m_cpu_device(nullptr) , m_last(*this, "m_last", 0) { - auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&exec()); + auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&state()); if (nl != nullptr) m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent()); } @@ -226,7 +226,7 @@ public: , m_cpu_device(nullptr) , m_last(*this, "m_last", 0) { - auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&exec()); + auto *nl = dynamic_cast<netlist_mame_device::netlist_mame_t *>(&state()); if (nl != nullptr) m_cpu_device = downcast<netlist_mame_cpu_device *>(&nl->parent()); } @@ -503,9 +503,9 @@ public: for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { - m_channels[i].m_param_name = netlist::pool().make_unique<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), ""); - m_channels[i].m_param_mult = netlist::pool().make_unique<netlist::param_fp_t>(*this, plib::pfmt("MULT{1}")(i), 1.0); - m_channels[i].m_param_offset = netlist::pool().make_unique<netlist::param_fp_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0); + m_channels[i].m_param_name = anetlist.make_object<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), ""); + m_channels[i].m_param_mult = anetlist.make_object<netlist::param_fp_t>(*this, plib::pfmt("MULT{1}")(i), 1.0); + m_channels[i].m_param_offset = anetlist.make_object<netlist::param_fp_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0); } } @@ -589,7 +589,7 @@ netlist::setup_t &netlist_mame_device::setup() { if (!m_netlist) throw device_missing_dependencies(); - return m_netlist->nlstate().setup(); + return m_netlist->setup(); } void netlist_mame_device::register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name) @@ -739,7 +739,7 @@ void netlist_mame_analog_output_device::custom_netlist_additions(netlist::netlis if (owner()->has_running_machine()) m_delegate.resolve(); - auto dev = netlist::pool().make_unique<NETLIB_NAME(analog_callback)>(nlstate, dfqn); + auto dev = nlstate.make_object<NETLIB_NAME(analog_callback)>(nlstate, dfqn); //static_cast<NETLIB_NAME(analog_callback) *>(dev.get())->register_callback(std::move(m_delegate)); dev->register_callback(std::move(m_delegate)); nlstate.register_device(dfqn, std::move(dev)); @@ -774,7 +774,7 @@ void netlist_mame_logic_output_device::custom_netlist_additions(netlist::netlist if (owner()->has_running_machine()) m_delegate.resolve(); - auto dev = netlist::pool().make_unique<NETLIB_NAME(logic_callback)>(nlstate, dfqn); + auto dev = nlstate.make_object<NETLIB_NAME(logic_callback)>(nlstate, dfqn); dev->register_callback(std::move(m_delegate)); nlstate.register_device(dfqn, std::move(dev)); nlstate.setup().register_link(dname + ".IN", pin); @@ -1027,9 +1027,9 @@ void netlist_mame_device::device_config_complete() } -void netlist_mame_device::common_dev_start(netlist::netlist_t *lnetlist) const +void netlist_mame_device::common_dev_start(netlist::netlist_state_t *lnetlist) const { - auto &lsetup = lnetlist->nlstate().setup(); + auto &lsetup = lnetlist->setup(); // Override log statistics pstring p = plib::util::environment("NL_STATS", ""); @@ -1040,7 +1040,7 @@ void netlist_mame_device::common_dev_start(netlist::netlist_t *lnetlist) const if (err) lsetup.log().warning("NL_STATS: invalid value {1}", p); else - lnetlist->enable_stats(v); + lnetlist->exec().enable_stats(v); } // register additional devices @@ -1054,7 +1054,7 @@ void netlist_mame_device::common_dev_start(netlist::netlist_t *lnetlist) const if( sdev != nullptr ) { LOGDEVCALLS("Preparse subdevice %s/%s\n", d.name(), d.shortname()); - sdev->pre_parse_action(lnetlist->nlstate()); + sdev->pre_parse_action(*lnetlist); } } @@ -1072,21 +1072,21 @@ void netlist_mame_device::common_dev_start(netlist::netlist_t *lnetlist) const if( sdev != nullptr ) { LOGDEVCALLS("Found subdevice %s/%s\n", d.name(), d.shortname()); - sdev->custom_netlist_additions(lnetlist->nlstate()); + sdev->custom_netlist_additions(*lnetlist); } } lsetup.prepare_to_run(); #endif } -plib::unique_ptr<netlist::netlist_t> netlist_mame_device::base_validity_check(validity_checker &valid) const +plib::unique_ptr<netlist::netlist_state_t> netlist_mame_device::base_validity_check(validity_checker &valid) const { try { //netlist_mame_t lnetlist(*this, "netlist", plib::make_unique<netlist_validate_callbacks_t>()); - auto lnetlist = plib::make_unique<netlist::netlist_t>("netlist", plib::make_unique<netlist_validate_callbacks_t>()); + auto lnetlist = plib::make_unique<netlist::netlist_state_t>("netlist", plib::make_unique<netlist_validate_callbacks_t>()); // enable validation mode - lnetlist->nlstate().setup().set_extended_validation(false); + lnetlist->setup().set_extended_validation(false); common_dev_start(lnetlist.get()); for (device_t &d : subdevices()) @@ -1095,7 +1095,7 @@ plib::unique_ptr<netlist::netlist_t> netlist_mame_device::base_validity_check(va if( sdev != nullptr ) { LOGDEVCALLS("Validity check on subdevice %s/%s\n", d.name(), d.shortname()); - sdev->validity_helper(valid, lnetlist->nlstate()); + sdev->validity_helper(valid, *lnetlist); } } @@ -1114,7 +1114,7 @@ plib::unique_ptr<netlist::netlist_t> netlist_mame_device::base_validity_check(va { osd_printf_error("%s\n", err.what()); } - return plib::unique_ptr<netlist::netlist_t>(nullptr); + return plib::unique_ptr<netlist::netlist_state_t>(nullptr); } void netlist_mame_device::device_validity_check(validity_checker &valid) const @@ -1129,18 +1129,18 @@ void netlist_mame_device::device_start() { LOGDEVCALLS("device_start entry\n"); - m_netlist = netlist::pool().make_unique<netlist_mame_t>(*this, "netlist"); + m_netlist = std::make_unique<netlist_mame_t>(*this, "netlist"); if (!machine().options().verbose()) { - m_netlist->nlstate().log().verbose.set_enabled(false); - m_netlist->nlstate().log().debug.set_enabled(false); + m_netlist->log().verbose.set_enabled(false); + m_netlist->log().debug.set_enabled(false); } common_dev_start(m_netlist.get()); - m_netlist->nlstate().save(*this, m_rem, pstring(this->name()), "m_rem"); - m_netlist->nlstate().save(*this, m_div, pstring(this->name()), "m_div"); - m_netlist->nlstate().save(*this, m_old, pstring(this->name()), "m_old"); + m_netlist->save(*this, m_rem, pstring(this->name()), "m_rem"); + m_netlist->save(*this, m_div, pstring(this->name()), "m_div"); + m_netlist->save(*this, m_old, pstring(this->name()), "m_old"); save_state(); @@ -1162,13 +1162,13 @@ void netlist_mame_device::device_reset() LOGDEVCALLS("device_reset\n"); m_old = netlist::netlist_time::zero(); m_rem = netlist::netlist_time::zero(); - netlist().reset(); + netlist().exec().reset(); } void netlist_mame_device::device_stop() { LOGDEVCALLS("device_stop\n"); - netlist().stop(); + netlist().exec().stop(); } ATTR_COLD void netlist_mame_device::device_post_load() @@ -1176,7 +1176,7 @@ ATTR_COLD void netlist_mame_device::device_post_load() LOGDEVCALLS("device_post_load\n"); netlist().run_state_manager().post_load(); - netlist().nlstate().rebuild_lists(); + netlist().rebuild_lists(); } ATTR_COLD void netlist_mame_device::device_pre_save() @@ -1199,46 +1199,46 @@ void netlist_mame_device::update_icount(netlist::netlist_time time) noexcept void netlist_mame_device::check_mame_abort_slice() noexcept { if (m_icount <= 0) - netlist().abort_current_queue_slice(); + netlist().exec().abort_current_queue_slice(); } ATTR_COLD void netlist_mame_device::save_state() { for (auto const & s : netlist().run_state_manager().save_list()) { - netlist().log().debug("saving state for {1}\n", s->m_name.c_str()); - if (s->m_dt.is_float) + netlist().log().debug("saving state for {1}\n", s->name().c_str()); + if (s->dt().is_float()) { - if (s->m_dt.size == sizeof(double)) - save_pointer((double *) s->m_ptr, s->m_name.c_str(), s->m_count); - else if (s->m_dt.size == sizeof(float)) - save_pointer((float *) s->m_ptr, s->m_name.c_str(), s->m_count); + if (s->dt().size() == sizeof(double)) + save_pointer((double *) s->ptr(), s->name().c_str(), s->count()); + else if (s->dt().size() == sizeof(float)) + save_pointer((float *) s->ptr(), s->name().c_str(), s->count()); else - netlist().log().fatal("Unknown floating type for {1}\n", s->m_name.c_str()); + netlist().log().fatal("Unknown floating type for {1}\n", s->name().c_str()); } - else if (s->m_dt.is_integral) + else if (s->dt().is_integral()) { - if (s->m_dt.size == sizeof(int64_t)) - save_pointer((int64_t *) s->m_ptr, s->m_name.c_str(), s->m_count); - else if (s->m_dt.size == sizeof(int32_t)) - save_pointer((int32_t *) s->m_ptr, s->m_name.c_str(), s->m_count); - else if (s->m_dt.size == sizeof(int16_t)) - save_pointer((int16_t *) s->m_ptr, s->m_name.c_str(), s->m_count); - else if (s->m_dt.size == sizeof(int8_t)) - save_pointer((int8_t *) s->m_ptr, s->m_name.c_str(), s->m_count); + if (s->dt().size() == sizeof(int64_t)) + save_pointer((int64_t *) s->ptr(), s->name().c_str(), s->count()); + else if (s->dt().size() == sizeof(int32_t)) + save_pointer((int32_t *) s->ptr(), s->name().c_str(), s->count()); + else if (s->dt().size() == sizeof(int16_t)) + save_pointer((int16_t *) s->ptr(), s->name().c_str(), s->count()); + else if (s->dt().size() == sizeof(int8_t)) + save_pointer((int8_t *) s->ptr(), s->name().c_str(), s->count()); #if (PHAS_INT128) - else if (s->m_dt.size == sizeof(INT128)) - save_pointer((int64_t *) s->m_ptr, s->m_name.c_str(), s->m_count * 2); + else if (s->dt().size() == sizeof(INT128)) + save_pointer((int64_t *) s->ptr(), s->name().c_str(), s->count() * 2); #endif else - netlist().log().fatal("Unknown integral type size {1} for {2}\n", s->m_dt.size, s->m_name.c_str()); + netlist().log().fatal("Unknown integral type size {1} for {2}\n", s->dt().size(), s->name().c_str()); } - else if (s->m_dt.is_custom) + else if (s->dt().is_custom()) { /* do nothing */ } else - netlist().log().fatal("found unsupported save element {1}\n", s->m_name); + netlist().log().fatal("found unsupported save element {1}\n", s->name()); } } @@ -1268,7 +1268,7 @@ void netlist_mame_cpu_device::device_start() state_add(STATE_GENPCBASE, "CURPC", m_genPC).noshow(); int index = 0; - for (auto &n : netlist().nlstate().nets()) + for (auto &n : netlist().nets()) { if (n->is_logic()) { @@ -1310,14 +1310,14 @@ ATTR_HOT void netlist_mame_cpu_device::execute_run() m_genPC++; m_genPC &= 255; debugger_instruction_hook(m_genPC); - netlist().process_queue(m_div); - update_icount(netlist().time()); + netlist().exec().process_queue(m_div); + update_icount(netlist().exec().time()); } } else { - netlist().process_queue(m_div * m_icount); - update_icount(netlist().time()); + netlist().exec().process_queue(m_div * m_icount); + update_icount(netlist().exec().time()); } } @@ -1339,11 +1339,11 @@ offs_t netlist_disassembler::disassemble(std::ostream &stream, offs_t pc, const { unsigned startpc = pc; int relpc = pc - m_dev->genPC(); - if (relpc >= 0 && relpc < m_dev->netlist().queue().size()) + if (relpc >= 0 && relpc < m_dev->netlist().exec().queue().size()) { - int dpc = m_dev->netlist().queue().size() - relpc - 1; - util::stream_format(stream, "%c %s @%10.7f", (relpc == 0) ? '*' : ' ', m_dev->netlist().queue()[dpc].object()->name().c_str(), - m_dev->netlist().queue()[dpc].exec_time().as_double()); + int dpc = m_dev->netlist().exec().queue().size() - relpc - 1; + util::stream_format(stream, "%c %s @%10.7f", (relpc == 0) ? '*' : ' ', m_dev->netlist().exec().queue()[dpc].object()->name().c_str(), + m_dev->netlist().exec().queue()[dpc].exec_time().as_double()); } pc+=1; @@ -1369,7 +1369,7 @@ void netlist_mame_sound_device::device_validity_check(validity_checker &valid) c if (lnetlist) { /*Ok - do some more checks */ - std::vector<nld_sound_out *> outdevs = lnetlist->nlstate().get_device_list<nld_sound_out>(); + std::vector<nld_sound_out *> outdevs = lnetlist->get_device_list<nld_sound_out>(); if (outdevs.size() == 0) osd_printf_error("No output devices\n"); else @@ -1381,7 +1381,7 @@ void netlist_mame_sound_device::device_validity_check(validity_checker &valid) c osd_printf_error("illegal channel number %d\n", chan); } } - std::vector<nld_sound_in *> indevs = lnetlist->nlstate().get_device_list<nld_sound_in>(); + std::vector<nld_sound_in *> indevs = lnetlist->get_device_list<nld_sound_in>(); if (indevs.size() > 1) osd_printf_error("A maximum of one input device is allowed but found %d!\n", (int)indevs.size()); } @@ -1397,7 +1397,7 @@ void netlist_mame_sound_device::device_start() // Configure outputs - std::vector<nld_sound_out *> outdevs = netlist().nlstate().get_device_list<nld_sound_out>(); + std::vector<nld_sound_out *> outdevs = netlist().get_device_list<nld_sound_out>(); if (outdevs.size() == 0) fatalerror("No output devices"); @@ -1424,7 +1424,7 @@ void netlist_mame_sound_device::device_start() m_in = nullptr; - std::vector<nld_sound_in *> indevs = netlist().nlstate().get_device_list<nld_sound_in>(); + std::vector<nld_sound_in *> indevs = netlist().get_device_list<nld_sound_in>(); if (indevs.size() > 1) fatalerror("A maximum of one input device is allowed!"); if (indevs.size() == 1) @@ -1464,9 +1464,9 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream } } - netlist::netlist_time cur(netlist().time()); + netlist::netlist_time cur(netlist().exec().time()); - netlist().process_queue(m_div * samples); + netlist().exec().process_queue(m_div * samples); cur += (m_div * samples); diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index 2a58d956f68..a7667940809 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -100,18 +100,18 @@ protected: netlist::netlist_time m_div; - plib::unique_ptr<netlist::netlist_t> base_validity_check(validity_checker &valid) const; + plib::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const; private: void save_state(); - void common_dev_start(netlist::netlist_t *lnetlist) const; + void common_dev_start(netlist::netlist_state_t *lnetlist) const; /* timing support here - so sound can hijack it ... */ netlist::netlist_time m_rem; netlist::netlist_time m_old; - netlist::unique_pool_ptr<netlist_mame_t> m_netlist; + std::unique_ptr<netlist_mame_t> m_netlist; func_type m_setup_func; }; diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index c698484e5bd..fc57916575e 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -222,7 +222,7 @@ namespace analog m_capmod = m_model.m_CAPMOD; // printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_model.m_VTO, m_polarity); - nl_assert_always(m_capmod == 0 || m_capmod == 2, "Error: CAPMODEL invalid value for " + m_model.name()); + nl_assert_always(m_capmod == 0 || m_capmod == 2, "Error: CAPMODEL invalid value"); // // From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm : @@ -238,7 +238,7 @@ namespace analog // calculate effective channel length m_Leff = m_model.m_L - 2 * m_model.m_LD; - nl_assert_always(m_Leff > nlconst::zero(), "Effective Lateral diffusion would be negative for model " + m_model.name()); + nl_assert_always(m_Leff > nlconst::zero(), "Effective Lateral diffusion would be negative for model"); nl_fptype Cox = (m_model.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : nlconst::zero(); @@ -259,7 +259,7 @@ namespace analog m_phi = m_model.m_PHI; else if (m_model.m_NSUB > nlconst::zero()) { - nl_assert_always(m_model.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model " + m_model.name()); + nl_assert_always(m_model.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model"); m_phi = nlconst::two() * Vt * plib::log (m_model.m_NSUB * nlconst::magic(1e6) / constants::NiSi()); } else diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index a891827cb1a..ddf76b27887 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -92,9 +92,9 @@ namespace netlist for (auto & pwr_sym : power_syms) { pstring devname = out_proxied->device().name(); - auto tp_t = state().setup().find_terminal(devname + "." + pwr_sym.first, + auto tp_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.first, /*detail::terminal_type::INPUT,*/ false); - auto tn_t = state().setup().find_terminal(devname + "." + pwr_sym.second, + auto tn_t = anetlist.setup().find_terminal(devname + "." + pwr_sym.second, /*detail::terminal_type::INPUT,*/ false); if (f && (tp_t != nullptr && tn_t != nullptr)) log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(out_proxied->device().name(), @@ -113,9 +113,9 @@ namespace netlist if (!f) { if (logic_family()->fixed_V() == nlconst::zero()) - log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); + log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(anetlist.setup().de_alias(out_proxied->device().name()))); else - log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); + log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(anetlist.setup().de_alias(out_proxied->device().name()))); m_GNDHack = plib::make_unique<analog_output_t>(*this, "_QGND"); m_VCCHack = plib::make_unique<analog_output_t>(*this, "_QVCC"); @@ -126,7 +126,7 @@ namespace netlist else { log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name()); - if (state().setup().is_extended_validation()) + if (anetlist.setup().is_extended_validation()) { // During validation, don't connect to terminals found // This will cause terminals not connected to a rail net to diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index 6448dfff3d6..e84472a536f 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -327,7 +327,7 @@ namespace devices for (int i=0; i < m_N(); i++) { pstring n = plib::pfmt("A{1}")(i); - m_I.push_back(pool().make_unique<analog_input_t>(*this, n)); + m_I.push_back(state().make_object<analog_input_t>(*this, n)); inps.push_back(n); m_vals.push_back(nlconst::zero()); } @@ -426,8 +426,8 @@ namespace devices { if (owner.state().setup().is_extended_validation() || force_analog_input) { - m_GND = pool().make_unique<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop)); - m_VCC = pool().make_unique<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop)); + m_GND = owner.state().make_object<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop)); + m_VCC = owner.state().make_object<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop)); } else { diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 951465b0515..e471bff549b 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -1,7 +1,7 @@ // license:GPL-2.0+ // copyright-holders:Couriersud -#include "nlid_truthtable.h" +#include "nlid_truthtable.h" #include "netlist/nl_setup.h" #include "plib/palloc.h" #include "plib/plists.h" @@ -245,13 +245,13 @@ namespace devices : truthtable_base_element_t(name, classname, def_param, sourcefile) { } - unique_pool_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override + unique_pool_ptr<device_t> Create(nlmempool &pool, netlist_state_t &anetlist, const pstring &name) override { using tt_type = nld_truthtable_t<m_NI, m_NO>; if (!m_ttbl) { - m_ttbl = pool().make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(); + m_ttbl = pool.make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(); truthtable_parser desc_s(m_NO, m_NI, packed_int(m_ttbl->m_out_state.data(), sizeof(m_ttbl->m_out_state[0]) * 8), m_ttbl->m_timing_index.data(), m_ttbl->m_timing_nt.data()); @@ -266,7 +266,7 @@ namespace devices if (m_family_desc == nullptr) plib::pthrow<nl_exception>("family description not found for {1}", m_family_name); - return pool().make_unique<tt_type>(anetlist, name, m_family_desc, *m_ttbl, m_desc); + return pool.make_unique<tt_type>(anetlist, name, m_family_desc, *m_ttbl, m_desc); } private: unique_pool_ptr<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t> m_ttbl; @@ -512,7 +512,7 @@ namespace factory ENTRY(12, sourcefile); default: pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no); - nl_assert_always(false, msg); + nl_assert_always(false, msg.c_str()); } ret->m_desc = desc.desc; ret->m_family_name = desc.family; diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 80c3be33e66..7a9ed54c7d7 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -49,11 +49,11 @@ namespace netlist unique_pool_ptr<devices::nld_base_d_to_a_proxy> logic_family_ttl_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const { - return pool().make_unique<devices::nld_d_to_a_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_d_to_a_proxy>(anetlist, name, proxied); } unique_pool_ptr<devices::nld_base_a_to_d_proxy> logic_family_ttl_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const { - return pool().make_unique<devices::nld_a_to_d_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied); } class logic_family_cd4xxx_t : public logic_family_desc_t @@ -76,12 +76,12 @@ namespace netlist unique_pool_ptr<devices::nld_base_d_to_a_proxy> logic_family_cd4xxx_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const { - return pool().make_unique<devices::nld_d_to_a_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_d_to_a_proxy>(anetlist, name, proxied); } unique_pool_ptr<devices::nld_base_a_to_d_proxy> logic_family_cd4xxx_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const { - return pool().make_unique<devices::nld_a_to_d_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied); } const logic_family_desc_t *family_TTL() @@ -100,7 +100,7 @@ namespace netlist // queue_t // ---------------------------------------------------------------------------------------- - detail::queue_t::queue_t(netlist_state_t &nl) + detail::queue_t::queue_t(netlist_t &nl) : timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>(512) , netlist_ref(nl) , m_qsize(0) @@ -144,8 +144,8 @@ namespace netlist // netlist_ref_t // ---------------------------------------------------------------------------------------- - detail::netlist_ref::netlist_ref(netlist_state_t &nl) - : m_netlist(nl.exec()) { } + detail::netlist_ref::netlist_ref(netlist_t &nl) + : m_netlist(nl) { } // ---------------------------------------------------------------------------------------- // device_object_t @@ -179,18 +179,16 @@ namespace netlist // netlist_t // ---------------------------------------------------------------------------------------- - netlist_t::netlist_t(const pstring &aname, plib::unique_ptr<callbacks_t> callbacks) - : m_state(plib::make_unique<netlist_state_t>(aname, *this, std::move(callbacks))) + netlist_t::netlist_t(netlist_state_t &state) + : m_state(state) , m_solver(nullptr) , m_time(netlist_time::zero()) , m_mainclock(nullptr) - , m_queue(*m_state) + , m_queue(*this) , m_use_stats(false) { - devices::initialize_factory(nlstate().setup().factory()); - NETLIST_NAME(base)(nlstate().setup()); - run_state_manager().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue"); - run_state_manager().save_item(this, m_time, "m_time"); + state.run_state_manager().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue"); + state.run_state_manager().save_item(this, m_time, "m_time"); } // ---------------------------------------------------------------------------------------- @@ -198,17 +196,21 @@ namespace netlist // ---------------------------------------------------------------------------------------- netlist_state_t::netlist_state_t(const pstring &aname, - netlist_t & anetlist, plib::unique_ptr<callbacks_t> &&callbacks) : m_name(aname) - , m_netlist(anetlist) , m_state() , m_callbacks(std::move(callbacks)) // Order is important here , m_log(*m_callbacks) - , m_setup(plib::make_unique<setup_t>(*this)) { pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); m_lib = plib::make_unique<plib::dynlib>(libpath); + + m_setup = plib::make_unique<setup_t>(*this); + // create the run interface + m_netlist = m_pool.make_unique<netlist_t>(*this); + + devices::initialize_factory(m_setup->factory()); + NETLIST_NAME(base)(*m_setup); } @@ -300,10 +302,10 @@ namespace netlist void netlist_t::reset() { log().debug("Searching for mainclock\n"); - m_mainclock = m_state->get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock"); + m_mainclock = m_state.get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock"); log().debug("Searching for solver\n"); - m_solver = m_state->get_single_device<devices::NETLIB_NAME(solver)>("solver"); + m_solver = m_state.get_single_device<devices::NETLIB_NAME(solver)>("solver"); m_time = netlist_time::zero(); m_queue.clear(); @@ -312,7 +314,7 @@ namespace netlist //if (m_solver != nullptr) // m_solver->reset(); - m_state->reset(); + m_state.reset(); } void netlist_state_t::reset() @@ -411,19 +413,19 @@ namespace netlist if (m_use_stats) { std::vector<size_t> index; - for (size_t i=0; i < m_state->m_devices.size(); i++) + for (size_t i=0; i < m_state.m_devices.size(); i++) index.push_back(i); std::sort(index.begin(), index.end(), - [&](size_t i1, size_t i2) { return m_state->m_devices[i1].second->m_stats->m_stat_total_time.total() < m_state->m_devices[i2].second->m_stats->m_stat_total_time.total(); }); + [&](size_t i1, size_t i2) { return m_state.m_devices[i1].second->m_stats->m_stat_total_time.total() < m_state.m_devices[i2].second->m_stats->m_stat_total_time.total(); }); plib::pperftime_t<true>::type total_time(0); plib::pperftime_t<true>::ctype total_count(0); for (auto & j : index) { - auto entry = m_state->m_devices[j].second.get(); - auto stats = m_state->m_devices[j].second.get()->m_stats.get(); + auto entry = m_state.m_devices[j].second.get(); + auto stats = m_state.m_devices[j].second.get()->m_stats.get(); log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(), stats->m_stat_call_count(), stats->m_stat_total_time.count(), stats->m_stat_total_time.total(), stats->m_stat_inc_active()); @@ -472,7 +474,7 @@ namespace netlist } auto trigger = total_count * 200 / 1000000; // 200 ppm - for (auto &entry : m_state->m_devices) + for (auto &entry : m_state.m_devices) { auto ep = entry.second.get(); auto stats = ep->m_stats.get(); @@ -483,7 +485,10 @@ namespace netlist static_cast<nl_fptype>(stats->m_stat_inc_active()) / static_cast<nl_fptype>(stats->m_stat_total_time.count()), stats->m_stat_inc_active(), stats->m_stat_total_time.count()); } + log().verbose(""); } + log().verbose("Current pool memory allocated: {1:12} kB", nlstate().pool().cur_alloc() >> 10); + log().verbose("Maximum pool memory allocated: {1:12} kB", nlstate().pool().max_alloc() >> 10); } core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const @@ -513,29 +518,29 @@ namespace netlist core_device_t::core_device_t(netlist_state_t &owner, const pstring &name) : object_t(name) , logic_family_t() - , netlist_ref(owner) + , netlist_ref(owner.exec()) , m_hint_deactivate(false) , m_active_outputs(*this, "m_active_outputs", 1) { if (logic_family() == nullptr) set_logic_family(family_TTL()); if (exec().stats_enabled()) - m_stats = pool().make_unique<stats_t>(); + m_stats = owner.make_object<stats_t>(); } core_device_t::core_device_t(core_device_t &owner, const pstring &name) : object_t(owner.name() + "." + name) , logic_family_t() - , netlist_ref(owner.state()) + , netlist_ref(owner.state().exec()) , m_hint_deactivate(false) , m_active_outputs(*this, "m_active_outputs", 1) { set_logic_family(owner.logic_family()); if (logic_family() == nullptr) set_logic_family(family_TTL()); - state().register_device(this->name(), owned_pool_ptr<core_device_t>(this, false)); + owner.state().register_device(this->name(), owned_pool_ptr<core_device_t>(this, false)); if (exec().stats_enabled()) - m_stats = pool().make_unique<stats_t>(); + m_stats = owner.state().make_object<stats_t>(); } void core_device_t::set_default_delegate(detail::core_terminal_t &term) @@ -627,7 +632,7 @@ namespace netlist detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *railterminal) : object_t(aname) - , netlist_ref(nl) + , netlist_ref(nl.exec()) , m_new_Q(*this, "m_new_Q", 0) , m_cur_Q (*this, "m_cur_Q", 0) , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED) @@ -982,4 +987,8 @@ namespace netlist return dynamic_cast<const analog_net_t *>(this) != nullptr; } + // ---------------------------------------------------------------------------------------- + // netlist_state_t + // ---------------------------------------------------------------------------------------- + } // namespace netlist diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index b4f41396298..739b6dfc6fd 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -23,6 +23,7 @@ #include "plib/pstonum.h" #include "plib/pstream.h" #include "plib/ptime.h" +#include "plib/pexception.h" #include "nl_errstr.h" #include "nltypes.h" @@ -174,13 +175,13 @@ class NETLIB_NAME(name) : public device_t //============================================================ #if defined(MAME_DEBUG) || (NL_DEBUG == true) -#define nl_assert(x) do { if (1) if (!(x)) plib::pthrow<nl_exception>(plib::pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); } while (0) +#define nl_assert(x) passert_always(x); #define NL_NOEXCEPT #else -#define nl_assert(x) do { if (0) if (!(x)) { /*throw nl_exception(plib::pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); */} } while (0) +#define nl_assert(x) do { } while (0) #define NL_NOEXCEPT noexcept #endif -#define nl_assert_always(x, msg) do { if (!(x)) plib::pthrow<nl_exception>("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}", msg, __FILE__, __LINE__, #x); } while (0) +#define nl_assert_always(x, msg) passert_always_msg(x, msg) //============================================================ // Namespace starts @@ -424,9 +425,19 @@ namespace netlist store().insert({obj, aname}); } - static const T get(const C *obj) noexcept + static const T &get(const C *obj) noexcept { - return store().find(obj)->second; + try + { + auto ret(store().find(obj)); + nl_assert(ret != store().end()); + return ret->second; + } + catch (...) + { + nl_assert_always(true, "exception in property_store_t.get()"); + return *static_cast<T *>(nullptr); + } } static void remove(const C *obj) noexcept @@ -472,7 +483,7 @@ namespace netlist /// /// \returns name of the object. - pstring name() const noexcept + const pstring &name() const noexcept { return props::get(this); } @@ -492,7 +503,7 @@ namespace netlist struct netlist_ref { - explicit netlist_ref(netlist_state_t &nl); + explicit netlist_ref(netlist_t &nl); COPYASSIGNMOVE(netlist_ref, delete) @@ -1076,10 +1087,7 @@ namespace netlist ~device_t() noexcept override = default; template<class C, typename... Args> - void create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args) - { - dev = pool().make_unique<C>(*this, name, std::forward<Args>(args)...); - } + void create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args); void register_subalias(const pstring &name, detail::core_terminal_t &term); void register_subalias(const pstring &name, const pstring &aliased); @@ -1335,7 +1343,7 @@ namespace netlist public: using base_queue = timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>; using entry_t = plib::pqentry_t<net_t *, netlist_time>; - explicit queue_t(netlist_state_t &nl); + explicit queue_t(netlist_t &nl); ~queue_t() noexcept override = default; queue_t(const queue_t &) = delete; @@ -1370,12 +1378,16 @@ namespace netlist // need to preserve order of device creation ... using devices_collection_type = std::vector<std::pair<pstring, owned_pool_ptr<core_device_t>>>; netlist_state_t(const pstring &aname, - netlist_t & anetlist, plib::unique_ptr<callbacks_t> &&callbacks); COPYASSIGNMOVE(netlist_state_t, delete) - ~netlist_state_t() noexcept = default; + /// \brief Destructor + /// + /// The destructor is virtual to allow implementation specific devices + /// to connect to the outside world. For examples see MAME netlist.cpp. + /// + virtual ~netlist_state_t() noexcept = default; friend class netlist_t; // allow access to private members @@ -1428,8 +1440,8 @@ namespace netlist plib::dynlib &lib() const noexcept { return *m_lib; } - netlist_t &exec() { return m_netlist; } - const netlist_t &exec() const { return m_netlist; } + netlist_t &exec() { return *m_netlist; } + const netlist_t &exec() const { return *m_netlist; } // state handling plib::state_manager_t &run_state_manager() { return m_state; } @@ -1536,12 +1548,21 @@ namespace netlist // sole use is to manage lifetime of family objects std::unordered_map<pstring, plib::unique_ptr<logic_family_desc_t>> m_family_cache; + template<typename T, typename... Args> + unique_pool_ptr<T> make_object(Args&&... args) + { + return m_pool.make_unique<T>(std::forward<Args>(args)...); + } + // memory pool - still needed in some places + nlmempool &pool() noexcept { return m_pool; } + const nlmempool &pool() const noexcept { return m_pool; } private: void reset(); + nlmempool m_pool; // must be deleted last! pstring m_name; - netlist_t &m_netlist; + unique_pool_ptr<netlist_t> m_netlist; plib::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists plib::state_manager_t m_state; plib::unique_ptr<callbacks_t> m_callbacks; @@ -1599,7 +1620,7 @@ namespace netlist { public: - explicit netlist_t(const pstring &aname, plib::unique_ptr<callbacks_t> callbacks); + explicit netlist_t(netlist_state_t &state); COPYASSIGNMOVE(netlist_t, delete) @@ -1643,10 +1664,6 @@ namespace netlist void stop(); void reset(); - // state handling - - plib::state_manager_t &run_state_manager() noexcept { return m_state->run_state_manager(); } - // only used by nltool to create static c-code devices::NETLIB_NAME(solver) *solver() const noexcept { return m_solver; } @@ -1658,11 +1675,11 @@ namespace netlist return static_cast<X *>(m_solver)->gmin(); } - netlist_state_t &nlstate() noexcept { return *m_state; } - const netlist_state_t &nlstate() const noexcept { return *m_state; } + netlist_state_t &nlstate() noexcept { return m_state; } + const netlist_state_t &nlstate() const noexcept { return m_state; } - log_type & log() noexcept { return m_state->log(); } - const log_type &log() const noexcept { return m_state->log(); } + log_type & log() noexcept { return m_state.log(); } + const log_type &log() const noexcept { return m_state.log(); } void print_stats() const; @@ -1674,7 +1691,7 @@ namespace netlist template <bool KEEP_STATS> void process_queue_stats(netlist_time delta) noexcept; - plib::unique_ptr<netlist_state_t> m_state; + netlist_state_t & m_state; devices::NETLIB_NAME(solver) * m_solver; // mostly rw @@ -1725,6 +1742,12 @@ namespace netlist return m_netlist.nlstate(); } + template<class C, typename... Args> + void device_t::create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args) + { + dev = state().make_object<C>(*this, name, std::forward<Args>(args)...); + } + template <typename T> param_num_t<T>::param_num_t(device_t &device, const pstring &name, const T val) : param_t(device, name) diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp index 4ab1c7765d0..55d62c7b336 100644 --- a/src/lib/netlist/nl_factory.cpp +++ b/src/lib/netlist/nl_factory.cpp @@ -76,9 +76,9 @@ namespace netlist { namespace factory // factory_lib_entry_t: factory class to wrap macro based chips/elements // ----------------------------------------------------------------------------- - unique_pool_ptr<device_t> library_element_t::Create(netlist_state_t &anetlist, const pstring &name) + unique_pool_ptr<device_t> library_element_t::Create(nlmempool &pool, netlist_state_t &anetlist, const pstring &name) { - return pool().make_unique<NETLIB_NAME(wrapper)>(anetlist, name); + return pool.make_unique<NETLIB_NAME(wrapper)>(anetlist, name); } void library_element_t::macro_actions(nlparse_t &nparser, const pstring &name) diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index ec53eb3bde7..e03989d860d 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -54,7 +54,10 @@ namespace factory { COPYASSIGNMOVE(element_t, default) - virtual unique_pool_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) = 0; + virtual unique_pool_ptr<device_t> Create(nlmempool &pool, + netlist_state_t &anetlist, + const pstring &name) = 0; + virtual void macro_actions(nlparse_t &nparser, const pstring &name) { plib::unused_var(nparser); @@ -84,9 +87,11 @@ namespace factory { const pstring &def_param, const pstring &sourcefile) : element_t(name, classname, def_param, sourcefile) { } - unique_pool_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override + unique_pool_ptr<device_t> Create(nlmempool &pool, + netlist_state_t &anetlist, + const pstring &name) override { - return pool().make_unique<C>(anetlist, name); + return pool.make_unique<C>(anetlist, name); } }; @@ -146,7 +151,9 @@ namespace factory { { } - unique_pool_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override; + unique_pool_ptr<device_t> Create(nlmempool &pool, + netlist_state_t &anetlist, + const pstring &name) override; void macro_actions(nlparse_t &nparser, const pstring &name) override; diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 8943fb41dab..e9b0ef6c34f 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -765,7 +765,7 @@ void setup_t::connect_terminals(detail::core_terminal_t &t1, detail::core_termin { log().debug("adding analog net ...\n"); // FIXME: Nets should have a unique name - auto anet = pool().make_owned<analog_net_t>(m_nlstate,"net." + t1.name()); + auto anet = nlstate().pool().make_owned<analog_net_t>(m_nlstate,"net." + t1.name()); auto anetp = anet.get(); m_nlstate.register_net(std::move(anet)); t1.set_net(anetp); @@ -961,7 +961,7 @@ void setup_t::register_dynamic_log_devices() for (const pstring &ll : loglist) { pstring name = "log_" + ll; - auto nc = factory().factory_by_name("LOG")->Create(m_nlstate, name); + auto nc = factory().factory_by_name("LOG")->Create(m_nlstate.pool(), m_nlstate, name); register_link(name + ".I", ll); log().debug(" dynamic link {1}: <{2}>\n",ll, name); m_nlstate.register_device(nc->name(), std::move(nc)); @@ -1118,11 +1118,11 @@ public: unique_pool_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const { - return pool().make_unique<devices::nld_d_to_a_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_d_to_a_proxy>(anetlist, name, proxied); } unique_pool_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const { - return pool().make_unique<devices::nld_a_to_d_proxy>(anetlist, name, proxied); + return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied); } @@ -1205,7 +1205,7 @@ void setup_t::prepare_to_run() if ( factory().is_class<devices::NETLIB_NAME(solver)>(e.second) || factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second)) { - m_nlstate.register_device(e.first, e.second->Create(m_nlstate, e.first)); + m_nlstate.register_device(e.first, e.second->Create(nlstate().pool(), m_nlstate, e.first)); } } @@ -1227,7 +1227,7 @@ void setup_t::prepare_to_run() if ( !factory().is_class<devices::NETLIB_NAME(solver)>(e.second) && !factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second)) { - auto dev = e.second->Create(m_nlstate, e.first); + auto dev = e.second->Create(m_nlstate.pool(), m_nlstate, e.first); m_nlstate.register_device(dev->name(), std::move(dev)); } } diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 308afccfa59..af3ccd5828b 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -87,12 +87,6 @@ namespace netlist template <typename T> using unique_pool_ptr = nlmempool::unique_pool_ptr<T>; - inline nlmempool &pool() - { - static nlmempool static_pool; - return static_pool; - } - namespace detail { /// \brief Enum specifying the type of object diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 0a79302787d..50aa880320e 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -63,7 +63,7 @@ namespace plib { { // call destructor p->~T(); - getref(m_a).deallocate(p); + getref(m_a).deallocate(p, sizeof(T)); } //private: arena_storage_type m_a; @@ -228,8 +228,7 @@ namespace plib { void deallocate(T* p, std::size_t n) noexcept { - unused_var(n); - m_a.deallocate(p); + m_a.deallocate(p, n); } template <class AR1, class T1, std::size_t A1, class AR2, class T2, std::size_t A2> @@ -263,7 +262,9 @@ namespace plib { struct aligned_arena { static constexpr const bool is_stateless = true; - template <class T, std::size_t ALIGN = alignof(T)> + using size_type = std::size_t; + + template <class T, size_type ALIGN = alignof(T)> using allocator_type = arena_allocator<aligned_arena, T, ALIGN>; template <typename T> @@ -298,8 +299,9 @@ namespace plib { #endif } - static inline void deallocate( void *ptr ) noexcept + static inline void deallocate( void *ptr, size_t size ) noexcept { + unused_var(size); #if (PUSE_ALIGNED_ALLOCATION) // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(ptr); @@ -319,7 +321,7 @@ namespace plib { } catch (...) { - deallocate(mem); + deallocate(mem, sizeof(T)); throw; } } @@ -335,7 +337,7 @@ namespace plib { } catch (...) { - deallocate(mem); + deallocate(mem, sizeof(T)); throw; } } @@ -387,7 +389,7 @@ namespace plib { inline void pdelete(T *ptr) noexcept { ptr->~T(); - aligned_arena::deallocate(ptr); + aligned_arena::deallocate(ptr, sizeof(T)); } diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index bb954eefa48..f08c9c025ea 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -72,11 +72,11 @@ /// \brief Number of bytes for cache line alignment /// -#define PALIGN_CACHELINE (64) +#define PALIGN_CACHELINE (16) /// \brief Number of bytes for vector alignment /// -#define PALIGN_VECTOROPT (64) +#define PALIGN_VECTOROPT (16) #define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE) #define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT) diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp index 6b53d362c79..674601f2ed8 100644 --- a/src/lib/netlist/plib/pexception.cpp +++ b/src/lib/netlist/plib/pexception.cpp @@ -19,12 +19,35 @@ namespace plib { // terminate //============================================================ - void terminate(const pstring &msg) noexcept + void terminate(const char *msg) noexcept { - std::cerr << msg.c_str() << "\n"; + try + { + std::cerr << msg << "\n"; + } + catch (...) + { + /* ignore */ + } std::terminate(); } + void passert_fail(const char *assertion, const char *file, int lineno, const char *msg) noexcept + { + try + { + std::cerr << file << ":" << lineno << ": "; + if (msg != nullptr) + std::cerr << msg << "\n"; + else + std::cerr << "Assertion '" << assertion << "' failed.\n"; + } + catch (...) + { + /* ignore */ + } + std::terminate(); + } //============================================================ // Exceptions diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h index 7317a320e28..f237f06e759 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -13,13 +13,22 @@ #include <exception> +#define passert_always(expr) \ + ((expr) ? static_cast<void>(0) : plib::passert_fail (#expr, __FILE__, __LINE__, nullptr)) + +#define passert_always_msg(expr, msg) \ + ((expr) ? static_cast<void>(0) : plib::passert_fail (#expr, __FILE__, __LINE__, msg)) + namespace plib { /// \brief Terminate the program. /// /// \note could be enhanced by setting a termination handler /// - [[noreturn]] void terminate(const pstring &msg) noexcept; + [[noreturn]] void terminate(const char *msg) noexcept; + + [[noreturn]] void passert_fail(const char *assertion, + const char *file, int lineno, const char *msg) noexcept; /// \brief throw an exception. /// diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 59ca2d6f56c..60acf014295 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -8,6 +8,7 @@ /// \file pmempool.h /// +#include "pconfig.h" #include "palloc.h" #include "pstream.h" #include "pstring.h" @@ -28,80 +29,21 @@ namespace plib { class mempool { - private: - struct block - { - block(mempool &mp, std::size_t min_bytes) - : m_num_alloc(0) - , m_cur(0) - , m_data(nullptr) - , m_mempool(mp) - { - min_bytes = std::max(mp.m_min_alloc, min_bytes); - m_free = min_bytes; - std::size_t alloc_bytes = (min_bytes + mp.m_min_align); // - 1); // & ~(mp.m_min_align - 1); - //m_data_allocated = ::operator new(alloc_bytes); - m_data_allocated = new char[alloc_bytes]; - void *r = m_data_allocated; - std::align(mp.m_min_align, min_bytes, r, alloc_bytes); - m_data = reinterpret_cast<char *>(r); - } - ~block() - { - //::operator delete(m_data_allocated); - delete [] m_data_allocated; - } - - block(const block &) = delete; - block(block &&) = delete; - block &operator =(const block &) = delete; - block &operator =(block &&) = delete; - - std::size_t m_num_alloc; - std::size_t m_free; - std::size_t m_cur; - char *m_data; - char *m_data_allocated; - mempool &m_mempool; - }; - - struct info - { - info(block *b, std::size_t p) : m_block(b), m_pos(p) { } - ~info() = default; - COPYASSIGNMOVE(info, default) - - block * m_block; - std::size_t m_pos; - }; - - - block * new_block(std::size_t min_bytes) - { - auto *b = plib::pnew<block>(*this, min_bytes); - m_blocks.push_back(b); - return b; - } - + public: - static std::unordered_map<void *, info> &sinfo() - { - static std::unordered_map<void *, info> spinfo; - return spinfo; - } + using size_type = std::size_t; - size_t m_min_alloc; - size_t m_min_align; + static constexpr const bool is_stateless = false; - std::vector<block *> m_blocks; - public: - static constexpr const bool is_stateless = false; - template <class T, std::size_t ALIGN = alignof(T)> + template <class T, size_type ALIGN = alignof(T)> using allocator_type = arena_allocator<mempool, T, ALIGN>; - mempool(size_t min_alloc = (1<<21), size_t min_align = 16) - : m_min_alloc(min_alloc), m_min_align(min_align) + mempool(size_t min_alloc = (1<<21), size_t min_align = PALIGN_CACHELINE) + : m_min_alloc(min_alloc) + , m_min_align(min_align) + , m_stat_cur_alloc(0) + , m_stat_max_alloc(0) { } @@ -156,29 +98,32 @@ namespace plib { sinfo().insert({ ret, info(b, b->m_cur)}); rs -= (capacity - size); b->m_cur += rs; + m_stat_cur_alloc += size; + m_stat_max_alloc = std::max(m_stat_max_alloc, m_stat_cur_alloc); return ret; } - static void deallocate(void *ptr) + static void deallocate(void *ptr, size_t size) { auto it = sinfo().find(ptr); if (it == sinfo().end()) - plib::terminate("mempool::free - pointer not found\n"); + plib::terminate("mempool::free - pointer not found"); block *b = it->second.m_block; if (b->m_num_alloc == 0) - plib::terminate("mempool::free - double free was called\n"); + plib::terminate("mempool::free - double free was called"); else { + mempool &mp = b->m_mempool; b->m_num_alloc--; + mp.m_stat_cur_alloc -= size; //printf("Freeing in block %p %lu\n", b, b->m_num_alloc); if (b->m_num_alloc == 0) { - mempool &mp = b->m_mempool; auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b); if (itb == mp.m_blocks.end()) - plib::terminate("mempool::free - block not found\n"); + plib::terminate("mempool::free - block not found"); mp.m_blocks.erase(itb); plib::pdelete(b); @@ -204,7 +149,7 @@ namespace plib { } catch (...) { - this->deallocate(mem); + this->deallocate(mem, sizeof(T)); throw; } } @@ -220,13 +165,85 @@ namespace plib { } catch (...) { - this->deallocate(mem); + this->deallocate(mem, sizeof(T)); throw; } } + size_type cur_alloc() const noexcept { return m_stat_cur_alloc; } + size_type max_alloc() const noexcept { return m_stat_max_alloc; } + bool operator ==(const mempool &rhs) const noexcept { return this == &rhs; } + private: + struct block + { + block(mempool &mp, size_type min_bytes) + : m_num_alloc(0) + , m_cur(0) + , m_data(nullptr) + , m_mempool(mp) + { + min_bytes = std::max(mp.m_min_alloc, min_bytes); + m_free = min_bytes; + size_type alloc_bytes = (min_bytes + mp.m_min_align); // - 1); // & ~(mp.m_min_align - 1); + //m_data_allocated = ::operator new(alloc_bytes); + m_data_allocated = new char[alloc_bytes]; + void *r = m_data_allocated; + std::align(mp.m_min_align, min_bytes, r, alloc_bytes); + m_data = reinterpret_cast<char *>(r); + } + ~block() + { + //::operator delete(m_data_allocated); + delete [] m_data_allocated; + } + + block(const block &) = delete; + block(block &&) = delete; + block &operator =(const block &) = delete; + block &operator =(block &&) = delete; + + size_type m_num_alloc; + size_type m_free; + size_type m_cur; + char *m_data; + char *m_data_allocated; + mempool &m_mempool; + }; + + struct info + { + info(block *b, size_type p) : m_block(b), m_pos(p) { } + ~info() = default; + COPYASSIGNMOVE(info, default) + + block * m_block; + size_type m_pos; + }; + + + block * new_block(size_type min_bytes) + { + auto *b = plib::pnew<block>(*this, min_bytes); + m_blocks.push_back(b); + return b; + } + + + static std::unordered_map<void *, info> &sinfo() + { + static std::unordered_map<void *, info> spinfo; + return spinfo; + } + + size_t m_min_alloc; + size_t m_min_align; + + std::vector<block *> m_blocks; + + size_t m_stat_cur_alloc; + size_t m_stat_max_alloc; }; } // namespace plib diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h index 659c6991c42..71db3b97bb6 100644 --- a/src/lib/netlist/plib/pstate.h +++ b/src/lib/netlist/plib/pstate.h @@ -28,16 +28,22 @@ public: struct datatype_t { datatype_t(std::size_t bsize, bool bintegral, bool bfloat) - : size(bsize), is_integral(bintegral), is_float(bfloat), is_custom(false) + : m_size(bsize), m_is_integral(bintegral), m_is_float(bfloat), m_is_custom(false) {} explicit datatype_t(bool bcustom) - : size(0), is_integral(false), is_float(false), is_custom(bcustom) + : m_size(0), m_is_integral(false), m_is_float(false), m_is_custom(bcustom) {} - const std::size_t size; - const bool is_integral; - const bool is_float; - const bool is_custom; + std::size_t size() const noexcept { return m_size; } + bool is_integral() const noexcept { return m_is_integral; } + bool is_float() const noexcept { return m_is_float; } + bool is_custom() const noexcept { return m_is_custom; } + + private: + std::size_t m_size; + bool m_is_integral; + bool m_is_float; + bool m_is_custom; }; template<typename T> @@ -64,7 +70,7 @@ public: struct entry_t { - using list_t = std::vector<plib::unique_ptr<entry_t>>; + using list_t = std::vector<entry_t>; entry_t(const pstring &stname, const datatype_t &dt, const void *owner, const std::size_t count, void *ptr) @@ -73,11 +79,19 @@ public: entry_t(const pstring &stname, const void *owner, callback_t *callback) : m_name(stname), m_dt(datatype_t(true)), m_owner(owner), m_callback(callback), m_count(0), m_ptr(nullptr) { } + pstring name() const noexcept { return m_name; } + datatype_t dt() const noexcept { return m_dt; } + const void * owner() const noexcept { return m_owner; } + callback_t * callback() const noexcept { return m_callback; } + std::size_t count() const noexcept { return m_count; } + void * ptr() const noexcept { return m_ptr; } + + private: pstring m_name; - const datatype_t m_dt; + datatype_t m_dt; const void * m_owner; callback_t * m_callback; - const std::size_t m_count; + std::size_t m_count; void * m_ptr; }; @@ -115,19 +129,19 @@ public: void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr) { - m_save.push_back(plib::make_unique<entry_t>(stname, dt, owner, count, ptr)); + m_save.emplace_back(stname, dt, owner, count, ptr); } void pre_save() { for (auto & s : m_custom) - s->m_callback->on_pre_save(*this); + s.callback()->on_pre_save(*this); } void post_load() { for (auto & s : m_custom) - s->m_callback->on_post_load(*this); + s.callback()->on_post_load(*this); } void remove_save_items(const void *owner) @@ -136,14 +150,14 @@ public: while (i != m_save.begin()) { i--; - if (i->get()->m_owner == owner) + if (i->owner() == owner) i = m_save.erase(i); } i = m_custom.end(); while (i > m_custom.begin()) { i--; - if (i->get()->m_owner == owner) + if (i->owner() == owner) i = m_custom.erase(i); } } @@ -152,7 +166,7 @@ public: { std::vector<const entry_t *> ret; for (auto &i : m_save) - ret.push_back(i.get()); + ret.push_back(&i); return ret; } @@ -166,7 +180,7 @@ private: template<> inline void state_manager_t::save_item(const void *owner, callback_t &state, const pstring &stname) { - m_custom.push_back(plib::make_unique<entry_t>(stname, owner, &state)); + m_custom.emplace_back(stname, owner, &state); state.register_state(*this, stname); } diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 114ec2f764e..fadf1af2d03 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -201,17 +201,15 @@ private: tool_app_t &m_app; }; -class netlist_tool_t : public netlist::netlist_t +class netlist_tool_t : public netlist::netlist_state_t { public: netlist_tool_t(tool_app_t &app, const pstring &aname) - : netlist::netlist_t(aname, plib::make_unique<netlist_tool_callbacks_t>(app)) + : netlist::netlist_state_t(aname, plib::make_unique<netlist_tool_callbacks_t>(app)) { } - netlist::setup_t &setup() { return nlstate().setup(); } - void read_netlist(const pstring &filename, const pstring &name, const std::vector<pstring> &logs, const std::vector<pstring> &defines, @@ -254,19 +252,19 @@ public: run_state_manager().pre_save(); std::size_t size = 0; for (auto const & s : run_state_manager().save_list()) - size += s->m_dt.size * s->m_count; + size += s->dt().size() * s->count(); std::vector<char> buf(size); char *p = buf.data(); for (auto const & s : run_state_manager().save_list()) { - std::size_t sz = s->m_dt.size * s->m_count; - if (s->m_dt.is_float || s->m_dt.is_integral) - std::copy(static_cast<char *>(s->m_ptr), - static_cast<char *>(s->m_ptr) + sz, p); + std::size_t sz = s->dt().size() * s->count(); + if (s->dt().is_float() || s->dt().is_integral()) + std::copy(static_cast<char *>(s->ptr()), + static_cast<char *>(s->ptr()) + sz, p); else - log().fatal("found unsupported save element {1}\n", s->m_name); + log().fatal("found unsupported save element {1}\n", s->name()); p += sz; } return buf; @@ -276,7 +274,7 @@ public: { std::size_t size = 0; for (auto const & s : run_state_manager().save_list()) - size += s->m_dt.size * s->m_count; + size += s->dt().size() * s->count(); if (buf.size() != size) plib::pthrow<netlist::nl_exception>("Size different during load state."); @@ -285,15 +283,15 @@ public: for (auto const & s : run_state_manager().save_list()) { - std::size_t sz = s->m_dt.size * s->m_count; - if (s->m_dt.is_float || s->m_dt.is_integral) - std::copy(p, p + sz, static_cast<char *>(s->m_ptr)); + std::size_t sz = s->dt().size() * s->count(); + if (s->dt().is_float() || s->dt().is_integral()) + std::copy(p, p + sz, static_cast<char *>(s->ptr())); else - log().fatal("found unsupported save element {1}\n", s->m_name); + log().fatal("found unsupported save element {1}\n", s->name()); p += sz; } run_state_manager().post_load(); - nlstate().rebuild_lists(); + this->rebuild_lists(); } protected: @@ -388,7 +386,7 @@ void tool_app_t::run() auto t_guard(t.guard()); //plib::perftime_t<plib::exact_ticks> t; - nt.enable_stats(opt_stats()); + nt.exec().enable_stats(opt_stats()); if (!opt_verb()) nt.log().verbose.set_enabled(false); @@ -399,7 +397,7 @@ void tool_app_t::run() opt_logs(), m_defines, opt_rfolders(), opt_includes()); - nt.reset(); + nt.exec().reset(); inps = read_input(nt.setup(), opt_inp()); ttr = netlist::netlist_time::from_fp(opt_ttr()); @@ -410,7 +408,7 @@ void tool_app_t::run() t.reset(); - netlist::netlist_time nlt = nt.time(); + netlist::netlist_time nlt = nt.exec().time(); { auto t_guard(t.guard()); @@ -425,7 +423,7 @@ void tool_app_t::run() std::vector<char> loadstate; reader.read(loadstate); nt.load_state(loadstate); - pout("Loaded state, run will continue at {1:.6f}\n", nt.time().as_double()); + pout("Loaded state, run will continue at {1:.6f}\n", nt.exec().time().as_double()); } unsigned pos = 0; @@ -435,7 +433,7 @@ void tool_app_t::run() && inps[pos].m_time < ttr && inps[pos].m_time >= nlt) { - nt.process_queue(inps[pos].m_time - nlt); + nt.exec().process_queue(inps[pos].m_time - nlt); inps[pos].setparam(); nlt = inps[pos].m_time; pos++; @@ -444,7 +442,7 @@ void tool_app_t::run() pout("runnning ...\n"); if (ttr > nlt) - nt.process_queue(ttr - nlt); + nt.exec().process_queue(ttr - nlt); else { pout("end time {1:.6f} less than saved time {2:.6f}\n", @@ -463,7 +461,7 @@ void tool_app_t::run() plib::pbinary_writer writer(strm); writer.write(savestate); } - nt.stop(); + nt.exec().stop(); } auto emutime(t.as_seconds<nl_fptype>()); @@ -526,11 +524,11 @@ void tool_app_t::static_compile() // need to reset ... - nt.reset(); + nt.exec().reset(); std::map<pstring, pstring> mp; - nt.solver()->create_solver_code(mp); + nt.exec().solver()->create_solver_code(mp); for (auto &e : mp) { @@ -538,7 +536,7 @@ void tool_app_t::static_compile() sout << e.second; } - nt.stop(); + nt.exec().stop(); } @@ -758,7 +756,7 @@ void tool_app_t::create_header() } pout("#endif // __PLIB_PREPROCESSOR__\n"); pout("#endif\n"); - nt.stop(); + nt.exec().stop(); } @@ -875,7 +873,7 @@ void tool_app_t::create_docheader() } } } - nt.stop(); + nt.exec().stop(); } @@ -904,7 +902,7 @@ void tool_app_t::listdevices() pstring out = plib::pfmt("{1:-20} {2}(<id>")(f->classname())(f->name()); f->macro_actions(nt.setup(), f->name() + "_lc"); - auto d = f->Create(nt.nlstate(), f->name() + "_lc"); + auto d = f->Create(nt.pool(), nt, f->name() + "_lc"); // get the list of terminals ... std::vector<pstring> terms(nt.setup().get_terminals_for_device_name(d->name())); diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 1b6340a0dbc..5bd4be1e096 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -109,7 +109,7 @@ namespace solver { pstring nname(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()))); nl_assert(p->net().is_analog()); - auto net_proxy_output_u = pool().make_unique<proxied_analog_output_t>(*this, nname, static_cast<analog_net_t *>(&p->net())); + auto net_proxy_output_u = state().make_object<proxied_analog_output_t>(*this, nname, static_cast<analog_net_t *>(&p->net())); net_proxy_output = net_proxy_output_u.get(); m_inps.emplace_back(std::move(net_proxy_output_u)); } @@ -336,7 +336,6 @@ namespace solver { pstring num = plib::pfmt("{1}")(k); - // FIXME: This shouldn't be necessary, recalculate on each entry ... state().save(*this, m_gonn[k],"GO" + num, this->name(), m_terms[k].count()); state().save(*this, m_gtn[k],"GT" + num, this->name(), m_terms[k].count()); state().save(*this, m_Idrn[k],"IDR" + num, this->name(), m_terms[k].count()); |