mirror of
https://github.com/holub/mame
synced 2025-05-08 23:31:54 +03:00
netlist: logic devices now support model parameter. [Couriersud]
This a big forward to allow reuse of code. Still a longer way to go but the foundation there. Also brings quite a number of simplifications and dead code removal.
This commit is contained in:
parent
cd4dc51ea9
commit
227ab3025e
@ -64,8 +64,8 @@ namespace netlist
|
||||
, m_supply(*this)
|
||||
, m_RVI(*this, "RVI")
|
||||
, m_RVO(*this, "RVO")
|
||||
, m_model(*this, "MODEL", "TTL_7414_GATE")
|
||||
, m_modacc(m_model)
|
||||
, m_stmodel(*this, "STMODEL", "TTL_7414_GATE")
|
||||
, m_modacc(m_stmodel)
|
||||
, m_last_state(*this, "m_last_var", 1)
|
||||
{
|
||||
register_subalias("Q", m_RVO.P());
|
||||
@ -117,12 +117,12 @@ namespace netlist
|
||||
NETLIB_NAME(power_pins) m_supply;
|
||||
analog::NETLIB_SUB(twoterm) m_RVI;
|
||||
analog::NETLIB_SUB(twoterm) m_RVO;
|
||||
param_model_t m_model;
|
||||
param_model_t m_stmodel;
|
||||
schmitt_trigger_model_t m_modacc;
|
||||
state_var<int> m_last_state;
|
||||
};
|
||||
|
||||
NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "MODEL")
|
||||
NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "STMODEL")
|
||||
|
||||
} // namespace devices
|
||||
} // namespace netlist
|
||||
|
@ -16,6 +16,6 @@
|
||||
|
||||
#define SCHMITT_TRIGGER(name, model) \
|
||||
NET_REGISTER_DEV(SCHMITT_TRIGGER, name) \
|
||||
NETDEV_PARAMI(name, MODEL, model)
|
||||
NETDEV_PARAMI(name, STMODEL, model)
|
||||
|
||||
#endif /* NLD_SCHMITT_H_ */
|
||||
|
@ -53,14 +53,12 @@ namespace devices
|
||||
, m_feedback(*this, "FB")
|
||||
, m_Q(*this, "Q")
|
||||
, m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
|
||||
, m_model(*this, "MODEL", "FAMILY(TYPE=TTL)")
|
||||
, m_supply(*this)
|
||||
{
|
||||
m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));
|
||||
|
||||
connect(m_feedback, m_Q);
|
||||
}
|
||||
//NETLIB_RESETI();
|
||||
|
||||
NETLIB_UPDATE_PARAMI()
|
||||
{
|
||||
@ -79,7 +77,6 @@ namespace devices
|
||||
param_fp_t m_freq;
|
||||
netlist_time m_inc;
|
||||
|
||||
param_model_t m_model;
|
||||
NETLIB_NAME(power_pins) m_supply;
|
||||
};
|
||||
|
||||
@ -192,12 +189,8 @@ namespace devices
|
||||
NETLIB_CONSTRUCTOR(logic_input)
|
||||
, m_Q(*this, "Q")
|
||||
, m_IN(*this, "IN", false)
|
||||
// make sure we get the family first
|
||||
, m_model(*this, "MODEL", "FAMILY(TYPE=TTL)")
|
||||
, m_supply(*this)
|
||||
{
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
m_Q.set_logic_family(this->logic_family());
|
||||
}
|
||||
|
||||
NETLIB_UPDATEI() { }
|
||||
@ -212,7 +205,6 @@ namespace devices
|
||||
logic_output_t m_Q;
|
||||
|
||||
param_logic_t m_IN;
|
||||
param_model_t m_model;
|
||||
NETLIB_NAME(power_pins) m_supply;
|
||||
};
|
||||
|
||||
@ -222,13 +214,8 @@ namespace devices
|
||||
NETLIB_CONSTRUCTOR(logic_inputN)
|
||||
, m_Q(*this, "Q{}")
|
||||
, m_IN(*this, "IN", 0)
|
||||
// make sure we get the family first
|
||||
, m_model(*this, "model", "MODEL(TYPE=TTL)")
|
||||
, m_supply(*this)
|
||||
{
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
for (auto &q : m_Q)
|
||||
q.set_logic_family(this->logic_family());
|
||||
}
|
||||
|
||||
NETLIB_UPDATEI() { }
|
||||
@ -244,7 +231,6 @@ namespace devices
|
||||
object_array_t<logic_output_t, N> m_Q;
|
||||
|
||||
param_int_t m_IN;
|
||||
param_model_t m_model;
|
||||
NETLIB_NAME(power_pins) m_supply;
|
||||
};
|
||||
|
||||
@ -465,13 +451,8 @@ namespace devices
|
||||
, m_GON(*this, "GON", nlconst::magic(1e9)) // FIXME: all switches should have some on value
|
||||
, m_GOFF(*this, "GOFF", nlconst::cgmin())
|
||||
, m_last_state(*this, "m_last_state", 0)
|
||||
, m_model(*this, "MODEL", "FAMILY(TYPE=TTL)")
|
||||
, m_power_pins(*this)
|
||||
{
|
||||
// Pass on logic family
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
m_I.set_logic_family(this->logic_family());
|
||||
|
||||
// connect and register pins
|
||||
register_subalias("1", m_R1.P());
|
||||
register_subalias("2", m_R1.N());
|
||||
@ -528,7 +509,6 @@ namespace devices
|
||||
|
||||
private:
|
||||
state_var<netlist_sig_t> m_last_state;
|
||||
param_model_t m_model;
|
||||
nld_power_pins m_power_pins;
|
||||
};
|
||||
|
||||
@ -545,14 +525,9 @@ namespace devices
|
||||
, m_IN(*this, "IN")
|
||||
, m_Q(*this, "Q")
|
||||
, m_QQ(*this, "QQ")
|
||||
, m_model(*this, "MODEL", "FAMILY(TYPE=TTL)")
|
||||
, m_power_pins(*this)
|
||||
, m_last_state(*this, "m_last_state", 2) // ensure first execution
|
||||
{
|
||||
// Pass on logic family
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
m_Q.set_logic_family(this->logic_family());
|
||||
m_QQ.set_logic_family(this->logic_family());
|
||||
}
|
||||
|
||||
NETLIB_RESETI()
|
||||
@ -562,7 +537,6 @@ namespace devices
|
||||
|
||||
NETLIB_UPDATEI()
|
||||
{
|
||||
//printf("P %f N %f\n", m_IP(), m_IN());
|
||||
const netlist_sig_t state = (m_IP() > m_IN());
|
||||
if (state != m_last_state)
|
||||
{
|
||||
@ -579,7 +553,6 @@ namespace devices
|
||||
analog_input_t m_IN;
|
||||
logic_output_t m_Q;
|
||||
logic_output_t m_QQ;
|
||||
param_model_t m_model;
|
||||
nld_power_pins m_power_pins;
|
||||
|
||||
private:
|
||||
|
@ -474,7 +474,7 @@ namespace factory
|
||||
truthtable_base_element_t::truthtable_base_element_t(const pstring &name, const pstring &classname,
|
||||
const pstring &def_param, const pstring &sourcefile)
|
||||
: factory::element_t(name, classname, def_param, sourcefile)
|
||||
, m_family_name(NETLIST_DEFAULT_TRUTHTABLE_FAMILY)
|
||||
, m_family_name(NETLIST_DEFAULT_LOGIC_FAMILY)
|
||||
{
|
||||
}
|
||||
|
||||
@ -510,7 +510,7 @@ namespace factory
|
||||
nl_assert_always(false, msg.c_str());
|
||||
}
|
||||
ret->m_desc = desc.desc;
|
||||
ret->m_family_name = (desc.family != "" ? desc.family : pstring(NETLIST_DEFAULT_TRUTHTABLE_FAMILY));
|
||||
ret->m_family_name = (desc.family != "" ? desc.family : pstring(NETLIST_DEFAULT_LOGIC_FAMILY));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -79,11 +79,16 @@ static NETLIST_START(family_models)
|
||||
NET_MODEL("OPAMP _()")
|
||||
NET_MODEL("SCHMITT_TRIGGER _()")
|
||||
|
||||
// TTL: FAMILY(IVL=0.16 IVH=0.4 OVL=0.1 OVH=1.0 ORL=1.0 ORH=130)
|
||||
NET_MODEL("74XX FAMILY(TYPE=TTL IVL=0.16 IVH=0.4 OVL=0.1 OVH=1.0 ORL=1.0 ORH=130)")
|
||||
|
||||
NET_MODEL("74XXOC FAMILY(IVL=0.16 IVH=0.4 OVL=0.1 OVH=0.05 ORL=10.0 ORH=1.0e8)")
|
||||
NET_MODEL("74XX FAMILY(TYPE=TTL)")
|
||||
NET_MODEL("CD4XXX FAMILY(TYPE=CD4XXX)")
|
||||
// CMOS
|
||||
// low input 1.5 , high input trigger 3.5 at 5V supply
|
||||
// output offsets, low for CMOS, thus 0.05
|
||||
// output currents: see https://www.classe.cornell.edu/~ib38/teaching/p360/lectures/wk09/l26/EE2301Exp3F10.pdf
|
||||
// typical CMOS may sink 0.4mA while output stays <= 0.4V
|
||||
NET_MODEL("CD4XXX FAMILY(TYPE=CMOS IVL=0.3 IVH=0.7 OVL=0.05 OVH=0.05 ORL=500 ORH=500)")
|
||||
|
||||
NET_MODEL("74XXOC FAMILY(TYPE=TTL IVL=0.16 IVH=0.4 OVL=0.1 OVH=0.05 ORL=10.0 ORH=1.0e8)")
|
||||
NETLIST_END()
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
@ -159,7 +159,7 @@ NETLIST_START(otheric_lib)
|
||||
TT_LINE(" 0 | 1 |100")
|
||||
TT_LINE(" 1 | 0 |100")
|
||||
// 2.1V negative going and 2.7V positive going at 5V
|
||||
TT_FAMILY("FAMILY(IVL=0.42 IVH=0.54 OVL=0.05 OVH=0.05 ORL=10.0 ORH=10.0)")
|
||||
TT_FAMILY("FAMILY(TYPE=CMOS IVL=0.42 IVH=0.54 OVL=0.05 OVH=0.05 ORL=10.0 ORH=10.0)")
|
||||
TRUTHTABLE_END()
|
||||
|
||||
LOCAL_LIB_ENTRY(MC14584B_DIP)
|
||||
|
@ -25,87 +25,15 @@
|
||||
namespace netlist
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// callbacks_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
plib::unique_ptr<plib::dynlib_base> callbacks_t:: static_solver_lib() const
|
||||
{
|
||||
return plib::make_unique<plib::dynlib_static>(nullptr);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// logic_family_ttl_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default)
|
||||
logic_family_desc_t::logic_family_desc_t()
|
||||
{
|
||||
}
|
||||
|
||||
class logic_family_ttl_t : public logic_family_desc_t
|
||||
{
|
||||
public:
|
||||
logic_family_ttl_t() : logic_family_desc_t()
|
||||
{
|
||||
m_low_thresh_PCNT = nlconst::magic(0.8 / 5.0);
|
||||
m_high_thresh_PCNT = nlconst::magic(2.0 / 5.0);
|
||||
// m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications.
|
||||
m_low_VO = nlconst::magic(0.1);
|
||||
m_high_VO = nlconst::magic(1.0); // 4.0
|
||||
m_R_low = nlconst::magic(1.0);
|
||||
m_R_high = nlconst::magic(130.0);
|
||||
}
|
||||
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, const logic_output_t *proxied) const override;
|
||||
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const override;
|
||||
};
|
||||
|
||||
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, const logic_output_t *proxied) const
|
||||
{
|
||||
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, const logic_input_t *proxied) const
|
||||
{
|
||||
return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
|
||||
}
|
||||
|
||||
class logic_family_cd4xxx_t : public logic_family_desc_t
|
||||
{
|
||||
public:
|
||||
logic_family_cd4xxx_t() : logic_family_desc_t()
|
||||
{
|
||||
m_low_thresh_PCNT = nlconst::magic(1.5 / 5.0);
|
||||
m_high_thresh_PCNT = nlconst::magic(3.5 / 5.0);
|
||||
// m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications.
|
||||
m_low_VO = nlconst::magic(0.05);
|
||||
m_high_VO = nlconst::magic(0.05); // 4.95
|
||||
// https://www.classe.cornell.edu/~ib38/teaching/p360/lectures/wk09/l26/EE2301Exp3F10.pdf
|
||||
// typical CMOS may sink 0.4mA while output stays <= 0.4V
|
||||
m_R_low = nlconst::magic(500.0);
|
||||
m_R_high = nlconst::magic(500.0);
|
||||
}
|
||||
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, const logic_output_t *proxied) const override;
|
||||
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const override;
|
||||
};
|
||||
|
||||
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, const logic_output_t *proxied) const
|
||||
{
|
||||
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, const logic_input_t *proxied) const
|
||||
{
|
||||
return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
|
||||
}
|
||||
|
||||
const logic_family_desc_t *family_TTL()
|
||||
{
|
||||
static logic_family_ttl_t obj;
|
||||
return &obj;
|
||||
}
|
||||
const logic_family_desc_t *family_CD4XXX()
|
||||
{
|
||||
static logic_family_cd4xxx_t obj;
|
||||
return &obj;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// queue_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -445,90 +373,95 @@ namespace netlist
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void netlist_t::print_stats() const
|
||||
{
|
||||
if (m_use_stats)
|
||||
{
|
||||
std::vector<size_t> index;
|
||||
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->stats()->m_stat_total_time.total() < m_state.m_devices[i2].second->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 = entry->stats();
|
||||
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());
|
||||
total_time += stats->m_stat_total_time.total();
|
||||
total_count += stats->m_stat_total_time.count();
|
||||
}
|
||||
|
||||
log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count,
|
||||
total_time, total_time / static_cast<decltype(total_time)>(total_count ? total_count : 1));
|
||||
|
||||
log().verbose("Total loop {1:15}", m_stat_mainloop());
|
||||
log().verbose("Total time {1:15}", total_time);
|
||||
|
||||
// FIXME: clang complains about unreachable code without
|
||||
const auto clang_workaround_unreachable_code = NL_USE_QUEUE_STATS;
|
||||
if (clang_workaround_unreachable_code)
|
||||
{
|
||||
// Only one serialization should be counted in total time
|
||||
// But two are contained in m_stat_mainloop
|
||||
plib::pperftime_t<true> overhead;
|
||||
plib::pperftime_t<true> test;
|
||||
{
|
||||
auto overhead_guard(overhead.guard());
|
||||
for (int j=0; j<100000;j++)
|
||||
{
|
||||
auto test_guard(test.guard());
|
||||
}
|
||||
}
|
||||
|
||||
plib::pperftime_t<true>::type total_overhead = overhead()
|
||||
* static_cast<plib::pperftime_t<true>::type>(total_count)
|
||||
/ static_cast<plib::pperftime_t<true>::type>(200000);
|
||||
|
||||
log().verbose("Queue Pushes {1:15}", m_queue.m_prof_call());
|
||||
log().verbose("Queue Moves {1:15}", m_queue.m_prof_sortmove());
|
||||
log().verbose("Queue Removes {1:15}", m_queue.m_prof_remove());
|
||||
log().verbose("Queue Retimes {1:15}", m_queue.m_prof_retime());
|
||||
log().verbose("");
|
||||
|
||||
log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
|
||||
log().verbose("Total overhead {1:15}", total_overhead);
|
||||
plib::pperftime_t<true>::type overhead_per_pop = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
|
||||
/ static_cast<plib::pperftime_t<true>::type>(m_queue.m_prof_call());
|
||||
log().verbose("Overhead per pop {1:11}", overhead_per_pop );
|
||||
log().verbose("");
|
||||
}
|
||||
|
||||
auto trigger = total_count * 200 / 1000000; // 200 ppm
|
||||
for (auto &entry : m_state.m_devices)
|
||||
{
|
||||
auto *ep = entry.second.get();
|
||||
auto *stats = ep->stats();
|
||||
// Factor of 3 offers best performace increase
|
||||
if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count()
|
||||
&& stats->m_stat_inc_active() > trigger)
|
||||
log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(),
|
||||
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("");
|
||||
netlist_state_t::stats_info si{m_queue, m_stat_mainloop, m_perf_out_processed};
|
||||
m_state.print_stats(si);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void netlist_state_t::print_stats(stats_info &si) const
|
||||
{
|
||||
std::vector<size_t> index;
|
||||
for (size_t i=0; i < this->m_devices.size(); i++)
|
||||
index.push_back(i);
|
||||
|
||||
std::sort(index.begin(), index.end(),
|
||||
[&](size_t i1, size_t i2) { return this->m_devices[i1].second->stats()->m_stat_total_time.total() < this->m_devices[i2].second->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 = this->m_devices[j].second.get();
|
||||
auto *stats = entry->stats();
|
||||
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());
|
||||
total_time += stats->m_stat_total_time.total();
|
||||
total_count += stats->m_stat_total_time.count();
|
||||
}
|
||||
|
||||
log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count,
|
||||
total_time, total_time / static_cast<decltype(total_time)>(total_count ? total_count : 1));
|
||||
|
||||
log().verbose("Total loop {1:15}", si.m_stat_mainloop());
|
||||
log().verbose("Total time {1:15}", total_time);
|
||||
|
||||
// FIXME: clang complains about unreachable code without
|
||||
const auto clang_workaround_unreachable_code = NL_USE_QUEUE_STATS;
|
||||
if (clang_workaround_unreachable_code)
|
||||
{
|
||||
// Only one serialization should be counted in total time
|
||||
// But two are contained in m_stat_mainloop
|
||||
plib::pperftime_t<true> overhead;
|
||||
plib::pperftime_t<true> test;
|
||||
{
|
||||
auto overhead_guard(overhead.guard());
|
||||
for (int j=0; j<100000;j++)
|
||||
{
|
||||
auto test_guard(test.guard());
|
||||
}
|
||||
}
|
||||
|
||||
plib::pperftime_t<true>::type total_overhead = overhead()
|
||||
* static_cast<plib::pperftime_t<true>::type>(total_count)
|
||||
/ static_cast<plib::pperftime_t<true>::type>(200000);
|
||||
|
||||
log().verbose("Queue Pushes {1:15}", si.m_queue.m_prof_call());
|
||||
log().verbose("Queue Moves {1:15}", si.m_queue.m_prof_sortmove());
|
||||
log().verbose("Queue Removes {1:15}", si.m_queue.m_prof_remove());
|
||||
log().verbose("Queue Retimes {1:15}", si.m_queue.m_prof_retime());
|
||||
log().verbose("");
|
||||
|
||||
log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
|
||||
log().verbose("Total overhead {1:15}", total_overhead);
|
||||
plib::pperftime_t<true>::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
|
||||
/ static_cast<plib::pperftime_t<true>::type>(si.m_queue.m_prof_call());
|
||||
log().verbose("Overhead per pop {1:11}", overhead_per_pop );
|
||||
log().verbose("");
|
||||
}
|
||||
|
||||
auto trigger = total_count * 200 / 1000000; // 200 ppm
|
||||
for (auto &entry : this->m_devices)
|
||||
{
|
||||
auto *ep = entry.second.get();
|
||||
auto *stats = ep->stats();
|
||||
// Factor of 3 offers best performace increase
|
||||
if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count()
|
||||
&& stats->m_stat_inc_active() > trigger)
|
||||
log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(),
|
||||
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("");
|
||||
}
|
||||
|
||||
core_device_t *netlist_state_t::get_single_device(const pstring &classname, bool (*cc)(core_device_t *)) const
|
||||
{
|
||||
core_device_t *ret = nullptr;
|
||||
@ -630,76 +563,49 @@ namespace netlist
|
||||
|
||||
device_t::device_t(netlist_state_t &owner, const pstring &name)
|
||||
: base_device_t(owner, name)
|
||||
, m_model(*this, "MODEL", pstring(NETLIST_DEFAULT_LOGIC_FAMILY))
|
||||
{
|
||||
// FIXME: this needs debugging!
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
//printf("Issue with 1 %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model()));
|
||||
}
|
||||
|
||||
device_t::device_t(netlist_state_t &owner, const pstring &name,
|
||||
const pstring &model)
|
||||
: base_device_t(owner, name)
|
||||
, m_model(*this, "MODEL", model)
|
||||
{
|
||||
//printf("In 1a %s: %s\n", this->name().c_str(), model.c_str());
|
||||
set_logic_family(state().setup().family_from_model(model)); //printf("%s %f %f\n", this->name().c_str(), logic_family()->R_low(), logic_family()->R_high());
|
||||
// FIXME: this needs debugging!
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
printf("Issue with 1a %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model()));
|
||||
}
|
||||
|
||||
device_t::device_t(netlist_state_t &owner, const pstring &name,
|
||||
const logic_family_desc_t *desc)
|
||||
: base_device_t(owner, name)
|
||||
, m_model(*this, "MODEL", pstring(""))
|
||||
{
|
||||
set_logic_family(desc);
|
||||
// FIXME: this needs debugging!
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
printf("Issue with 1b %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
throw nl_exception(MF_NULLPTR_FAMILY(this->name(), "<pointer provided by constructor>"));
|
||||
}
|
||||
|
||||
device_t::device_t(device_t &owner, const pstring &name)
|
||||
: base_device_t(owner, name)
|
||||
, m_model(*this, "MODEL", pstring(""))
|
||||
{
|
||||
set_logic_family(owner.logic_family());
|
||||
//printf("%s %f %f\n", this->name().c_str(), logic_family()->R_low(), logic_family()->R_high());
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
printf("Issue with 2 %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
throw nl_exception(MF_NULLPTR_FAMILY(this->name(), "<owner logic family>"));
|
||||
}
|
||||
|
||||
device_t::device_t(device_t &owner, const pstring &name, const pstring &model)
|
||||
: base_device_t(owner, name)
|
||||
, m_model(*this, "MODEL", model)
|
||||
{
|
||||
set_logic_family(state().setup().family_from_model(model));
|
||||
//printf("%s %f %f\n", this->name().c_str(), logic_family()->R_low(), logic_family()->R_high());
|
||||
set_logic_family(state().setup().family_from_model(m_model()));
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
printf("Issue with 3 %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
}
|
||||
|
||||
device_t::device_t(device_t &owner, const pstring &name, const logic_family_desc_t *desc)
|
||||
: base_device_t(owner, name)
|
||||
{
|
||||
set_logic_family(desc);
|
||||
//printf("%s %f %f\n", this->name().c_str(), logic_family()->R_low(), logic_family()->R_high());
|
||||
if (logic_family() == nullptr)
|
||||
{
|
||||
printf("Issue with 3 %s\n", this->name().c_str());
|
||||
set_logic_family(family_TTL());
|
||||
}
|
||||
throw nl_exception(MF_NULLPTR_FAMILY(this->name(), m_model()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -742,7 +648,7 @@ namespace netlist
|
||||
auto *p = dynamic_cast<analog_net_t *>(this);
|
||||
|
||||
if (p != nullptr)
|
||||
p->m_cur_Analog = nlconst::zero();
|
||||
p->set_Q_Analog(nlconst::zero());
|
||||
|
||||
// rebuild m_list and reset terminals to active or analog out state
|
||||
|
||||
@ -833,12 +739,6 @@ namespace netlist
|
||||
{
|
||||
}
|
||||
|
||||
logic_t::logic_t(device_t &dev, const pstring &aname, const state_e state,
|
||||
nldelegate delegate)
|
||||
: core_terminal_t(dev, aname, state, delegate)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// terminal_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -868,6 +768,29 @@ namespace netlist
|
||||
// net_output_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// logic_t
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
logic_t::logic_t(device_t &dev, const pstring &aname, const state_e terminal_state,
|
||||
nldelegate delegate)
|
||||
: core_terminal_t(dev, aname, terminal_state, delegate)
|
||||
, logic_family_t(dev.logic_family())
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// logic_input_t
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
logic_input_t::logic_input_t(device_t &dev, const pstring &aname,
|
||||
nldelegate delegate)
|
||||
: logic_t(dev, aname, STATE_INP_ACTIVE, delegate)
|
||||
{
|
||||
state().setup().register_term(*this);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// logic_output_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -878,7 +801,6 @@ namespace netlist
|
||||
{
|
||||
this->set_net(&m_my_net);
|
||||
state().register_net(owned_pool_ptr<logic_net_t>(&m_my_net, false));
|
||||
set_logic_family(dev.logic_family());
|
||||
state().setup().register_term(*this);
|
||||
}
|
||||
|
||||
@ -919,18 +841,6 @@ namespace netlist
|
||||
net().set_Q_Analog(val);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// logic_input_t
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
logic_input_t::logic_input_t(device_t &dev, const pstring &aname,
|
||||
nldelegate delegate)
|
||||
: logic_t(dev, aname, STATE_INP_ACTIVE, delegate)
|
||||
{
|
||||
set_logic_family(dev.logic_family());
|
||||
state().setup().register_term(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Parameters ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -279,7 +279,11 @@ namespace netlist
|
||||
class logic_family_desc_t
|
||||
{
|
||||
public:
|
||||
logic_family_desc_t();
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init, modernize-use-equals-default)
|
||||
logic_family_desc_t()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PCOPYASSIGNMOVE(logic_family_desc_t, delete)
|
||||
|
||||
@ -326,6 +330,7 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
logic_family_t() : m_logic_family(nullptr) {}
|
||||
logic_family_t(const logic_family_desc_t *d) : m_logic_family(d) {}
|
||||
PCOPYASSIGNMOVE(logic_family_t, delete)
|
||||
|
||||
const logic_family_desc_t *logic_family() const noexcept { return m_logic_family; }
|
||||
@ -337,9 +342,6 @@ namespace netlist
|
||||
const logic_family_desc_t *m_logic_family;
|
||||
};
|
||||
|
||||
const logic_family_desc_t *family_TTL(); ///< logic family for TTL devices.
|
||||
const logic_family_desc_t *family_CD4XXX(); ///< logic family for CD4XXX CMOS devices.
|
||||
|
||||
/// \brief A persistent variable template.
|
||||
/// Use the state_var template to define a variable whose value is saved.
|
||||
/// Within a device definition use
|
||||
@ -891,14 +893,10 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
logic_t(device_t &dev, const pstring &aname,
|
||||
state_e state, nldelegate delegate = nldelegate());
|
||||
state_e terminal_state, nldelegate delegate = nldelegate());
|
||||
|
||||
logic_net_t & net() noexcept;
|
||||
const logic_net_t & net() const noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -970,8 +968,6 @@ namespace netlist
|
||||
|
||||
using list_t = std::vector<analog_net_t *>;
|
||||
|
||||
friend class detail::net_t;
|
||||
|
||||
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr);
|
||||
|
||||
nl_fptype Q_Analog() const noexcept { return m_cur_Analog; }
|
||||
@ -1348,14 +1344,14 @@ namespace netlist
|
||||
device_t(netlist_state_t &owner, const pstring &name);
|
||||
device_t(netlist_state_t &owner, const pstring &name,
|
||||
const pstring &model);
|
||||
// only needed by proxies
|
||||
device_t(netlist_state_t &owner, const pstring &name,
|
||||
const logic_family_desc_t *desc);
|
||||
|
||||
device_t(device_t &owner, const pstring &name);
|
||||
// pass in a default model - this may be overwritten by PARAM(DEVICE.MODEL, "XYZ(...)")
|
||||
device_t(device_t &owner, const pstring &name,
|
||||
const pstring &model);
|
||||
device_t(device_t &owner, const pstring &name,
|
||||
const logic_family_desc_t *desc);
|
||||
|
||||
PCOPYASSIGNMOVE(device_t, delete)
|
||||
|
||||
@ -1366,6 +1362,8 @@ namespace netlist
|
||||
NETLIB_UPDATEI() { }
|
||||
NETLIB_UPDATE_TERMINALSI() { }
|
||||
|
||||
private:
|
||||
param_model_t m_model;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -1440,8 +1438,6 @@ namespace netlist
|
||||
///
|
||||
virtual ~netlist_state_t() noexcept = default;
|
||||
|
||||
friend class netlist_t; // allow access to private members
|
||||
|
||||
template<class C>
|
||||
static bool check_class(core_device_t *p) noexcept
|
||||
{
|
||||
@ -1628,9 +1624,21 @@ namespace netlist
|
||||
/// turned on.
|
||||
bool is_extended_validation() const { return m_extended_validation; }
|
||||
|
||||
private:
|
||||
struct stats_info
|
||||
{
|
||||
const detail::queue_t &m_queue;// performance
|
||||
const plib::pperftime_t<true> &m_stat_mainloop;
|
||||
const plib::pperfcount_t<true> &m_perf_out_processed;
|
||||
};
|
||||
|
||||
/// \brief print statistics gathered during run
|
||||
///
|
||||
void print_stats(stats_info &si) const;
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
detail::net_t *find_net(const pstring &name) const; // FIXME: stale
|
||||
|
||||
nlmempool m_pool; // must be deleted last!
|
||||
@ -2045,9 +2053,7 @@ namespace netlist
|
||||
|
||||
inline solver::matrix_solver_t *analog_t::solver() const noexcept
|
||||
{
|
||||
if (this->has_net())
|
||||
return net().solver();
|
||||
return nullptr;
|
||||
return (this->has_net() ? net().solver() : nullptr);
|
||||
}
|
||||
|
||||
inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); }
|
||||
@ -2056,7 +2062,6 @@ namespace netlist
|
||||
{
|
||||
if (!(gt && go && Idr) && (gt || go || Idr))
|
||||
{
|
||||
state().log().fatal("Inconsistent nullptrs for terminal {}", name());
|
||||
throw nl_exception("Inconsistent nullptrs for terminal {}", name());
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ static constexpr const int NETLIST_CLOCK = 1'000'000'000;
|
||||
|
||||
// FIXME: need a better solution for global constants.
|
||||
|
||||
static constexpr const char *NETLIST_DEFAULT_TRUTHTABLE_FAMILY = "74XX";
|
||||
static constexpr const char *NETLIST_DEFAULT_LOGIC_FAMILY = "74XX";
|
||||
|
||||
/// \brief Floating point types used
|
||||
///
|
||||
|
@ -22,6 +22,7 @@ namespace netlist
|
||||
PERRMSGV(MF_DUPLICATE_NAME_DEVICE_LIST, 1, "Error adding {1} to device list. Duplicate name.")
|
||||
PERRMSGV(MF_UNKNOWN_TYPE_FOR_OBJECT, 1, "Unknown type for object {1},")
|
||||
PERRMSGV(MF_NET_1_DUPLICATE_TERMINAL_2, 2, "net {1}: duplicate terminal {2}")
|
||||
PERRMSGV(MF_NULLPTR_FAMILY, 2, "Unable to determine family for device {1} from model {2}")
|
||||
PERRMSGV(MF_REMOVE_TERMINAL_1_FROM_NET_2, 2, "Can not remove terminal {1} from net {2}.")
|
||||
PERRMSGV(MF_UNKNOWN_PARAM_TYPE, 1, "Can not determine param_type for {1}")
|
||||
PERRMSGV(MF_ERROR_CONNECTING_1_TO_2, 2, "Error connecting {1} to {2}")
|
||||
@ -60,6 +61,7 @@ namespace netlist
|
||||
PERRMSGV(MF_PARAM_COUNT_MISMATCH_2, 2, "Parameter count mismatch for {1} - only found {2}")
|
||||
PERRMSGV(MF_PARAM_COUNT_EXCEEDED_2, 2, "Parameter count exceed for {1} - found {2}")
|
||||
PERRMSGV(MF_UNKNOWN_OBJECT_TYPE_1, 1, "Unknown object type {1}")
|
||||
PERRMSGV(MF_UNKNOWN_FAMILY_TYPE_1, 2, "Unknown family type {1} in model {2}")
|
||||
PERRMSGV(MF_INVALID_NUMBER_CONVERSION_1_2, 2, "Invalid number conversion {1} : {2}")
|
||||
PERRMSGV(MF_INVALID_ENUM_CONVERSION_1_2, 2, "Invalid element found {1} : {2}")
|
||||
PERRMSGV(MF_ADDING_PARAMETER_1_TO_PARAMETER_LIST,1, "Error adding parameter {1} to parameter list")
|
||||
|
@ -1177,24 +1177,38 @@ nl_fptype models_t::value(const pstring &model, const pstring &entity)
|
||||
return val * factor;
|
||||
}
|
||||
|
||||
// FIXME: all this belongs elsewhere
|
||||
|
||||
P_ENUM(family_type,
|
||||
CUSTOM,
|
||||
TTL,
|
||||
MOS,
|
||||
CMOS,
|
||||
NMOS,
|
||||
PMOS);
|
||||
|
||||
class logic_family_std_proxy_t : public logic_family_desc_t
|
||||
{
|
||||
public:
|
||||
logic_family_std_proxy_t() = default;
|
||||
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist,
|
||||
const pstring &name, const logic_output_t *proxied) const override;
|
||||
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const override;
|
||||
};
|
||||
logic_family_std_proxy_t(family_type ft)
|
||||
: m_family_type(ft)
|
||||
{
|
||||
}
|
||||
|
||||
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, const logic_output_t *proxied) const
|
||||
{
|
||||
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, const logic_input_t *proxied) const
|
||||
{
|
||||
return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
|
||||
}
|
||||
// FIXME: create proxies based on family type (far future)
|
||||
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist,
|
||||
const pstring &name, const logic_output_t *proxied) const override
|
||||
{
|
||||
return anetlist.make_object<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
|
||||
}
|
||||
|
||||
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const override
|
||||
{
|
||||
return anetlist.make_object<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
|
||||
}
|
||||
private:
|
||||
family_type m_family_type;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Class representing the logic families.
|
||||
@ -1232,19 +1246,19 @@ public:
|
||||
param_model_t::value_t m_ORH; //!< Output output resistance for logic 1
|
||||
};
|
||||
|
||||
|
||||
const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
|
||||
{
|
||||
family_type ft(family_type::CUSTOM);
|
||||
|
||||
if (models().value_str(model, "TYPE") == "TTL")
|
||||
return family_TTL();
|
||||
if (models().value_str(model, "TYPE") == "CD4XXX")
|
||||
return family_CD4XXX();
|
||||
if (!ft.set_from_string(models().value_str(model, "TYPE")) || ft == family_type::CUSTOM)
|
||||
throw nl_exception(MF_UNKNOWN_FAMILY_TYPE_1(models().value_str(model, "TYPE"), model));
|
||||
|
||||
auto it = m_nlstate.family_cache().find(model);
|
||||
if (it != m_nlstate.family_cache().end())
|
||||
return it->second.get();
|
||||
|
||||
auto ret = plib::make_unique<logic_family_std_proxy_t>();
|
||||
auto ret = plib::make_unique<logic_family_std_proxy_t>(ft);
|
||||
|
||||
ret->m_low_thresh_PCNT = models().value(model, "IVL");
|
||||
ret->m_high_thresh_PCNT = models().value(model, "IVH");
|
||||
|
@ -27,9 +27,9 @@ NETLIST_START(gamemachine)
|
||||
*
|
||||
*/
|
||||
|
||||
NET_MODEL("OPENDRAIN FAMILY(OVL=0.0 OVH=0.0 ORL=1.0 ORH=1e12)")
|
||||
NET_MODEL("TYPE6K FAMILY(OVL=0.05 OVH=0.05 ORL=1.0 ORH=6000)")
|
||||
NET_MODEL("DIRECTDRIVE FAMILY(OVL=0.05 OVH=0.05 ORL=1.0 ORH=1000)")
|
||||
NET_MODEL("OPENDRAIN FAMILY(TYPE=MOS OVL=0.0 OVH=0.0 ORL=1.0 ORH=1e12)")
|
||||
NET_MODEL("TYPE6K FAMILY(TYPE=MOS OVL=0.05 OVH=0.05 ORL=1.0 ORH=6000)")
|
||||
NET_MODEL("DIRECTDRIVE FAMILY(TYPE=MOS OVL=0.05 OVH=0.05 ORL=1.0 ORH=1000)")
|
||||
|
||||
LOGIC_INPUT(P08, 1, "OPENDRAIN")
|
||||
LOGIC_INPUT(P09, 1, "OPENDRAIN")
|
||||
|
@ -430,7 +430,7 @@ NETLIST_START(kidniki)
|
||||
ALIAS(I_SINH0, SINH_DUMMY.2)
|
||||
#endif
|
||||
|
||||
NET_MODEL("AY8910PORT FAMILY(OVL=0.05 OVH=0.05 ORL=100.0 ORH=0.5k)")
|
||||
NET_MODEL("AY8910PORT FAMILY(TYPE=NMOS OVL=0.05 OVH=0.05 ORL=100.0 ORH=0.5k)")
|
||||
|
||||
LOGIC_INPUT(I_SD0, 1, "AY8910PORT")
|
||||
LOGIC_INPUT(I_BD0, 1, "AY8910PORT")
|
||||
|
@ -357,7 +357,7 @@ NETLIST_START(zac1b11142)
|
||||
ALIAS(VCC, I_P5.Q)
|
||||
ALIAS(I_V0.Q, GND)
|
||||
|
||||
NET_MODEL("AY8910PORT FAMILY(OVL=0.05 OVH=0.05 ORL=100.0 ORH=0.5k)")
|
||||
NET_MODEL("AY8910PORT FAMILY(TYPE=NMOS OVL=0.05 OVH=0.05 ORL=100.0 ORH=0.5k)")
|
||||
|
||||
// AY-3-8910 4G/4H digital outputs
|
||||
LOGIC_INPUT(I_IOA0, 1, "AY8910PORT")
|
||||
|
Loading…
Reference in New Issue
Block a user