netlist: code maintenance. (nw)

Simplification, remove some trampolines.
This commit is contained in:
couriersud 2019-10-30 19:10:40 +01:00
parent 3ff1066d43
commit beab34006a
13 changed files with 141 additions and 140 deletions

View File

@ -522,7 +522,7 @@ public:
if (i != m_num_channels)
state().log().fatal("sound input numbering has to be sequential!");
m_num_channels++;
m_channels[i].m_param = dynamic_cast<netlist::param_double_t *>(setup().find_param((*m_channels[i].m_param_name)(), true));
m_channels[i].m_param = dynamic_cast<netlist::param_double_t *>(state().setup().find_param((*m_channels[i].m_param_name)(), true));
}
}
}

View File

@ -41,7 +41,7 @@ namespace netlist
logic_output_t m_DO;
state_array<uint8_t, 128> m_ram; // 1024x1 bits
state_container<std::array<uint8_t, 128>> m_ram; // 1024x1 bits
param_ptr_t m_RAM;
nld_power_pins m_power_pins;
};

View File

@ -76,7 +76,7 @@ namespace netlist
logic_input_t m_DIN;
logic_output_t m_DOUTQ;
state_array<uint64_t, 4> m_ram; // 256 bits
state_container<std::array<uint64_t, 4>> m_ram; // 256 bits
state_var_u8 m_addr; // 256 bits
state_var_sig m_enq;
nld_power_pins m_power_pins;

View File

@ -32,7 +32,7 @@ namespace netlist
logic_input_t m_RC;
logic_input_t m_IN;
state_array<uint16_t, 5> m_buffer;
state_container<std::array<uint16_t, 5>> m_buffer;
logic_output_t m_OUT;
nld_power_pins m_power_pins;

View File

@ -92,9 +92,9 @@ namespace netlist
for (auto & pwr_sym : power_syms)
{
pstring devname = out_proxied->device().name();
auto tp_t = setup().find_terminal(devname + "." + pwr_sym.first,
auto tp_t = state().setup().find_terminal(devname + "." + pwr_sym.first,
/*detail::terminal_type::INPUT,*/ false);
auto tn_t = setup().find_terminal(devname + "." + pwr_sym.second,
auto tn_t = state().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() == 0.0)
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name())));
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name())));
else
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name())));
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().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 (setup().is_extended_validation())
if (state().setup().is_extended_validation())
{
// During validation, don't connect to terminals found
// This will cause terminals not connected to a rail net to

View File

@ -231,7 +231,7 @@ namespace devices
/* make sure we get the family first */
, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
{
set_logic_family(setup().family_from_model(m_FAMILY()));
set_logic_family(state().setup().family_from_model(m_FAMILY()));
m_Q.set_logic_family(this->logic_family());
}
@ -438,7 +438,7 @@ namespace devices
nld_power_pins(device_t &owner, const pstring &sVCC = "VCC",
const pstring &sGND = "GND", bool force_analog_input = false)
{
if (owner.setup().is_extended_validation() || force_analog_input)
if (owner.state().setup().is_extended_validation() || force_analog_input)
{
m_GND = plib::make_unique<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop));
m_VCC = plib::make_unique<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop));

View File

@ -561,7 +561,7 @@ namespace netlist
: core_device_t(owner, name)
{
}
#if 0
setup_t &device_t::setup() noexcept
{
return state().setup();
@ -571,13 +571,14 @@ namespace netlist
{
return state().setup();
}
#endif
void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term)
{
pstring alias = this->name() + "." + name;
// everything already fully qualified
setup().register_alias_nofqn(alias, term.name());
state().setup().register_alias_nofqn(alias, term.name());
}
void device_t::register_subalias(const pstring &name, const pstring &aliased)
@ -586,17 +587,17 @@ namespace netlist
pstring aliased_fqn = this->name() + "." + aliased;
// everything already fully qualified
setup().register_alias_nofqn(alias, aliased_fqn);
state().setup().register_alias_nofqn(alias, aliased_fqn);
}
void device_t::connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2)
{
setup().register_link_fqn(t1.name(), t2.name());
state().setup().register_link_fqn(t1.name(), t2.name());
}
void device_t::connect(const pstring &t1, const pstring &t2)
{
setup().register_link_fqn(name() + "." + t1, name() + "." + t2);
state().setup().register_link_fqn(name() + "." + t1, name() + "." + t2);
}
/* FIXME: this is only used by solver code since matrix solvers are started in
@ -604,7 +605,7 @@ namespace netlist
*/
void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2)
{
if (!setup().connect(t1, t2))
if (!state().setup().connect(t1, t2))
log().fatal(MF_ERROR_CONNECTING_1_TO_2(t1.name(), t2.name()));
}
@ -620,7 +621,7 @@ namespace netlist
detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring &desc)
{
dev.set_logic_family(dev.setup().family_from_model(desc));
dev.set_logic_family(dev.state().setup().family_from_model(desc));
}
detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc)
@ -870,7 +871,7 @@ namespace netlist
param_t::param_t(device_t &device, const pstring &name)
: device_object_t(device, device.name() + "." + name)
{
device.setup().register_param_t(this->name(), *this);
device.state().setup().register_param_t(this->name(), *this);
}
param_t::param_type_t param_t::param_type() const
@ -900,7 +901,7 @@ namespace netlist
pstring param_t::get_initial(const device_t &dev, bool *found)
{
pstring res = dev.setup().get_initial_param_val(this->name(), "");
pstring res = dev.state().setup().get_initial_param_val(this->name(), "");
*found = (res != "");
return res;
}
@ -913,7 +914,7 @@ namespace netlist
param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val)
: param_t(device, name)
{
m_param = device.setup().get_initial_param_val(this->name(),val);
m_param = device.state().setup().get_initial_param_val(this->name(),val);
}
void param_str_t::changed()
@ -945,7 +946,7 @@ namespace netlist
plib::unique_ptr<std::istream> param_data_t::stream()
{
return device().setup().get_data_stream(str());
return device().state().setup().get_data_stream(str());
}
bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT

