summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/nl_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/nl_base.cpp')
-rw-r--r--src/lib/netlist/nl_base.cpp239
1 files changed, 111 insertions, 128 deletions
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 80acf9847a3..4374ef2212d 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -6,6 +6,7 @@
*/
#include <cstring>
+#include <cmath>
#include "solver/nld_matrix_solver.h"
#include "solver/nld_solver.h"
@@ -25,7 +26,7 @@ namespace netlist
namespace detail
{
#if (USE_MEMPOOL)
-static plib::mempool pool(65536, 8);
+static plib::mempool pool(6553600, 64);
void * object_t::operator new (size_t size)
{
@@ -135,24 +136,6 @@ const logic_family_desc_t *family_CD4XXX()
return &obj;
}
-class logic_family_std_proxy_t : public logic_family_desc_t
-{
-public:
- logic_family_std_proxy_t() { }
- virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
- const pstring &name, logic_output_t *proxied) const override;
- virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
-};
-
-plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
- const pstring &name, logic_output_t *proxied) const
-{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
-}
-plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
-{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
-}
// ----------------------------------------------------------------------------------------
// queue_t
@@ -199,10 +182,10 @@ void detail::queue_t::on_post_load()
netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
for (std::size_t i = 0; i < m_qsize; i++ )
{
- detail::net_t *n = netlist().find_net(m_names[i].m_buf);
+ detail::net_t *n = netlist().find_net(pstring(m_names[i].m_buf, pstring::UTF8));
//log().debug("Got {1} ==> {2}\n", qtemp[i].m_name, n));
//log().debug("schedule time {1} ({2})\n", n->time().as_double(), netlist_time::from_raw(m_times[i]).as_double()));
- this->push(n, netlist_time::from_raw(m_times[i]));
+ this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
@@ -234,24 +217,22 @@ detail::device_object_t::device_object_t(core_device_t &dev, const pstring &anam
{
}
-detail::device_object_t::type_t detail::device_object_t::type() const
+detail::terminal_type detail::core_terminal_t::type() const
{
if (dynamic_cast<const terminal_t *>(this) != nullptr)
- return type_t::TERMINAL;
- else if (dynamic_cast<const param_t *>(this) != nullptr)
- return param_t::PARAM;
+ return terminal_type::TERMINAL;
else if (dynamic_cast<const logic_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return terminal_type::INPUT;
else if (dynamic_cast<const logic_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return terminal_type::OUTPUT;
else if (dynamic_cast<const analog_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return terminal_type::INPUT;
else if (dynamic_cast<const analog_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return terminal_type::OUTPUT;
else
{
netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
- return type_t::TERMINAL; // please compiler
+ return terminal_type::TERMINAL; // please compiler
}
}
@@ -272,19 +253,16 @@ netlist_t::netlist_t(const pstring &aname)
{
state().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
state().save_item(this, m_time, "m_time");
- m_setup = new setup_t(*this);
+ m_setup = plib::make_unique<setup_t>(*this);
/* FIXME: doesn't really belong here */
NETLIST_NAME(base)(*m_setup);
}
netlist_t::~netlist_t()
{
- if (m_setup != nullptr)
- delete m_setup;
m_nets.clear();
m_devices.clear();
- pfree(m_lib);
pstring::resetmem();
}
@@ -303,48 +281,18 @@ void netlist_t::register_dev(plib::owned_ptr<core_device_t> dev)
void netlist_t::remove_dev(core_device_t *dev)
{
- m_devices.erase(
- std::remove_if(
- m_devices.begin(),
+ m_devices.erase(
+ std::remove_if(
+ m_devices.begin(),
m_devices.end(),
- [&] (plib::owned_ptr<core_device_t> const& p)
- {
- return p.get() == dev;
- }),
+ [&] (plib::owned_ptr<core_device_t> const& p)
+ {
+ return p.get() == dev;
+ }),
m_devices.end()
- );
+ );
}
-const logic_family_desc_t *netlist_t::family_from_model(const pstring &model)
-{
- model_map_t map;
- setup().model_parse(model, map);
-
- if (setup().model_value_str(map, "TYPE") == "TTL")
- return family_TTL();
- if (setup().model_value_str(map, "TYPE") == "CD4XXX")
- return family_CD4XXX();
-
- for (auto & e : m_family_cache)
- if (e.first == model)
- return e.second.get();
-
- auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
-
- ret->m_fixed_V = setup().model_value(map, "FV");
- ret->m_low_thresh_PCNT = setup().model_value(map, "IVL");
- ret->m_high_thresh_PCNT = setup().model_value(map, "IVH");
- ret->m_low_VO = setup().model_value(map, "OVL");
- ret->m_high_VO = setup().model_value(map, "OVH");
- ret->m_R_low = setup().model_value(map, "ORL");
- ret->m_R_high = setup().model_value(map, "ORH");
-
- auto retp = ret.get();
-
- m_family_cache.emplace_back(model, std::move(ret));
-
- return retp;
-}
void netlist_t::start()
@@ -372,6 +320,7 @@ void netlist_t::start()
/* create devices */
+ log().debug("Creating devices ...\n");
for (auto & e : setup().m_device_factory)
{
if ( !setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
@@ -394,9 +343,12 @@ void netlist_t::start()
auto p = setup().m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
if (p != setup().m_param_values.end())
{
- //FIXME: Error checking
- auto v = p->second.as_long();
- d->set_hint_deactivate(!v);
+ //FIXME: turn this into a proper function
+ bool error;
+ auto v = p->second.as_double(&error);
+ if (error || std::abs(v - std::floor(v)) > 1e-6 )
+ log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
+ d->set_hint_deactivate(v == 0.0);
}
}
else
@@ -404,11 +356,30 @@ void netlist_t::start()
}
pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
- m_lib = plib::palloc<plib::dynlib>(libpath);
+ m_lib = plib::make_unique<plib::dynlib>(libpath);
/* resolve inputs */
setup().resolve_inputs();
+ /* Make sure devices are fully created - now done in register_dev */
+
+ log().debug("Setting delegate pointers ...\n");
+ for (auto &dev : m_devices)
+ dev->set_delegate_pointer();
+
+ log().verbose("looking for two terms connected to rail nets ...");
+ for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
+ {
+ if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
+ {
+ log().warning(MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3,
+ t->name(), t->m_N.net().name(), t->m_P.net().name());
+ t->m_N.net().remove_terminal(t->m_N);
+ t->m_P.net().remove_terminal(t->m_P);
+ remove_dev(t);
+ }
+ }
+
log().verbose("initialize solver ...\n");
if (m_solver == nullptr)
@@ -420,12 +391,6 @@ void netlist_t::start()
else
m_solver->post_start();
- /* finally, set the pointers */
-
- log().debug("Setting delegate pointers ...\n");
- for (auto &dev : m_devices)
- dev->set_delegate_pointer();
-
}
void netlist_t::stop()
@@ -433,7 +398,8 @@ void netlist_t::stop()
log().debug("Printing statistics ...\n");
print_stats();
log().debug("Stopping solver device ...\n");
- m_solver->stop();
+ if (m_solver != nullptr)
+ m_solver->stop();
}
detail::net_t *netlist_t::find_net(const pstring &name)
@@ -474,16 +440,16 @@ void netlist_t::reset()
dev->update_param();
// Step all devices once !
+ /*
+ * INFO: The order here affects power up of e.g. breakout. However, such
+ * variations are explicitly stated in the breakout manual.
+ */
#if 0
for (std::size_t i = 0; i < m_devices.size(); i++)
{
m_devices[i]->update_dev();
}
#else
- /* FIXME: this makes breakout attract mode working again.
- * It is however not acceptable that this depends on the startup order.
- * Best would be, if reset would call update_dev for devices which need it.
- */
std::size_t i = m_devices.size();
while (i>0)
m_devices[--i]->update_dev();
@@ -495,7 +461,7 @@ void netlist_t::process_queue(const netlist_time &delta)
{
netlist_time stop(m_time + delta);
- m_queue.push(nullptr, stop);
+ m_queue.push(detail::queue_t::entry_t(stop, nullptr));
m_stat_mainloop.start();
@@ -522,17 +488,20 @@ void netlist_t::process_queue(const netlist_time &delta)
while (m_queue.top().m_exec_time > mc_time)
{
m_time = mc_time;
- mc_time += inc;
mc_net.toggle_new_Q();
mc_net.update_devs();
+ mc_time += inc;
}
const detail::queue_t::entry_t e(m_queue.pop());
m_time = e.m_exec_time;
- if (e.m_object == nullptr)
+ if (e.m_object != nullptr)
+ {
+ e.m_object->update_devs();
+ m_perf_out_processed.inc();
+ }
+ else
break;
- e.m_object->update_devs();
- m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
@@ -599,6 +568,21 @@ void netlist_t::print_stats() const
}
}
+core_device_t *netlist_t::pget_single_device(const pstring classname, bool (*cc)(core_device_t *))
+{
+ core_device_t *ret = nullptr;
+ for (auto &d : m_devices)
+ {
+ if (cc(d.get()))
+ {
+ if (ret != nullptr)
+ this->log().fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
+ else
+ ret = d.get();
+ }
+ }
+ return ret;
+}
// ----------------------------------------------------------------------------------------
@@ -610,7 +594,7 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -623,7 +607,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner.netlist())
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -639,17 +623,16 @@ core_device_t::~core_device_t()
void core_device_t::set_delegate_pointer()
{
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = pFunc;
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
- m_static_update = plib::mfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
+#if (!NL_USE_PMF_VIRTUAL)
+ m_static_update.set_base(&core_device_t::update, this);
#endif
}
+plib::plog_base<NL_DEBUG> &core_device_t::log()
+{
+ return netlist().log();
+}
+
// ----------------------------------------------------------------------------------------
// device_t
// ----------------------------------------------------------------------------------------
@@ -697,7 +680,7 @@ void device_t::connect(const pstring &t1, const pstring &t2)
void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2)
{
if (!setup().connect(t1, t2))
- netlist().log().fatal(MF_2_ERROR_CONNECTING_1_TO_2, t1.name(), t2.name());
+ log().fatal(MF_2_ERROR_CONNECTING_1_TO_2, t1.name(), t2.name());
}
@@ -705,9 +688,9 @@ void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_term
// family_setter_t
// -----------------------------------------------------------------------------
-detail::family_setter_t::family_setter_t(core_device_t &dev, const char *desc)
+detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring desc)
{
- dev.set_logic_family(dev.netlist().family_from_model(desc));
+ dev.set_logic_family(dev.netlist().setup().family_from_model(desc));
}
detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc)
@@ -719,13 +702,6 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-// FIXME: move somewhere central
-
-struct do_nothing_deleter{
- template<typename T> void operator()(T*){}
-};
-
-
detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
: object_t(aname)
, netlist_ref(nl)
@@ -734,10 +710,9 @@ detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
, m_time(*this, "m_time", netlist_time::zero())
, m_active(*this, "m_active", 0)
, m_in_queue(*this, "m_in_queue", 2)
- , m_railterminal(nullptr)
, m_cur_Analog(*this, "m_cur_Analog", 0.0)
+ , m_railterminal(mr)
{
- m_railterminal = mr;
}
detail::net_t::~net_t()
@@ -758,7 +733,7 @@ void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
if (m_time > netlist().time())
{
m_in_queue = 1; /* pending */
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
else
{
@@ -968,16 +943,20 @@ terminal_t::~terminal_t()
void terminal_t::schedule_solve()
{
- // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
- if (net().solver() != nullptr)
- net().solver()->update_forced();
+ // Nets may belong to railnets which do not have a solver attached
+ // FIXME: Enforce that all terminals get connected?
+ if (this->has_net())
+ if (net().solver() != nullptr)
+ net().solver()->update_forced();
}
void terminal_t::schedule_after(const netlist_time &after)
{
- // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
- if (net().solver() != nullptr)
- net().solver()->update_after(after);
+ // Nets may belong to railnets which do not have a solver attached
+ // FIXME: Enforce that all terminals get connected?
+ if (this->has_net())
+ if (net().solver() != nullptr)
+ net().solver()->update_after(after);
}
// ----------------------------------------------------------------------------------------
@@ -1037,7 +1016,7 @@ analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(&m_my_net, false));
this->set_net(&m_my_net);
- net().m_cur_Analog = NL_FCONST(0.0);
+ //net().m_cur_Analog = NL_FCONST(0.0);
netlist().setup().register_term(*this);
}
@@ -1047,7 +1026,7 @@ analog_output_t::~analog_output_t()
void analog_output_t::initial(const nl_double val)
{
- net().m_cur_Analog = val;
+ net().set_Q_Analog(val);
}
// -----------------------------------------------------------------------------
@@ -1133,11 +1112,11 @@ param_double_t::param_double_t(device_t &device, const pstring name, const doubl
m_param = device.setup().get_initial_param_val(this->name(),val);
netlist().save(*this, m_param, "m_param");
}
-
+#if 0
param_double_t::~param_double_t()
{
}
-
+#endif
param_int_t::param_int_t(device_t &device, const pstring name, const int val)
: param_t(device, name)
{
@@ -1145,9 +1124,11 @@ param_int_t::param_int_t(device_t &device, const pstring name, const int val)
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_int_t::~param_int_t()
{
}
+#endif
param_logic_t::param_logic_t(device_t &device, const pstring name, const bool val)
: param_t(device, name)
@@ -1156,9 +1137,11 @@ param_logic_t::param_logic_t(device_t &device, const pstring name, const bool va
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_logic_t::~param_logic_t()
{
}
+#endif
param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
: param_t(device, name)
@@ -1167,13 +1150,15 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
//netlist().save(*this, m_param, "m_param");
}
+#if 0
param_ptr_t::~param_ptr_t()
{
}
+#endif
void param_model_t::changed()
{
- netlist().log().fatal("Models can not be changed at runtime");
+ netlist().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
m_map.clear();
}
@@ -1200,8 +1185,6 @@ std::unique_ptr<plib::pistream> param_data_t::stream()
return device().netlist().setup().get_data_stream(Value());
}
-
-
namespace devices
{
// ----------------------------------------------------------------------------------------