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:
couriersud 2020-05-10 16:10:42 +02:00
parent cd4dc51ea9
commit 227ab3025e
14 changed files with 204 additions and 295 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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()
/* ----------------------------------------------------------------------------

View File

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

View File

@ -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,24 +373,32 @@ namespace netlist
#endif
}
void netlist_t::print_stats() const
{
if (m_use_stats)
{
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 < m_state.m_devices.size(); i++)
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 m_state.m_devices[i1].second->stats()->m_stat_total_time.total() < m_state.m_devices[i2].second->stats()->m_stat_total_time.total(); });
[&](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 = m_state.m_devices[j].second.get();
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(),
@ -474,7 +410,7 @@ namespace netlist
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 loop {1:15}", si.m_stat_mainloop());
log().verbose("Total time {1:15}", total_time);
// FIXME: clang complains about unreachable code without
@ -497,22 +433,22 @@ namespace netlist
* 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("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 = (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
/ static_cast<plib::pperftime_t<true>::type>(m_queue.m_prof_call());
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 : m_state.m_devices)
for (auto &entry : this->m_devices)
{
auto *ep = entry.second.get();
auto *stats = ep->stats();
@ -525,9 +461,6 @@ namespace netlist
}
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
{
@ -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 ...
// ----------------------------------------------------------------------------------------

View File

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

View File

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

View File

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

View File

@ -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
{
// 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> logic_family_std_proxy_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, const logic_input_t *proxied) const
{
}
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");

View File

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

View File

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

View File

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