View File

@ -187,20 +187,13 @@ namespace netlist
namespace devices
{
class matrix_solver_t;
class NETLIB_NAME(gnd);
class NETLIB_NAME(solver);
class NETLIB_NAME(mainclock);
class NETLIB_NAME(netlistparams);
class NETLIB_NAME(base_proxy);
class NETLIB_NAME(base_d_to_a_proxy);
class NETLIB_NAME(base_a_to_d_proxy);
} // namespace devices
namespace detail {
struct family_setter_t;
class queue_t;
} // namespace detail
class logic_output_t;
class logic_input_t;
class analog_net_t;
@ -210,7 +203,6 @@ namespace netlist
class netlist_state_t;
class core_device_t;
class device_t;
class callbacks_t;
//============================================================
// Exceptions
@ -351,24 +343,32 @@ namespace netlist
* Use this state_var template to define an array whose contents are saved.
* Please refer to \ref state_var.
*/
template <typename T, std::size_t N>
struct state_array : public std::array<T, N>
template <typename C>
struct state_container : public C
{
public:
using value_type = typename C::value_type;
//! Constructor.
template <typename O>
state_array(O &owner, //!< owner must have a netlist() method.
const pstring &name, //!< identifier/name for this state variable
const T &value //!< Initial value after construction
state_container(O &owner, //!< owner must have a netlist() method.
const pstring &name, //!< identifier/name for this state variable
const value_type &value //!< Initial value after construction
);
//! Constructor.
template <typename O>
state_container(O &owner, //!< owner must have a netlist() method.
const pstring &name, //!< identifier/name for this state variable
std::size_t n, //!< number of elements to allocate
const value_type &value //!< Initial value after construction
);
//! Copy Constructor.
state_array(const state_array &rhs) noexcept = default;
state_container(const state_container &rhs) noexcept = default;
//! Destructor.
~state_array() noexcept = default;
~state_container() noexcept = default;
//! Move Constructor.
state_array(state_array &&rhs) noexcept = default;
state_array &operator=(const state_array &rhs) noexcept = default;
state_array &operator=(state_array &&rhs) noexcept = default;
state_container(state_container &&rhs) noexcept = default;
state_container &operator=(const state_container &rhs) noexcept = default;
state_container &operator=(state_container &&rhs) noexcept = default;
};
// -----------------------------------------------------------------------------
@ -471,9 +471,6 @@ namespace netlist
netlist_state_t & state() noexcept;
const netlist_state_t & state() const noexcept;
setup_t & setup() noexcept;
const setup_t & setup() const noexcept;
netlist_t & exec() noexcept { return m_netlist; }
const netlist_t & exec() const noexcept { return m_netlist; }
@ -1244,9 +1241,6 @@ namespace netlist
~device_t() noexcept override = default;
setup_t &setup() noexcept;
const setup_t &setup() const noexcept;
template<class C, typename... Args>
void create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args)
{
@ -1271,62 +1265,66 @@ namespace netlist
// family_setter_t
// -----------------------------------------------------------------------------
struct detail::family_setter_t
{
/* clang will complain about an unused private field if
* a defaulted constructor is used
namespace detail {
struct family_setter_t
{
/* clang will complain about an unused private field if
* a defaulted constructor is used
*/
// NOLINTNEXTLINE(modernize-use-equals-default)
family_setter_t();
family_setter_t(core_device_t &dev, const pstring &desc);
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
};
template <class T, bool TS>
using timed_queue = plib::timed_queue_linear<T, TS>;
/* Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
* This slows down processing by about 25% on a Kaby Lake.
*/
// NOLINTNEXTLINE(modernize-use-equals-default)
family_setter_t();
family_setter_t(core_device_t &dev, const pstring &desc);
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
};
template <class T, bool TS>
using timed_queue = plib::timed_queue_linear<T, TS>;
//template <class T, bool TS>
//using timed_queue = timed_queue_heap<T, TS>;
/* Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
* This slows down processing by about 25% on a Kaby Lake.
*/
// -----------------------------------------------------------------------------
// queue_t
// -----------------------------------------------------------------------------
//template <class T, bool TS>
//using timed_queue = timed_queue_heap<T, TS>;
/* We don't need a thread-safe queue currently. Parallel processing of
* solvers will update inputs after parallel processing.
*/
class queue_t :
//public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
public timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>,
public netlist_ref,
public plib::state_manager_t::callback_t
{
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);
virtual ~queue_t() noexcept = default;
// -----------------------------------------------------------------------------
// queue_t
// -----------------------------------------------------------------------------
queue_t(const queue_t &) = delete;
queue_t(queue_t &&) = delete;
queue_t &operator=(const queue_t &) = delete;
queue_t &operator=(queue_t &&) = delete;
/* We don't need a thread-safe queue currently. Parallel processing of
* solvers will update inputs after parallel processing.
*/
class detail::queue_t :
//public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
public timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>,
public detail::netlist_ref,
public plib::state_manager_t::callback_t
{
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);
virtual ~queue_t() noexcept = default;
protected:
queue_t(const queue_t &) = delete;
queue_t(queue_t &&) = delete;
queue_t &operator=(const queue_t &) = delete;
queue_t &operator=(queue_t &&) = delete;
void register_state(plib::state_manager_t &manager, const pstring &module) override;
void on_pre_save(plib::state_manager_t &manager) override;
void on_post_load(plib::state_manager_t &manager) override;
protected:
private:
std::size_t m_qsize;
std::vector<netlist_time::internal_type> m_times;
std::vector<std::size_t> m_net_ids;
};
void register_state(plib::state_manager_t &manager, const pstring &module) override;
void on_pre_save(plib::state_manager_t &manager) override;
void on_post_load(plib::state_manager_t &manager) override;
private:
std::size_t m_qsize;
std::vector<netlist_time::internal_type> m_times;
std::vector<std::size_t> m_net_ids;
};
}
// -----------------------------------------------------------------------------
// netlist_state__t
@ -1666,16 +1664,6 @@ namespace netlist
return m_netlist.nlstate();
}
inline setup_t & detail::netlist_ref::setup() noexcept
{
return m_netlist.nlstate().setup();
}
inline const setup_t & detail::netlist_ref::setup() const noexcept
{
return m_netlist.nlstate().setup();
}
template <typename T>
param_num_t<T>::param_num_t(device_t &device, const pstring &name, const T val)
: param_t(device, name)
@ -1909,15 +1897,25 @@ namespace netlist
owner.state().save(owner, m_value, owner.name(), name);
}
template <typename T, std::size_t N>
template <typename C>
template <typename O>
state_array<T,N>::state_array(O &owner, const pstring &name, const T & value)
state_container<C>::state_container(O &owner, const pstring &name,
const state_container<C>::value_type & value)
{
owner.state().save(owner, *static_cast<std::array<T, N> *>(this), owner.name(), name);
for (std::size_t i=0; i<N; i++)
owner.state().save(owner, *static_cast<C *>(this), owner.name(), name);
for (std::size_t i=0; i < this->size(); i++)
(*this)[i] = value;
}
template <typename C>
template <typename O>
state_container<C>::state_container(O &owner, const pstring &name,
std::size_t n, const state_container<C>::value_type & value)
: C(n, value)
{
owner.state().save(owner, *static_cast<C *>(this), owner.name(), name);
}
// -----------------------------------------------------------------------------
// Hot section
//

View File

@ -94,15 +94,8 @@
// Use nano-second resolution - Sufficient for now
static constexpr const auto NETLIST_INTERNAL_RES = 1000000000;
//static constexpr const auto NETLIST_INTERNAL_RES = 1000000000000;
static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES;
//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000))
//#define NETLIST_CLOCK (NETLIST_INTERNAL_RES)
//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000000))
//#define NETLIST_CLOCK (UINT64_C(1000000000))
//#define nl_double float
using nl_double = double;

View File

@ -83,7 +83,7 @@ public:
state_manager_t() = default;
template<typename C>
template<typename C> //, typename std::enable_if<std::is_integral<C>::value || std::is_floating_point<C>::value>::type>
void save_item(const void *owner, C &state, const pstring &stname)
{
save_state_ptr( owner, stname, dtype<C>(), 1, &state);
@ -101,8 +101,8 @@ public:
save_state_ptr(owner, stname, dtype<C>(), count, state);
}
template<typename C>
void save_item(const void *owner, std::vector<C> &v, const pstring &stname)
template<typename C, typename A>
void save_item(const void *owner, std::vector<C, A> &v, const pstring &stname)
{
save_state_ptr(owner, stname, dtype<C>(), v.size(), v.data());
}

View File

@ -16,10 +16,7 @@ namespace devices
{
terms_for_net_t::terms_for_net_t(analog_net_t * net)
: m_last_V(0.0)
, m_DD_n_m_1(0.0)
, m_h_n_m_1(1e-12)
, m_net(net)
: m_net(net)
, m_railstart(0)
{
}
@ -342,14 +339,19 @@ namespace devices
/*
* save states
*/
m_last_V.resize(iN, plib::constants<nl_double>::zero());
m_DD_n_m_1.resize(iN, plib::constants<nl_double>::zero());
m_h_n_m_1.resize(iN, plib::constants<nl_double>::zero());
state().save(*this, m_last_V.as_base(), this->name(), "m_last_V");
state().save(*this, m_DD_n_m_1.as_base(), this->name(), "m_DD_n_m_1");
state().save(*this, m_h_n_m_1.as_base(), this->name(), "m_h_n_m_1");
for (std::size_t k = 0; k < iN; k++)
{
pstring num = plib::pfmt("{1}")(k);
state().save(*this, m_terms[k].m_last_V, this->name(), "lastV." + num);
state().save(*this, m_terms[k].m_DD_n_m_1, this->name(), "m_DD_n_m_1." + num);
state().save(*this, m_terms[k].m_h_n_m_1, this->name(), "m_h_n_m_1." + num);
// 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());
@ -559,19 +561,21 @@ namespace devices
if (m_params.m_dynamic_ts)
{
for (auto &t : m_terms)
for (std::size_t k = 0; k < m_terms.size(); k++)
{
auto &t = m_terms[k];
//const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
// avoid floating point exceptions
const nl_double DD_n = std::max(-1e100, std::min(1e100,(t.getV() - t.m_last_V)));
const nl_double DD_n = std::max(-1e100, std::min(1e100,(t.getV() - m_last_V[k])));
const nl_double hn = cur_ts;
//printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1);
nl_double DD2 = (DD_n / hn - t.m_DD_n_m_1 / t.m_h_n_m_1) / (hn + t.m_h_n_m_1);
nl_double DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
nl_double new_net_timestep(0);
t.m_h_n_m_1 = hn;
t.m_DD_n_m_1 = DD_n;
m_h_n_m_1[k] = hn;
m_DD_n_m_1[k] = DD_n;
if (std::fabs(DD2) > plib::constants<nl_double>::cast(1e-60)) // avoid div-by-zero
new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(plib::constants<nl_double>::cast(0.5)*DD2));
else
@ -580,7 +584,7 @@ namespace devices
if (new_net_timestep < new_solver_timestep)
new_solver_timestep = new_net_timestep;
t.m_last_V = t.getV();
m_last_V[k] = t.getV();
}
if (new_solver_timestep < m_params.m_min_timestep)
{

View File

@ -136,11 +136,6 @@ namespace devices
plib::aligned_vector<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */
plib::aligned_vector<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
/* state */
nl_double m_last_V;
nl_double m_DD_n_m_1;
nl_double m_h_n_m_1;
plib::aligned_vector<int> m_connected_net_idx;
private:
analog_net_t * m_net;
@ -375,6 +370,17 @@ namespace devices
plib::aligned_vector<terms_for_net_t> m_terms;
plib::aligned_vector<terms_for_net_t> m_rails_temp;
/* state - variable time_stepping */
plib::aligned_vector<nl_double> m_last_V;
plib::aligned_vector<nl_double> m_DD_n_m_1;
plib::aligned_vector<nl_double> m_h_n_m_1;
// FIXME: it should be like this, however dimensions are determined
// in vsetup.
//state_container<std::vector<nl_double>> m_last_V;
//state_container<std::vector<nl_double>> m_DD_n_m_1;
//state_container<std::vector<nl_double>> m_h_n_m_1;
std::vector<unique_pool_ptr<proxied_analog_output_t>> m_inps;
const solver_parameters_t &m_params;
@ -385,6 +391,9 @@ namespace devices
state_var<int> m_iterative_fail;
state_var<int> m_iterative_total;
private:
state_var<netlist_time> m_last_step;

View File

@ -24,10 +24,6 @@ namespace netlist
{
namespace devices
{
class NETLIB_NAME(solver);
class matrix_solver_t;
NETLIB_OBJECT(solver)
{
NETLIB_CONSTRUCTOR(solver)