Separate include file usage for netlist.

Device implementations (all cpp files in netlist/devices) now should
only include nl_base.h. 
Netlist implementation sources should only include "net_lib.h". 
Refactored netlist.h and netlist.cpp to avoid namespace congestion in
netlist.h.
Fixed VC2015 build. (nw)
This commit is contained in:
couriersud 2017-01-29 13:05:33 +01:00
parent 2720512e31
commit c713f9ed1d
95 changed files with 1669 additions and 1553 deletions

View File

@ -75,11 +75,13 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/tools/nl_convert.h",
MAME_DIR .. "src/lib/netlist/analog/nld_bjt.cpp",
MAME_DIR .. "src/lib/netlist/analog/nld_bjt.h",
MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.cpp",
MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.h",
MAME_DIR .. "src/lib/netlist/analog/nlid_fourterm.cpp",
MAME_DIR .. "src/lib/netlist/analog/nlid_fourterm.h",
MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.h",
MAME_DIR .. "src/lib/netlist/analog/nld_switches.cpp",
MAME_DIR .. "src/lib/netlist/analog/nld_switches.h",
MAME_DIR .. "src/lib/netlist/analog/nld_twoterm.cpp",
MAME_DIR .. "src/lib/netlist/analog/nlid_twoterm.cpp",
MAME_DIR .. "src/lib/netlist/analog/nlid_twoterm.h",
MAME_DIR .. "src/lib/netlist/analog/nld_twoterm.h",
MAME_DIR .. "src/lib/netlist/analog/nld_opamps.cpp",
MAME_DIR .. "src/lib/netlist/analog/nld_opamps.h",
@ -190,8 +192,8 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/devices/nld_log.h",
MAME_DIR .. "src/lib/netlist/devices/nld_system.cpp",
MAME_DIR .. "src/lib/netlist/devices/nld_system.h",
MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.cpp",
MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_truthtable.cpp",
MAME_DIR .. "src/lib/netlist/devices/nlid_truthtable.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_cmos.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_system.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_proxy.cpp",

View File

@ -37,6 +37,391 @@ const device_type NETLIST_LOGIC_OUTPUT = &device_creator<netlist_mame_logic_outp
const device_type NETLIST_ANALOG_OUTPUT = &device_creator<netlist_mame_analog_output_t>;
const device_type NETLIST_STREAM_OUTPUT = &device_creator<netlist_mame_stream_output_t>;
// ----------------------------------------------------------------------------------------
// Special netlist extension devices ....
// ----------------------------------------------------------------------------------------
class netlist_mame_device_t;
class netlist_mame_t : public netlist::netlist_t
{
public:
netlist_mame_t(netlist_mame_device_t &parent, const pstring &aname)
: netlist::netlist_t(aname),
m_parent(parent)
{}
virtual ~netlist_mame_t() { };
inline running_machine &machine();
netlist_mame_device_t &parent() { return m_parent; }
protected:
void vlog(const plib::plog_level &l, const pstring &ls) const override;
private:
netlist_mame_device_t &m_parent;
};
// ----------------------------------------------------------------------------------------
// analog_callback
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(analog_callback) : public netlist::device_t
{
public:
NETLIB_NAME(analog_callback)(netlist::netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
, m_in(*this, "IN")
, m_cpu_device(nullptr)
, m_last(*this, "m_last", 0)
{
m_cpu_device = downcast<netlist_mame_cpu_device_t *>(&downcast<netlist_mame_t &>(netlist()).parent());
}
ATTR_COLD void reset() override
{
m_last = 0.0;
}
ATTR_COLD void register_callback(netlist_analog_output_delegate callback)
{
m_callback = callback;
}
NETLIB_UPDATEI()
{
nl_double cur = m_in();
// FIXME: make this a parameter
// avoid calls due to noise
if (std::fabs(cur - m_last) > 1e-6)
{
m_cpu_device->update_time_x();
m_callback(cur, m_cpu_device->local_time());
m_cpu_device->check_mame_abort_slice();
m_last = cur;
}
}
private:
netlist::analog_input_t m_in;
netlist_analog_output_delegate m_callback;
netlist_mame_cpu_device_t *m_cpu_device;
netlist::state_var<nl_double> m_last;
};
// ----------------------------------------------------------------------------------------
// logic_callback
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(logic_callback) : public netlist::device_t
{
public:
NETLIB_NAME(logic_callback)(netlist::netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
, m_in(*this, "IN")
, m_cpu_device(nullptr)
, m_last(*this, "m_last", 0)
{
m_cpu_device = downcast<netlist_mame_cpu_device_t *>(&downcast<netlist_mame_t &>(netlist()).parent());
}
ATTR_COLD void reset() override
{
m_last = 0;
}
ATTR_COLD void register_callback(netlist_logic_output_delegate callback)
{
m_callback = callback;
}
NETLIB_UPDATEI()
{
netlist_sig_t cur = m_in();
// FIXME: make this a parameter
// avoid calls due to noise
if (cur != m_last)
{
m_cpu_device->update_time_x();
m_callback(cur, m_cpu_device->local_time());
m_cpu_device->check_mame_abort_slice();
m_last = cur;
}
}
private:
netlist::logic_input_t m_in;
netlist_logic_output_delegate m_callback;
netlist_mame_cpu_device_t *m_cpu_device;
netlist::state_var<netlist_sig_t> m_last;
};
// ----------------------------------------------------------------------------------------
// sound_out
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(sound_out) : public netlist::device_t
{
public:
NETLIB_NAME(sound_out)(netlist::netlist_t &anetlist, const pstring &name)
: netlist::device_t(anetlist, name)
, m_channel(*this, "CHAN", 0)
, m_mult(*this, "MULT", 1000.0)
, m_offset(*this, "OFFSET", 0.0)
, m_sample(netlist::netlist_time::from_hz(1)) //sufficiently big enough
, m_in(*this, "IN")
, m_last_buffer(*this, "m_last_buffer", netlist::netlist_time::zero())
{
}
static const int BUFSIZE = 2048;
ATTR_COLD void reset() override
{
m_cur = 0.0;
m_last_pos = 0;
m_last_buffer = netlist::netlist_time::zero();
}
ATTR_HOT void sound_update(const netlist::netlist_time &upto)
{
int pos = (upto - m_last_buffer) / m_sample;
if (pos >= BUFSIZE)
netlist().log().fatal("sound {1}: exceeded BUFSIZE\n", name().c_str());
while (m_last_pos < pos )
{
m_buffer[m_last_pos++] = (stream_sample_t) m_cur;
}
}
NETLIB_UPDATEI()
{
nl_double val = m_in() * m_mult() + m_offset();
sound_update(netlist().time());
/* ignore spikes */
if (std::abs(val) < 32767.0)
m_cur = val;
else if (val > 0.0)
m_cur = 32767.0;
else
m_cur = -32767.0;
}
public:
ATTR_HOT void buffer_reset(const netlist::netlist_time &upto)
{
m_last_pos = 0;
m_last_buffer = upto;
m_cur = 0.0;
}
netlist::param_int_t m_channel;
netlist::param_double_t m_mult;
netlist::param_double_t m_offset;
stream_sample_t *m_buffer;
netlist::netlist_time m_sample;
private:
netlist::analog_input_t m_in;
double m_cur;
int m_last_pos;
netlist::state_var<netlist::netlist_time> m_last_buffer;
};
// ----------------------------------------------------------------------------------------
// sound_in
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(sound_in) : public netlist::device_t
{
public:
NETLIB_NAME(sound_in)(netlist::netlist_t &anetlist, const pstring &name)
: netlist::device_t(anetlist, name)
, m_feedback(*this, "FB") // clock part
, m_Q(*this, "Q")
{
connect(m_feedback, m_Q);
m_inc = netlist::netlist_time::from_nsec(1);
for (int i = 0; i < MAX_INPUT_CHANNELS; i++)
{
m_param_name[i] = std::make_unique<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), "");
m_param_mult[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("MULT{1}")(i), 1.0);
m_param_offset[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0);
}
m_num_channel = 0;
}
static const int MAX_INPUT_CHANNELS = 10;
ATTR_COLD void reset() override
{
m_pos = 0;
for (auto & elem : m_buffer)
elem = nullptr;
}
ATTR_COLD int resolve()
{
m_pos = 0;
for (int i = 0; i < MAX_INPUT_CHANNELS; i++)
{
if ((*m_param_name[i])() != pstring(""))
{
if (i != m_num_channel)
netlist().log().fatal("sound input numbering has to be sequential!");
m_num_channel++;
m_param[i] = dynamic_cast<netlist::param_double_t *>(setup().find_param((*m_param_name[i])(), true));
}
}
return m_num_channel;
}
NETLIB_UPDATEI()
{
for (int i=0; i<m_num_channel; i++)
{
if (m_buffer[i] == nullptr)
break; // stop, called outside of stream_update
const nl_double v = m_buffer[i][m_pos];
m_param[i]->setTo(v * (*m_param_mult[i])() + (*m_param_offset[i])());
}
m_pos++;
m_Q.push(!m_Q.net().new_Q(), m_inc );
}
public:
ATTR_HOT void buffer_reset()
{
m_pos = 0;
}
std::unique_ptr<netlist::param_str_t> m_param_name[MAX_INPUT_CHANNELS];
netlist::param_double_t *m_param[MAX_INPUT_CHANNELS];
stream_sample_t *m_buffer[MAX_INPUT_CHANNELS];
std::unique_ptr<netlist::param_double_t> m_param_mult[MAX_INPUT_CHANNELS];
std::unique_ptr<netlist::param_double_t> m_param_offset[MAX_INPUT_CHANNELS];
netlist::netlist_time m_inc;
private:
netlist::logic_input_t m_feedback;
netlist::logic_output_t m_Q;
int m_pos;
int m_num_channel;
};
// ----------------------------------------------------------------------------------------
// Extensions to interface netlist with MAME code ....
// ----------------------------------------------------------------------------------------
class netlist_source_memregion_t : public netlist::source_t
{
public:
netlist_source_memregion_t(netlist::setup_t &setup, pstring name)
: netlist::source_t(setup), m_name(name)
{
}
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_name;
};
class netlist_data_memregions_t : public netlist::source_t
{
public:
netlist_data_memregions_t(netlist::setup_t &setup);
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
};
netlist::setup_t &netlist_mame_device_t::setup()
{
return m_netlist->setup();
}
void netlist_mame_device_t::register_memregion_source(netlist::setup_t &setup, const char *name)
{
setup.register_source(plib::make_unique_base<netlist::source_t, netlist_source_memregion_t>(setup, pstring(name, pstring::UTF8)));
}
running_machine &netlist_mame_t::machine()
{
return m_parent.machine();
}
void netlist_mame_analog_input_t::write(const double val)
{
if (is_sound_device())
{
update_to_current_time();
m_param->setTo(val * m_mult + m_offset);
}
else
{
// FIXME: use device timer ....
m_param->setTo(val * m_mult + m_offset);
}
}
void netlist_mame_int_input_t::write(const uint32_t val)
{
const uint32_t v = (val >> m_shift) & m_mask;
if (v != (*m_param)())
synchronize(0, v);
}
void netlist_mame_logic_input_t::write(const uint32_t val)
{
const uint32_t v = (val >> m_shift) & 1;
if (v != (*m_param)())
synchronize(0, v);
}
void netlist_mame_int_input_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
if (is_sound_device())
update_to_current_time();
m_param->setTo(param);
}
void netlist_mame_logic_input_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
if (is_sound_device())
update_to_current_time();
m_param->setTo(param);
}
void netlist_ram_pointer_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_data = (*m_param)();
}
void netlist_mame_cpu_device_t::state_string_export(const device_state_entry &entry, std::string &str) const
{
if (entry.index() >= 0)
{
if (entry.index() & 1)
str = string_format("%10.6f", *((double *)entry.dataptr()));
else
str = string_format("%d", *((netlist_sig_t *)entry.dataptr()));
}
}
// ----------------------------------------------------------------------------------------
// netlist_mame_analog_input_t
// ----------------------------------------------------------------------------------------
@ -61,17 +446,17 @@ netlist_mame_analog_input_t::netlist_mame_analog_input_t(const machine_config &m
void netlist_mame_analog_input_t::static_set_name(device_t &device, const char *param_name)
{
netlist_mame_analog_input_t &netlist = downcast<netlist_mame_analog_input_t &>(device);
netlist.m_param_name = pstring(param_name, pstring::UTF8);
netlist.m_param_name = param_name;
}
void netlist_mame_analog_input_t::device_start()
{
LOG_DEV_CALLS(("start %s\n", tag()));
netlist::param_t *p = this->nl_owner().setup().find_param(m_param_name);
netlist::param_t *p = this->nl_owner().setup().find_param(pstring(m_param_name, pstring::UTF8));
m_param = dynamic_cast<netlist::param_double_t *>(p);
if (m_param == nullptr)
{
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.c_str());
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name);
}
if (m_mult != 1.0 || m_offset != 0.0)
{
@ -96,19 +481,20 @@ netlist_mame_analog_output_t::netlist_mame_analog_output_t(const machine_config
void netlist_mame_analog_output_t::static_set_params(device_t &device, const char *in_name, netlist_analog_output_delegate adelegate)
{
netlist_mame_analog_output_t &mame_output = downcast<netlist_mame_analog_output_t &>(device);
mame_output.m_in = pstring(in_name, pstring::UTF8);
mame_output.m_in = in_name;
mame_output.m_delegate = adelegate;
}
void netlist_mame_analog_output_t::custom_netlist_additions(netlist::setup_t &setup)
{
pstring dname = "OUT_" + m_in;
const pstring pin(m_in, pstring::UTF8);
pstring dname = "OUT_" + pin;
m_delegate.bind_relative_to(owner()->machine().root_device());
plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(analog_callback)>(setup.netlist(), setup.build_fqn(dname));
static_cast<NETLIB_NAME(analog_callback) *>(dev.get())->register_callback(m_delegate);
setup.netlist().register_dev(std::move(dev));
setup.register_link(dname + ".IN", m_in);
setup.register_link(dname + ".IN", pin);
}
void netlist_mame_analog_output_t::device_start()
@ -131,19 +517,20 @@ netlist_mame_logic_output_t::netlist_mame_logic_output_t(const machine_config &m
void netlist_mame_logic_output_t::static_set_params(device_t &device, const char *in_name, netlist_logic_output_delegate adelegate)
{
netlist_mame_logic_output_t &mame_output = downcast<netlist_mame_logic_output_t &>(device);
mame_output.m_in = pstring(in_name, pstring::UTF8);
mame_output.m_in = in_name;
mame_output.m_delegate = adelegate;
}
void netlist_mame_logic_output_t::custom_netlist_additions(netlist::setup_t &setup)
{
pstring dname = "OUT_" + m_in;
pstring pin(m_in, pstring::UTF8);
pstring dname = "OUT_" + pin;
m_delegate.bind_relative_to(owner()->machine().root_device());
plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(logic_callback)>(setup.netlist(), setup.build_fqn(dname));
static_cast<NETLIB_NAME(logic_callback) *>(dev.get())->register_callback(m_delegate);
setup.netlist().register_dev(std::move(dev));
setup.register_link(dname + ".IN", m_in);
setup.register_link(dname + ".IN", pin);
}
void netlist_mame_logic_output_t::device_start()
@ -170,7 +557,7 @@ void netlist_mame_int_input_t::static_set_params(device_t &device, const char *p
{
netlist_mame_int_input_t &netlist = downcast<netlist_mame_int_input_t &>(device);
LOG_DEV_CALLS(("static_set_params %s\n", device.tag()));
netlist.m_param_name = pstring(param_name, pstring::UTF8);
netlist.m_param_name = param_name;
netlist.m_shift = shift;
netlist.m_mask = mask;
}
@ -178,11 +565,11 @@ void netlist_mame_int_input_t::static_set_params(device_t &device, const char *p
void netlist_mame_int_input_t::device_start()
{
LOG_DEV_CALLS(("start %s\n", tag()));
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name);
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8));
m_param = dynamic_cast<netlist::param_int_t *>(p);
if (m_param == nullptr)
{
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.c_str());
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name);
}
}
@ -203,18 +590,18 @@ void netlist_mame_logic_input_t::static_set_params(device_t &device, const char
{
netlist_mame_logic_input_t &netlist = downcast<netlist_mame_logic_input_t &>(device);
LOG_DEV_CALLS(("static_set_params %s\n", device.tag()));
netlist.m_param_name = pstring(param_name, pstring::UTF8);
netlist.m_param_name = param_name;
netlist.m_shift = shift;
}
void netlist_mame_logic_input_t::device_start()
{
LOG_DEV_CALLS(("start %s\n", tag()));
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name);
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8));
m_param = dynamic_cast<netlist::param_logic_t *>(p);
if (m_param == nullptr)
{
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.c_str());
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name);
}
}
@ -236,17 +623,17 @@ void netlist_ram_pointer_t::static_set_params(device_t &device, const char *para
{
netlist_ram_pointer_t &netlist = downcast<netlist_ram_pointer_t&>(device);
LOG_DEV_CALLS(("static_set_params %s\n", device.tag()));
netlist.m_param_name = pstring(param_name, pstring::UTF8);
netlist.m_param_name = param_name;
}
void netlist_ram_pointer_t::device_start()
{
LOG_DEV_CALLS(("start %s\n", tag()));
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name);
netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8));
m_param = dynamic_cast<netlist::param_ptr_t *>(p);
if (m_param == nullptr)
{
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.c_str());
fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name);
}
m_data = (*m_param)();
@ -267,7 +654,7 @@ netlist_mame_stream_input_t::netlist_mame_stream_input_t(const machine_config &m
void netlist_mame_stream_input_t::static_set_params(device_t &device, int channel, const char *param_name)
{
netlist_mame_stream_input_t &netlist = downcast<netlist_mame_stream_input_t &>(device);
netlist.m_param_name = pstring(param_name, pstring::UTF8);
netlist.m_param_name = param_name;
netlist.m_channel = channel;
}
@ -282,7 +669,7 @@ void netlist_mame_stream_input_t::custom_netlist_additions(netlist::setup_t &set
setup.register_dev("NETDEV_SOUND_IN", "STREAM_INPUT");
pstring sparam = plib::pfmt("STREAM_INPUT.CHAN{1}")(m_channel);
setup.register_param(sparam, m_param_name);
setup.register_param(sparam, pstring(m_param_name, pstring::UTF8));
sparam = plib::pfmt("STREAM_INPUT.MULT{1}")(m_channel);
setup.register_param(sparam, m_mult);
sparam = plib::pfmt("STREAM_INPUT.OFFSET{1}")(m_channel);
@ -304,7 +691,7 @@ netlist_mame_stream_output_t::netlist_mame_stream_output_t(const machine_config
void netlist_mame_stream_output_t::static_set_params(device_t &device, int channel, const char *out_name)
{
netlist_mame_stream_output_t &netlist = downcast<netlist_mame_stream_output_t &>(device);
netlist.m_out_name = pstring(out_name, pstring::UTF8);
netlist.m_out_name = out_name;
netlist.m_channel = channel;
}
@ -324,7 +711,7 @@ void netlist_mame_stream_output_t::custom_netlist_additions(netlist::setup_t &se
setup.register_param(sname + ".CHAN" , m_channel);
setup.register_param(sname + ".MULT", m_mult);
setup.register_param(sname + ".OFFSET", m_offset);
setup.register_link(sname + ".IN", m_out_name);
setup.register_link(sname + ".IN", pstring(m_out_name, pstring::UTF8));
}
@ -381,6 +768,11 @@ netlist_mame_device_t::netlist_mame_device_t(const machine_config &mconfig, devi
{
}
netlist_mame_device_t::~netlist_mame_device_t()
{
pstring::resetmem();
}
void netlist_mame_device_t::static_set_constructor(device_t &device, void (*setup_func)(netlist::setup_t &))
{
LOG_DEV_CALLS(("static_set_constructor\n"));

View File

@ -13,8 +13,17 @@
#include "emu.h"
#include "netlist/nl_base.h"
#include "netlist/nl_setup.h"
#include "netlist/nl_time.h"
class netlist_mame_t;
namespace netlist {
class setup_t;
class param_double_t;
class param_int_t;
class param_logic_t;
class param_ptr_t;
}
// MAME specific configuration
@ -72,7 +81,7 @@
#define MEMREGION_SOURCE(_name) \
setup.register_source(plib::make_unique_base<netlist::source_t, netlist_source_memregion_t>(setup, _name));
netlist_mame_device_t::register_memregion_source(setup, _name);
#define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \
void _name(const double data, const attotime &time)
@ -81,54 +90,6 @@
void _name(const int data, const attotime &time)
// ----------------------------------------------------------------------------------------
// Extensions to interface netlist with MAME code ....
// ----------------------------------------------------------------------------------------
class netlist_source_memregion_t : public netlist::source_t
{
public:
netlist_source_memregion_t(netlist::setup_t &setup, pstring name)
: netlist::source_t(setup), m_name(name)
{
}
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
private:
pstring m_name;
};
class netlist_data_memregions_t : public netlist::source_t
{
public:
netlist_data_memregions_t(netlist::setup_t &setup);
virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override;
};
class netlist_mame_device_t;
class netlist_mame_t : public netlist::netlist_t
{
public:
netlist_mame_t(netlist_mame_device_t &parent, const pstring &aname)
: netlist::netlist_t(aname),
m_parent(parent)
{}
virtual ~netlist_mame_t() { };
inline running_machine &machine();
netlist_mame_device_t &parent() { return m_parent; }
protected:
void vlog(const plib::plog_level &l, const pstring &ls) const override;
private:
netlist_mame_device_t &m_parent;
};
// ----------------------------------------------------------------------------------------
// netlist_mame_device_t
@ -141,17 +102,19 @@ public:
// construction/destruction
netlist_mame_device_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
netlist_mame_device_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *file);
virtual ~netlist_mame_device_t() { pstring::resetmem(); }
virtual ~netlist_mame_device_t();
static void static_set_constructor(device_t &device, void (*setup_func)(netlist::setup_t &));
ATTR_HOT inline netlist::setup_t &setup() { return m_netlist->setup(); }
ATTR_HOT inline netlist::setup_t &setup();
ATTR_HOT inline netlist_mame_t &netlist() { return *m_netlist; }
ATTR_HOT inline const netlist::netlist_time last_time_update() { return m_old; }
ATTR_HOT void update_time_x();
ATTR_HOT void check_mame_abort_slice();
static void register_memregion_source(netlist::setup_t &setup, const char *name);
int m_icount;
protected:
@ -184,11 +147,6 @@ private:
void (*m_setup_func)(netlist::setup_t &);
};
inline running_machine &netlist_mame_t::machine()
{
return m_parent.machine();
}
// ----------------------------------------------------------------------------------------
// netlist_mame_cpu_device_t
// ----------------------------------------------------------------------------------------
@ -246,16 +204,7 @@ protected:
// device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override
{
if (entry.index() >= 0)
{
if (entry.index() & 1)
str = string_format("%10.6f", *((double *)entry.dataptr()));
else
str = string_format("%d", *((netlist_sig_t *)entry.dataptr()));
}
}
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
private:
@ -365,19 +314,7 @@ public:
static void static_set_name(device_t &device, const char *param_name);
inline void write(const double val)
{
if (is_sound_device())
{
update_to_current_time();
m_param->setTo(val * m_mult + m_offset);
}
else
{
// FIXME: use device timer ....
m_param->setTo(val * m_mult + m_offset);
}
}
void write(const double val);
inline DECLARE_INPUT_CHANGED_MEMBER(input_changed)
{
@ -399,7 +336,7 @@ protected:
private:
netlist::param_double_t *m_param;
bool m_auto_port;
pstring m_param_name;
const char *m_param_name;
};
// ----------------------------------------------------------------------------------------
@ -425,7 +362,7 @@ protected:
virtual void custom_netlist_additions(netlist::setup_t &setup) override;
private:
pstring m_in;
const char *m_in;
netlist_analog_output_delegate m_delegate;
};
@ -452,7 +389,7 @@ protected:
virtual void custom_netlist_additions(netlist::setup_t &setup) override;
private:
pstring m_in;
const char *m_in;
netlist_logic_output_delegate m_delegate;
};
@ -471,12 +408,7 @@ public:
static void static_set_params(device_t &device, const char *param_name, const uint32_t mask, const uint32_t shift);
inline void write(const uint32_t val)
{
const uint32_t v = (val >> m_shift) & m_mask;
if (v != (*m_param)())
synchronize(0, v);
}
void write(const uint32_t val);
inline DECLARE_INPUT_CHANGED_MEMBER(input_changed) { write(newval); }
DECLARE_WRITE_LINE_MEMBER(write_line) { write(state); }
@ -488,18 +420,13 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override
{
if (is_sound_device())
update_to_current_time();
m_param->setTo(param);
}
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
netlist::param_int_t *m_param;
uint32_t m_mask;
uint32_t m_shift;
pstring m_param_name;
const char *m_param_name;
};
@ -518,12 +445,7 @@ public:
static void static_set_params(device_t &device, const char *param_name, const uint32_t shift);
inline void write(const uint32_t val)
{
const uint32_t v = (val >> m_shift) & 1;
if (v != (*m_param)())
synchronize(0, v);
}
void write(const uint32_t val);
inline DECLARE_INPUT_CHANGED_MEMBER(input_changed) { write(newval); }
DECLARE_WRITE_LINE_MEMBER(write_line) { write(state); }
@ -535,17 +457,12 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override
{
if (is_sound_device())
update_to_current_time();
m_param->setTo(param);
}
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
netlist::param_logic_t *m_param;
uint32_t m_shift;
pstring m_param_name;
const char *m_param_name;
};
// ----------------------------------------------------------------------------------------
@ -568,14 +485,11 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override
{
m_data = (*m_param)();
}
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
netlist::param_ptr_t *m_param;
pstring m_param_name;
const char *m_param_name;
uint8_t* m_data;
};
@ -600,7 +514,7 @@ protected:
virtual void custom_netlist_additions(netlist::setup_t &setup) override;
private:
uint32_t m_channel;
pstring m_param_name;
const char *m_param_name;
};
// ----------------------------------------------------------------------------------------
@ -624,261 +538,9 @@ protected:
virtual void custom_netlist_additions(netlist::setup_t &setup) override;
private:
uint32_t m_channel;
pstring m_out_name;
const char *m_out_name;
};
// ----------------------------------------------------------------------------------------
// analog_callback
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(analog_callback) : public netlist::device_t
{
public:
NETLIB_NAME(analog_callback)(netlist::netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
, m_in(*this, "IN")
, m_cpu_device(nullptr)
, m_last(*this, "m_last", 0)
{
m_cpu_device = downcast<netlist_mame_cpu_device_t *>(&downcast<netlist_mame_t &>(netlist()).parent());
}
ATTR_COLD void reset() override
{
m_last = 0.0;
}
ATTR_COLD void register_callback(netlist_analog_output_delegate callback)
{
m_callback = callback;
}
NETLIB_UPDATEI()
{
nl_double cur = m_in();
// FIXME: make this a parameter
// avoid calls due to noise
if (std::fabs(cur - m_last) > 1e-6)
{
m_cpu_device->update_time_x();
m_callback(cur, m_cpu_device->local_time());
m_cpu_device->check_mame_abort_slice();
m_last = cur;
}
}
private:
netlist::analog_input_t m_in;
netlist_analog_output_delegate m_callback;
netlist_mame_cpu_device_t *m_cpu_device;
netlist::state_var<nl_double> m_last;
};
// ----------------------------------------------------------------------------------------
// logic_callback
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(logic_callback) : public netlist::device_t
{
public:
NETLIB_NAME(logic_callback)(netlist::netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
, m_in(*this, "IN")
, m_cpu_device(nullptr)
, m_last(*this, "m_last", 0)
{
m_cpu_device = downcast<netlist_mame_cpu_device_t *>(&downcast<netlist_mame_t &>(netlist()).parent());
}
ATTR_COLD void reset() override
{
m_last = 0;
}
ATTR_COLD void register_callback(netlist_logic_output_delegate callback)
{
m_callback = callback;
}
NETLIB_UPDATEI()
{
netlist_sig_t cur = m_in();
// FIXME: make this a parameter
// avoid calls due to noise
if (cur != m_last)
{
m_cpu_device->update_time_x();
m_callback(cur, m_cpu_device->local_time());
m_cpu_device->check_mame_abort_slice();
m_last = cur;
}
}
private:
netlist::logic_input_t m_in;
netlist_logic_output_delegate m_callback;
netlist_mame_cpu_device_t *m_cpu_device;
netlist::state_var<netlist_sig_t> m_last;
};
// ----------------------------------------------------------------------------------------
// sound_out
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(sound_out) : public netlist::device_t
{
public:
NETLIB_NAME(sound_out)(netlist::netlist_t &anetlist, const pstring &name)
: netlist::device_t(anetlist, name)
, m_channel(*this, "CHAN", 0)
, m_mult(*this, "MULT", 1000.0)
, m_offset(*this, "OFFSET", 0.0)
, m_sample(netlist::netlist_time::from_hz(1)) //sufficiently big enough
, m_in(*this, "IN")
, m_last_buffer(*this, "m_last_buffer", netlist::netlist_time::zero())
{
}
static const int BUFSIZE = 2048;
ATTR_COLD void reset() override
{
m_cur = 0.0;
m_last_pos = 0;
m_last_buffer = netlist::netlist_time::zero();
}
ATTR_HOT void sound_update(const netlist::netlist_time &upto)
{
int pos = (upto - m_last_buffer) / m_sample;
if (pos >= BUFSIZE)
netlist().log().fatal("sound {1}: exceeded BUFSIZE\n", name().c_str());
while (m_last_pos < pos )
{
m_buffer[m_last_pos++] = (stream_sample_t) m_cur;
}
}
NETLIB_UPDATEI()
{
nl_double val = m_in() * m_mult() + m_offset();
sound_update(netlist().time());
/* ignore spikes */
if (std::abs(val) < 32767.0)
m_cur = val;
else if (val > 0.0)
m_cur = 32767.0;
else
m_cur = -32767.0;
}
public:
ATTR_HOT void buffer_reset(const netlist::netlist_time &upto)
{
m_last_pos = 0;
m_last_buffer = upto;
m_cur = 0.0;
}
netlist::param_int_t m_channel;
netlist::param_double_t m_mult;
netlist::param_double_t m_offset;
stream_sample_t *m_buffer;
netlist::netlist_time m_sample;
private:
netlist::analog_input_t m_in;
double m_cur;
int m_last_pos;
netlist::state_var<netlist::netlist_time> m_last_buffer;
};
// ----------------------------------------------------------------------------------------
// sound_in
// ----------------------------------------------------------------------------------------
class NETLIB_NAME(sound_in) : public netlist::device_t
{
public:
NETLIB_NAME(sound_in)(netlist::netlist_t &anetlist, const pstring &name)
: netlist::device_t(anetlist, name)
, m_feedback(*this, "FB") // clock part
, m_Q(*this, "Q")
{
connect(m_feedback, m_Q);
m_inc = netlist::netlist_time::from_nsec(1);
for (int i = 0; i < MAX_INPUT_CHANNELS; i++)
{
m_param_name[i] = std::make_unique<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), "");
m_param_mult[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("MULT{1}")(i), 1.0);
m_param_offset[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0);
}
m_num_channel = 0;
}
static const int MAX_INPUT_CHANNELS = 10;
ATTR_COLD void reset() override
{
m_pos = 0;
for (auto & elem : m_buffer)
elem = nullptr;
}
ATTR_COLD int resolve()
{
m_pos = 0;
for (int i = 0; i < MAX_INPUT_CHANNELS; i++)
{
if ((*m_param_name[i])() != pstring(""))
{
if (i != m_num_channel)
netlist().log().fatal("sound input numbering has to be sequential!");
m_num_channel++;
m_param[i] = dynamic_cast<netlist::param_double_t *>(setup().find_param((*m_param_name[i])(), true));
}
}
return m_num_channel;
}
NETLIB_UPDATEI()
{
for (int i=0; i<m_num_channel; i++)
{
if (m_buffer[i] == nullptr)
break; // stop, called outside of stream_update
const nl_double v = m_buffer[i][m_pos];
m_param[i]->setTo(v * (*m_param_mult[i])() + (*m_param_offset[i])());
}
m_pos++;
m_Q.push(!m_Q.net().new_Q(), m_inc );
}
public:
ATTR_HOT void buffer_reset()
{
m_pos = 0;
}
std::unique_ptr<netlist::param_str_t> m_param_name[MAX_INPUT_CHANNELS];
netlist::param_double_t *m_param[MAX_INPUT_CHANNELS];
stream_sample_t *m_buffer[MAX_INPUT_CHANNELS];
std::unique_ptr<netlist::param_double_t> m_param_mult[MAX_INPUT_CHANNELS];
std::unique_ptr<netlist::param_double_t> m_param_offset[MAX_INPUT_CHANNELS];
netlist::netlist_time m_inc;
private:
netlist::logic_input_t m_feedback;
netlist::logic_output_t m_Q;
int m_pos;
int m_num_channel;
};
// device type definition
extern const device_type NETLIST_CORE;

View File

@ -6,7 +6,7 @@
*/
#include "solver/nld_solver.h"
#include "analog/nld_bjt.h"
#include "analog/nlid_twoterm.h"
#include "nl_setup.h"
#include <cmath>
@ -15,6 +15,7 @@ namespace netlist
{
namespace analog
{
class diode
{
public:
@ -42,6 +43,242 @@ private:
nl_double m_VT_inv;
};
// -----------------------------------------------------------------------------
// nld_Q - Base classes
// -----------------------------------------------------------------------------
/* FIXME: Make table pretty */
/*! Class representing the bjt model paramers.
* This is the model representation of the bjt model. Typically, SPICE uses
* the following parameters. A "Y" in the first column indicates that the
* parameter is actually used in netlist.
*
* |NL? |name |parameter |units|default| example|area |
* |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
* | Y |IS |transport saturation current|A |1E-016|1E-015|* |
* | Y |BF |ideal maximum forward beta|- |100|100| |
* | Y |NF |forward current emission coefficient|- |1|1| |
* | |VAF |forward Early voltage|V |infinite |200| |
* | |IKF |corner for forward beta high current roll-off|A |infinite |0.01|* |
* | |ISE |B-E leakage saturation current|A |0|0.0000000000001|* |
* | |NE |B-E leakage emission coefficient|- |1.5|2| |
* | Y |BR |ideal maximum reverse beta |- |1|0.1| |
* | Y |NR |reverse current emission coefficient|- |1|1| |
* | |VAR |reverse Early voltage|V |infinite |200| |
* | |IKR |corner for reverse beta high current roll-off|A |infinite |0.01|* |
* | |ISC |leakage saturation current|A |0|8| |
* | |NC |leakage emission coefficient|- |2|1.5| |
* | |RB |zero bias base resistance| |0|100|* |
* | |IRB |current where base resistance falls halfway to its min value|A |infinte |0.1|* |
* | |RBM |minimum base resistance at high currents| |RB |10|* |
* | |RE |emitter resistance| |0|1|* |
* | |RC |collector resistance | |0|10|* |
* | |CJE |B-E zero-bias depletion capacitance|F |0|2pF |* |
* | |VJE |B-E built-in potential|V |0.75|0.6| |
* | |MJE |B-E junction exponential factor |- |0.33|0.33| |
* | |TF |ideal forward transit time |sec |0|0.1ns | |
* | |XTF|coefficient for bias dependence of TF |- |0| | |
* | |VTF |voltage describing VBC dependence of TF |V |infinite | | |
* | |ITF |high-current parameter for effect on TF |A |0| |* |
* | |PTF |excess phase at freq=1.0/(TF*2PI) Hz |deg |0| | |
* | |CJC |B-C zero-bias depletion capacitance |F |0|2pF |* |
* | |VJC |B-C built-in potential |V |0.75|0.5| |
* | |MJC |B-C junction exponential factor |- |0.33|0.5| |
* | |XCJC |fraction of B-C depletion capacitance connected to internal base node |- |1| | |
* | |TR |ideal reverse transit time |sec |0|10ns | |
* | |CJS |zero-bias collector-substrate capacitance |F |0|2pF |* |
* | |VJS |substrate junction built-in potential |V |0.75| | |
* | |MJS |substrate junction exponential factor |- |0|0.5| |
* | |XTB |forward and reverse beta temperature exponent |- |0| | |
* | |EG|energy gap for temperature effect on IS |eV |1.11| | |
* | |XTI|temperature exponent for effect on IS |- |3| | |
* | |KF |flicker-noise coefficient |- |0| | |
* | |AF |flicker-noise exponent |- |1| | |
* | |FC |coefficient for forward-bias depletion capacitance formula |- |0.5| | |
* | |TNOM |Parameter measurement temperature |C |27|50| |
*/
class bjt_model_t : public param_model_t
{
public:
bjt_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_IS(*this, "IS")
, m_BF(*this, "BF")
, m_NF(*this, "NF")
, m_BR(*this, "BR")
, m_NR(*this, "NR")
{}
value_t m_IS; //!< transport saturation current
value_t m_BF; //!< ideal maximum forward beta
value_t m_NF; //!< forward current emission coefficient
value_t m_BR; //!< ideal maximum reverse beta
value_t m_NR; //!< reverse current emission coefficient
};
// Have a common start for transistors
NETLIB_OBJECT(Q)
{
public:
enum q_type {
BJT_NPN,
BJT_PNP
};
NETLIB_CONSTRUCTOR(Q)
, m_model(*this, "MODEL", "")
, m_qtype(BJT_NPN)
{
}
NETLIB_IS_DYNAMIC(true)
//NETLIB_RESETI();
NETLIB_UPDATEI();
inline q_type qtype() const { return m_qtype; }
inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
inline void set_qtype(q_type atype) { m_qtype = atype; }
protected:
bjt_model_t m_model;
private:
q_type m_qtype;
};
NETLIB_OBJECT_DERIVED(QBJT, Q)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
{ }
protected:
private:
};
// -----------------------------------------------------------------------------
// nld_QBJT_switch
// -----------------------------------------------------------------------------
/*
* + - C
* B ----VVV----+ |
* | |
* Rb Rc
* Rb Rc
* Rb Rc
* | |
* +----+----+
* |
* E
*/
NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
{
NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
, m_RB(*this, "m_RB", true)
, m_RC(*this, "m_RC", true)
, m_BC_dummy(*this, "m_BC", true)
, m_gB(NETLIST_GMIN_DEFAULT)
, m_gC(NETLIST_GMIN_DEFAULT)
, m_V(0.0)
, m_state_on(*this, "m_state_on", 0)
{
register_subalias("B", m_RB.m_P);
register_subalias("E", m_RB.m_N);
register_subalias("C", m_RC.m_P);
//register_term("_E1", m_RC.m_N);
//register_term("_B1", m_BC_dummy.m_P);
//register_term("_C1", m_BC_dummy.m_N);
connect(m_RB.m_N, m_RC.m_N);
connect(m_RB.m_P, m_BC_dummy.m_P);
connect(m_RC.m_P, m_BC_dummy.m_N);
}
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
nld_twoterm m_RB;
nld_twoterm m_RC;
// FIXME: this is needed so we have all terminals belong to one net list
nld_twoterm m_BC_dummy;
protected:
nl_double m_gB; // base conductance / switch on
nl_double m_gC; // collector conductance / switch on
nl_double m_V; // internal voltage source
state_var<unsigned> m_state_on;
private:
};
// -----------------------------------------------------------------------------
// nld_QBJT_EB
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
, m_gD_BC(*this, "m_D_BC")
, m_gD_BE(*this, "m_D_BE")
, m_D_CB(*this, "m_D_CB", true)
, m_D_EB(*this, "m_D_EB", true)
, m_D_EC(*this, "m_D_EC", true)
, m_alpha_f(0)
, m_alpha_r(0)
{
register_subalias("E", m_D_EB.m_P); // Cathode
register_subalias("B", m_D_EB.m_N); // Anode
register_subalias("C", m_D_CB.m_P); // Cathode
//register_term("_B1", m_D_CB.m_N); // Anode
//register_term("_E1", m_D_EC.m_P);
//register_term("_C1", m_D_EC.m_N);
connect(m_D_EB.m_P, m_D_EC.m_P);
connect(m_D_EB.m_N, m_D_CB.m_N);
connect(m_D_CB.m_P, m_D_EC.m_N);
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
generic_diode m_gD_BC;
generic_diode m_gD_BE;
private:
nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
nl_double m_alpha_f;
nl_double m_alpha_r;
};
// ----------------------------------------------------------------------------------------

View File

@ -8,15 +8,12 @@
#ifndef NLD_BJT_H_
#define NLD_BJT_H_
#include "nl_base.h"
#include "nld_twoterm.h"
#include "nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
// -----------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define QBJT_SW(name, model) \
NET_REGISTER_DEV(QBJT_SW, name) \
NETDEV_PARAMI(name, MODEL, model)
@ -25,250 +22,4 @@
NET_REGISTER_DEV(QBJT_EB, name) \
NETDEV_PARAMI(name, MODEL, model)
#endif
namespace netlist
{
namespace analog
{
// -----------------------------------------------------------------------------
// nld_Q - Base classes
// -----------------------------------------------------------------------------
/* FIXME: Make table pretty */
/*! Class representing the bjt model paramers.
* This is the model representation of the bjt model. Typically, SPICE uses
* the following parameters. A "Y" in the first column indicates that the
* parameter is actually used in netlist.
*
* |NL? |name |parameter |units|default| example|area |
* |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
* | Y |IS |transport saturation current|A |1E-016|1E-015|* |
* | Y |BF |ideal maximum forward beta|- |100|100| |
* | Y |NF |forward current emission coefficient|- |1|1| |
* | |VAF |forward Early voltage|V |infinite |200| |
* | |IKF |corner for forward beta high current roll-off|A |infinite |0.01|* |
* | |ISE |B-E leakage saturation current|A |0|0.0000000000001|* |
* | |NE |B-E leakage emission coefficient|- |1.5|2| |
* | Y |BR |ideal maximum reverse beta |- |1|0.1| |
* | Y |NR |reverse current emission coefficient|- |1|1| |
* | |VAR |reverse Early voltage|V |infinite |200| |
* | |IKR |corner for reverse beta high current roll-off|A |infinite |0.01|* |
* | |ISC |leakage saturation current|A |0|8| |
* | |NC |leakage emission coefficient|- |2|1.5| |
* | |RB |zero bias base resistance| |0|100|* |
* | |IRB |current where base resistance falls halfway to its min value|A |infinte |0.1|* |
* | |RBM |minimum base resistance at high currents| |RB |10|* |
* | |RE |emitter resistance| |0|1|* |
* | |RC |collector resistance | |0|10|* |
* | |CJE |B-E zero-bias depletion capacitance|F |0|2pF |* |
* | |VJE |B-E built-in potential|V |0.75|0.6| |
* | |MJE |B-E junction exponential factor |- |0.33|0.33| |
* | |TF |ideal forward transit time |sec |0|0.1ns | |
* | |XTF|coefficient for bias dependence of TF |- |0| | |
* | |VTF |voltage describing VBC dependence of TF |V |infinite | | |
* | |ITF |high-current parameter for effect on TF |A |0| |* |
* | |PTF |excess phase at freq=1.0/(TF*2PI) Hz |deg |0| | |
* | |CJC |B-C zero-bias depletion capacitance |F |0|2pF |* |
* | |VJC |B-C built-in potential |V |0.75|0.5| |
* | |MJC |B-C junction exponential factor |- |0.33|0.5| |
* | |XCJC |fraction of B-C depletion capacitance connected to internal base node |- |1| | |
* | |TR |ideal reverse transit time |sec |0|10ns | |
* | |CJS |zero-bias collector-substrate capacitance |F |0|2pF |* |
* | |VJS |substrate junction built-in potential |V |0.75| | |
* | |MJS |substrate junction exponential factor |- |0|0.5| |
* | |XTB |forward and reverse beta temperature exponent |- |0| | |
* | |EG|energy gap for temperature effect on IS |eV |1.11| | |
* | |XTI|temperature exponent for effect on IS |- |3| | |
* | |KF |flicker-noise coefficient |- |0| | |
* | |AF |flicker-noise exponent |- |1| | |
* | |FC |coefficient for forward-bias depletion capacitance formula |- |0.5| | |
* | |TNOM |Parameter measurement temperature |C |27|50| |
*/
class bjt_model_t : public param_model_t
{
public:
bjt_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_IS(*this, "IS")
, m_BF(*this, "BF")
, m_NF(*this, "NF")
, m_BR(*this, "BR")
, m_NR(*this, "NR")
{}
value_t m_IS; //!< transport saturation current
value_t m_BF; //!< ideal maximum forward beta
value_t m_NF; //!< forward current emission coefficient
value_t m_BR; //!< ideal maximum reverse beta
value_t m_NR; //!< reverse current emission coefficient
};
// Have a common start for transistors
NETLIB_OBJECT(Q)
{
public:
enum q_type {
BJT_NPN,
BJT_PNP
};
NETLIB_CONSTRUCTOR(Q)
, m_model(*this, "MODEL", "")
, m_qtype(BJT_NPN)
{
}
NETLIB_IS_DYNAMIC(true)
//NETLIB_RESETI();
NETLIB_UPDATEI();
inline q_type qtype() const { return m_qtype; }
inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
inline void set_qtype(q_type atype) { m_qtype = atype; }
protected:
bjt_model_t m_model;
private:
q_type m_qtype;
};
NETLIB_OBJECT_DERIVED(QBJT, Q)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
{ }
protected:
private:
};
// -----------------------------------------------------------------------------
// nld_QBJT_switch
// -----------------------------------------------------------------------------
/*
* + - C
* B ----VVV----+ |
* | |
* Rb Rc
* Rb Rc
* Rb Rc
* | |
* +----+----+
* |
* E
*/
NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
{
NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
, m_RB(*this, "m_RB", true)
, m_RC(*this, "m_RC", true)
, m_BC_dummy(*this, "m_BC", true)
, m_gB(NETLIST_GMIN_DEFAULT)
, m_gC(NETLIST_GMIN_DEFAULT)
, m_V(0.0)
, m_state_on(*this, "m_state_on", 0)
{
register_subalias("B", m_RB.m_P);
register_subalias("E", m_RB.m_N);
register_subalias("C", m_RC.m_P);
//register_term("_E1", m_RC.m_N);
//register_term("_B1", m_BC_dummy.m_P);
//register_term("_C1", m_BC_dummy.m_N);
connect(m_RB.m_N, m_RC.m_N);
connect(m_RB.m_P, m_BC_dummy.m_P);
connect(m_RC.m_P, m_BC_dummy.m_N);
}
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
nld_twoterm m_RB;
nld_twoterm m_RC;
// FIXME: this is needed so we have all terminals belong to one net list
nld_twoterm m_BC_dummy;
protected:
nl_double m_gB; // base conductance / switch on
nl_double m_gC; // collector conductance / switch on
nl_double m_V; // internal voltage source
state_var<unsigned> m_state_on;
private:
};
// -----------------------------------------------------------------------------
// nld_QBJT_EB
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
, m_gD_BC(*this, "m_D_BC")
, m_gD_BE(*this, "m_D_BE")
, m_D_CB(*this, "m_D_CB", true)
, m_D_EB(*this, "m_D_EB", true)
, m_D_EC(*this, "m_D_EC", true)
, m_alpha_f(0)
, m_alpha_r(0)
{
register_subalias("E", m_D_EB.m_P); // Cathode
register_subalias("B", m_D_EB.m_N); // Anode
register_subalias("C", m_D_CB.m_P); // Cathode
//register_term("_B1", m_D_CB.m_N); // Anode
//register_term("_E1", m_D_EC.m_P);
//register_term("_C1", m_D_EC.m_N);
connect(m_D_EB.m_P, m_D_EC.m_P);
connect(m_D_EB.m_N, m_D_CB.m_N);
connect(m_D_CB.m_P, m_D_EC.m_N);
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
generic_diode m_gD_BC;
generic_diode m_gD_BE;
private:
nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
nl_double m_alpha_f;
nl_double m_alpha_r;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_BJT_H_ */

View File

@ -9,13 +9,11 @@
#define NLD_FOURTERM_H_
#include "nl_base.h"
#include "nld_twoterm.h"
#include "nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define VCCS(name) \
NET_REGISTER_DEV(VCCS, name)
@ -29,206 +27,4 @@
#define LVCCS(name) \
NET_REGISTER_DEV(LVCCS, name)
#endif
namespace netlist
{
namespace analog
{
// ----------------------------------------------------------------------------------------
// nld_VCCS
// ----------------------------------------------------------------------------------------
/*
* Voltage controlled current source
*
* IP ---+ +------> OP
* | |
* RI I
* RI => G => I IOut = (V(IP)-V(IN)) * G
* RI I
* | |
* IN ---+ +------< ON
*
* G=1 ==> 1V ==> 1A
*
* RI = 1 / NETLIST_GMIN
*
*/
NETLIB_OBJECT(VCCS)
{
public:
NETLIB_CONSTRUCTOR(VCCS)
, m_G(*this, "G", 1.0)
, m_RI(*this, "RI", 1e9)
, m_OP(*this, "OP")
, m_ON(*this, "ON")
, m_IP(*this, "IP")
, m_IN(*this, "IN")
, m_OP1(*this, "_OP1")
, m_ON1(*this, "_ON1")
, m_gfac(1.0)
{
m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
m_OP.m_otherterm = &m_IP;
m_OP1.m_otherterm = &m_IN;
m_ON.m_otherterm = &m_IP;
m_ON1.m_otherterm = &m_IN;
connect(m_OP, m_OP1);
connect(m_ON, m_ON1);
m_gfac = NL_FCONST(1.0);
}
param_double_t m_G;
param_double_t m_RI;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI()
{
NETLIB_NAME(VCCS)::reset();
}
terminal_t m_OP;
terminal_t m_ON;
terminal_t m_IP;
terminal_t m_IN;
terminal_t m_OP1;
terminal_t m_ON1;
nl_double m_gfac;
};
/* Limited Current source*/
NETLIB_OBJECT_DERIVED(LVCCS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS)
, m_cur_limit(*this, "CURLIM", 1000.0)
, m_vi(0.0)
{
}
NETLIB_IS_DYNAMIC(true)
param_double_t m_cur_limit; /* current limit */
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
nl_double m_vi;
};
// ----------------------------------------------------------------------------------------
// nld_CCCS
// ----------------------------------------------------------------------------------------
/*
* Current controlled current source
*
* IP ---+ +------> OP
* | |
* RI I
* RI => G => I IOut = (V(IP)-V(IN)) / RI * G
* RI I
* | |
* IN ---+ +------< ON
*
* G=1 ==> 1A ==> 1A
*
* RI = 1
*
* This needs high levels of accuracy to work with 1 Ohm RI.
*
*/
NETLIB_OBJECT_DERIVED(CCCS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
, m_gfac(1.0)
{
m_gfac = NL_FCONST(1.0) / m_RI();
}
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
nl_double m_gfac;
};
// ----------------------------------------------------------------------------------------
// nld_VCVS
// ----------------------------------------------------------------------------------------
/*
* Voltage controlled voltage source
*
* Parameters:
* G Default: 1
* RO Default: 1 (would be typically 50 for an op-amp
*
* IP ---+ +--+---- OP
* | | |
* RI I RO
* RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
* RI I RO
* | | |
* IN ---+ +--+---- ON
*
* G=1 ==> 1V ==> 1V
*
* RI = 1 / NETLIST_GMIN
*
* Internal GI = G / RO
*
*/
NETLIB_OBJECT_DERIVED(VCVS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
, m_RO(*this, "RO", 1.0)
, m_OP2(*this, "_OP2")
, m_ON2(*this, "_ON2")
{
m_OP2.m_otherterm = &m_ON2;
m_ON2.m_otherterm = &m_OP2;
connect(m_OP2, m_OP1);
connect(m_ON2, m_ON1);
}
param_double_t m_RO;
protected:
//NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
terminal_t m_OP2;
terminal_t m_ON2;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_FOURTERM_H_ */

View File

@ -5,10 +5,12 @@
*
*/
#include "devices/net_lib.h"
#include "nld_opamps.h"
#include "nl_base.h"
#include "nl_errstr.h"
#include "nlid_twoterm.h"
#include "nlid_fourterm.h"
#include <cmath>
@ -45,6 +47,61 @@ namespace netlist
*
* */
/*! Class representing the opamp model parameters.
* The opamp model was designed based on designs from
* http://www.ecircuitcenter.com/Circuits/opmodel1/opmodel1.htm.
* Currently 2 different types are supported: Type 1 and Type 3. Type 1
* is less complex and should run faster than Type 3.
*
* This is an extension to the traditional SPICE approach which
* assumes that you will be using an manufacturer model. These models may
* have copyrights incompatible with the netlist license. Thus they may not
* be suitable for certain implementations of netlist.
*
* For the typical use cases in low frequency (< 100 KHz) applications at
* which netlist is targeted, this model is certainly suitable. All parameters
* can be determined from a typical opamp datasheet.
*
* |Type|name |parameter |units|default| example|
* |:--:|:-----|:----------------------------------------------|:----|------:|-------:|
* | 3 |TYPE |Model Type, 1 and 3 are supported | | | |
* |1,3 |FPF |frequency of first pole |Hz | |100 |
* | 3 |SLEW |unity gain slew rate |V/s | | 1|
* |1,3 |RI |input resistance |Ohm | |1M |
* |1,3 |RO |output resistance |Ohm | |50 |
* |1,3 |UGF |unity gain frequency (transition frequency) |Hz | |1000 |
* | 3 |VLL |low output swing minus low supply rail |V | |1.5 |
* | 3 |VLH |high supply rail minus high output swing |V | |1.5 |
* | 3 |DAB |Differential Amp Bias - total quiescent current|A | |0.001 |
*/
class opamp_model_t : public param_model_t
{
public:
opamp_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_TYPE(*this, "TYPE")
, m_FPF(*this, "FPF")
, m_SLEW(*this, "SLEW")
, m_RI(*this, "RI")
, m_RO(*this, "RO")
, m_UGF(*this, "UGF")
, m_VLL(*this, "VLL")
, m_VLH(*this, "VLH")
, m_DAB(*this, "DAB")
{}
value_t m_TYPE; //!< Model Type, 1 and 3 are supported
value_t m_FPF; //!< frequency of first pole
value_t m_SLEW; //!< unity gain slew rate
value_t m_RI; //!< input resistance
value_t m_RO; //!< output resistance
value_t m_UGF; //!< unity gain frequency (transition frequency)
value_t m_VLL; //!< low output swing minus low supply rail
value_t m_VLH; //!< high supply rail minus high output swing
value_t m_DAB; //!< Differential Amp Bias - total quiescent current
};
NETLIB_OBJECT(opamp)
{

View File

@ -10,87 +10,15 @@
#ifndef NLD_OPAMPS_H_
#define NLD_OPAMPS_H_
#include "nl_base.h"
#include "nld_twoterm.h"
#include "nld_fourterm.h"
#include "nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define OPAMP(name, model) \
NET_REGISTER_DEV(OPAMP, name) \
NETDEV_PARAMI(name, MODEL, model)
#endif
// ----------------------------------------------------------------------------------------
// Devices ...
// ----------------------------------------------------------------------------------------
namespace netlist
{
namespace analog
{
/*! Class representing the opamp model parameters.
* The opamp model was designed based on designs from
* http://www.ecircuitcenter.com/Circuits/opmodel1/opmodel1.htm.
* Currently 2 different types are supported: Type 1 and Type 3. Type 1
* is less complex and should run faster than Type 3.
*
* This is an extension to the traditional SPICE approach which
* assumes that you will be using an manufacturer model. These models may
* have copyrights incompatible with the netlist license. Thus they may not
* be suitable for certain implementations of netlist.
*
* For the typical use cases in low frequency (< 100 KHz) applications at
* which netlist is targeted, this model is certainly suitable. All parameters
* can be determined from a typical opamp datasheet.
*
* |Type|name |parameter |units|default| example|
* |:--:|:-----|:----------------------------------------------|:----|------:|-------:|
* | 3 |TYPE |Model Type, 1 and 3 are supported | | | |
* |1,3 |FPF |frequency of first pole |Hz | |100 |
* | 3 |SLEW |unity gain slew rate |V/s | | 1|
* |1,3 |RI |input resistance |Ohm | |1M |
* |1,3 |RO |output resistance |Ohm | |50 |
* |1,3 |UGF |unity gain frequency (transition frequency) |Hz | |1000 |
* | 3 |VLL |low output swing minus low supply rail |V | |1.5 |
* | 3 |VLH |high supply rail minus high output swing |V | |1.5 |
* | 3 |DAB |Differential Amp Bias - total quiescent current|A | |0.001 |
*/
class opamp_model_t : public param_model_t
{
public:
opamp_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_TYPE(*this, "TYPE")
, m_FPF(*this, "FPF")
, m_SLEW(*this, "SLEW")
, m_RI(*this, "RI")
, m_RO(*this, "RO")
, m_UGF(*this, "UGF")
, m_VLL(*this, "VLL")
, m_VLH(*this, "VLH")
, m_DAB(*this, "DAB")
{}
value_t m_TYPE; //!< Model Type, 1 and 3 are supported
value_t m_FPF; //!< frequency of first pole
value_t m_SLEW; //!< unity gain slew rate
value_t m_RI; //!< input resistance
value_t m_RO; //!< output resistance
value_t m_UGF; //!< unity gain frequency (transition frequency)
value_t m_VLL; //!< low output swing minus low supply rail
value_t m_VLH; //!< high supply rail minus high output swing
value_t m_DAB; //!< Differential Amp Bias - total quiescent current
};
} //namespace analog
} // namespace netlist
#endif /* NLD_OPAMPS_H_ */

View File

@ -5,8 +5,9 @@
*
*/
#include "nld_switches.h"
#include "nl_setup.h"
#include "nlid_twoterm.h"
#include "nl_base.h"
#include "nl_factory.h"
#define R_OFF (1.0 / netlist().gmin())
#define R_ON 0.01

View File

@ -10,21 +10,16 @@
#ifndef NLD_SWITCHES_H_
#define NLD_SWITCHES_H_
#include "nl_base.h"
#include "nld_twoterm.h"
#include "nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define SWITCH(name) \
NET_REGISTER_DEV(SWITCH, name)
#define SWITCH2(name) \
NET_REGISTER_DEV(SWITCH2, name)
#endif
#endif /* NLD_SWITCHES_H_ */

View File

@ -1,47 +1,15 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_twoterm.h
*
* Devices with two terminals ...
*
*
* (k)
* +-----T-----+
* | | |
* | +--+--+ |
* | | | |
* | R | |
* | R | |
* | R I |
* | | I | Device n
* | V+ I |
* | V | |
* | V- | |
* | | | |
* | +--+--+ |
* | | |
* +-----T-----+
* (l)
*
* This is a resistance in series to a voltage source and paralleled by a
* current source. This is suitable to model voltage sources, current sources,
* resistors, capacitors, inductances and diodes.
*
*/
#ifndef NLD_TWOTERM_H_
#define NLD_TWOTERM_H_
#include "nl_base.h"
#include "plib/pfunction.h"
#include "nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
// -----------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define RES(name, p_R) \
NET_REGISTER_DEV(RES, name) \
NETDEV_PARAMI(name, R, p_R)
@ -77,8 +45,6 @@
NET_REGISTER_DEV(CS, name) \
NETDEV_PARAMI(name, I, pI)
#endif
// -----------------------------------------------------------------------------
// Generic macros
// -----------------------------------------------------------------------------
@ -100,412 +66,4 @@
#define IND_P(ind) (static_cast<double>(ind) * 1e-12)
#endif
// -----------------------------------------------------------------------------
// Implementation
// -----------------------------------------------------------------------------
namespace netlist
{
namespace analog
{
// -----------------------------------------------------------------------------
// nld_twoterm
// -----------------------------------------------------------------------------
NETLIB_OBJECT(twoterm)
{
NETLIB_CONSTRUCTOR_EX(twoterm, bool terminals_owned = false)
, m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1")
, m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
{
m_P.m_otherterm = &m_N;
m_N.m_otherterm = &m_P;
}
terminal_t m_P;
terminal_t m_N;
//NETLIB_UPDATE_TERMINALSI() { }
//NETLIB_RESETI() { }
NETLIB_UPDATEI();
public:
/* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
{
/* GO, GT, I */
m_P.set( G, G, ( V) * G - I);
m_N.set( G, G, ( -V) * G + I);
}
/* inline */ nl_double deltaV() const
{
return m_P.net().Q_Analog() - m_N.net().Q_Analog();
}
void set_mat(const nl_double a11, const nl_double a12, const nl_double r1,
const nl_double a21, const nl_double a22, const nl_double r2)
{
/* GO, GT, I */
m_P.set(-a12, a11, r1);
m_N.set(-a21, a22, r2);
}
private:
template <class C>
static core_device_t &bselect(bool b, C &d1, core_device_t &d2)
{
core_device_t *h = dynamic_cast<core_device_t *>(&d1);
return b ? *h : d2;
}
};
// -----------------------------------------------------------------------------
// nld_R
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(R_base, twoterm)
{
NETLIB_CONSTRUCTOR_DERIVED(R_base, twoterm)
{
}
public:
inline void set_R(const nl_double R)
{
const nl_double G = NL_FCONST(1.0) / R;
set_mat( G, -G, 0.0,
-G, G, 0.0);
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
};
NETLIB_OBJECT_DERIVED(R, R_base)
{
NETLIB_CONSTRUCTOR_DERIVED(R, R_base)
, m_R(*this, "R", 1e9)
{
}
param_double_t m_R;
protected:
NETLIB_RESETI();
//NETLIB_UPDATEI() { }
NETLIB_UPDATE_PARAMI();
private:
/* protect set_R ... it's a recipe to desaster when used to bypass the parameter */
using NETLIB_NAME(R_base)::set_R;
};
// -----------------------------------------------------------------------------
// nld_POT
// -----------------------------------------------------------------------------
NETLIB_OBJECT(POT)
{
NETLIB_CONSTRUCTOR(POT)
, m_R1(*this, "_R1")
, m_R2(*this, "_R2")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_DialIsLog(*this, "DIALLOG", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
register_subalias("3", m_R2.m_N);
connect(m_R2.m_P, m_R1.m_N);
}
//NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
private:
NETLIB_SUB(R_base) m_R1;
NETLIB_SUB(R_base) m_R2;
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
};
NETLIB_OBJECT(POT2)
{
NETLIB_CONSTRUCTOR(POT2)
, m_R1(*this, "_R1")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_DialIsLog(*this, "DIALLOG", 0)
, m_Reverse(*this, "REVERSE", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
}
//NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
private:
NETLIB_SUB(R_base) m_R1;
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
param_logic_t m_Reverse;
};
// -----------------------------------------------------------------------------
// nld_C
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(C, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
, m_C(*this, "C", 1e-6)
, m_GParallel(0.0)
{
//register_term("1", m_P);
//register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
param_double_t m_C;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
nl_double m_GParallel;
};
// -----------------------------------------------------------------------------
// nld_L
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(L, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
, m_L(*this, "L", 1e-6)
, m_GParallel(0.0)
, m_G(0.0)
, m_I(0.0)
{
//register_term("1", m_P);
//register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
param_double_t m_L;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
nl_double m_GParallel;
nl_double m_G;
nl_double m_I;
};
// -----------------------------------------------------------------------------
// A generic diode model to be used in other devices (Diode, BJT ...)
// -----------------------------------------------------------------------------
class generic_diode
{
public:
generic_diode(device_t &dev, pstring name);
void update_diode(const double nVd);
void set_param(const double Is, const double n, double gmin);
inline double I() const { return m_Id; }
inline double G() const { return m_G; }
inline double Ieq() const { return (m_Id - m_Vd * m_G); }
inline double Vd() const { return m_Vd; }
/* owning object must save those ... */
private:
state_var<double> m_Vd;
state_var<double> m_Id;
state_var<double> m_G;
double m_Vt;
double m_Vmin;
double m_Is;
double m_n;
double m_gmin;
double m_VtInv;
double m_Vcrit;
};
/*! Class representing the diode model paramers.
* This is the model representation of the diode model. Typically, SPICE uses
* the following parameters. A "Y" in the first column indicates that the
* parameter is actually used in netlist.
*
* |NL? |name |parameter |units|default| example|area |
* |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
* | Y |IS |saturation current |A |1.0e-14| 1.0e-14| * |
* | |RS |ohmic resistanc |Ohm | 0| 10| * |
* | Y |N |emission coefficient |- | 1| 1| |
* | |TT |transit-time |sec | 0| 0.1ns| |
* | |CJO |zero-bias junction capacitance |F | 0| 2pF| * |
* | |VJ |junction potential |V | 1| 0.6| |
* | |M |grading coefficient |- | 0.5| 0.5| |
* | |EG |band-gap energy |eV | 1.11| 1.11 Si| |
* | |XTI |saturation-current temp.exp |- | 3|3.0 pn. 2.0 Schottky| |
* | |KF |flicker noise coefficient |- | 0| | |
* | |AF |flicker noise exponent |- | 1| | |
* | |FC |coefficient for forward-bias depletion capacitance formula|-|0.5|| |
* | |BV |reverse breakdown voltage |V |infinite| 40| |
* | |IBV |current at breakdown voltage |V | 0.001| | |
* | |TNOM |parameter measurement temperature|deg C| 27| 50| |
*
*/
class diode_model_t : public param_model_t
{
public:
diode_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_IS(*this, "IS")
, m_N(*this, "N")
{}
value_t m_IS; //!< saturation current.
value_t m_N; //!< emission coefficient.
};
// -----------------------------------------------------------------------------
// nld_D
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(D, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(D, twoterm)
, m_model(*this, "MODEL", "")
, m_D(*this, "m_D")
{
register_subalias("A", m_P);
register_subalias("K", m_N);
}
template <class CLASS>
NETLIB_NAME(D)(CLASS &owner, const pstring name, const pstring model)
: NETLIB_NAME(twoterm)(owner, name)
, m_model(*this, "MODEL", model)
, m_D(*this, "m_D")
{
register_subalias("A", m_P);
register_subalias("K", m_N);
}
NETLIB_IS_DYNAMIC(true)
NETLIB_UPDATE_TERMINALSI();
diode_model_t m_model;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
generic_diode m_D;
};
// -----------------------------------------------------------------------------
// nld_VS - Voltage source
//
// netlist voltage source must have inner resistance
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(VS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
, m_R(*this, "R", 0.1)
, m_V(*this, "V", 0.0)
, m_func(*this,"FUNC", "")
{
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
}
NETLIB_IS_TIMESTEP(m_func() != "")
NETLIB_TIMESTEPI();
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
param_double_t m_R;
param_double_t m_V;
param_str_t m_func;
plib::pfunction m_compiled;
};
// -----------------------------------------------------------------------------
// nld_CS - Current source
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(CS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
, m_I(*this, "I", 1.0)
, m_func(*this,"FUNC", "")
{
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
}
NETLIB_IS_TIMESTEP(m_func() != "")
NETLIB_TIMESTEPI();
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
param_double_t m_I;
param_str_t m_func;
plib::pfunction m_compiled;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_TWOTERM_H_ */

View File

@ -6,7 +6,7 @@
*/
#include "solver/nld_solver.h"
#include "nld_fourterm.h"
#include "nlid_fourterm.h"
#include "nl_setup.h"
#include <cmath>
@ -15,6 +15,8 @@ namespace netlist
{
namespace analog
{
// ----------------------------------------------------------------------------------------
// nld_VCCS
// ----------------------------------------------------------------------------------------

View File

@ -0,0 +1,211 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nlid_fourterm.h
*
*/
#ifndef NLID_FOURTERM_H_
#define NLID_FOURTERM_H_
#include "nl_base.h"
namespace netlist {
namespace analog {
// ----------------------------------------------------------------------------------------
// nld_VCCS
// ----------------------------------------------------------------------------------------
/*
* Voltage controlled current source
*
* IP ---+ +------> OP
* | |
* RI I
* RI => G => I IOut = (V(IP)-V(IN)) * G
* RI I
* | |
* IN ---+ +------< ON
*
* G=1 ==> 1V ==> 1A
*
* RI = 1 / NETLIST_GMIN
*
*/
NETLIB_OBJECT(VCCS)
{
public:
NETLIB_CONSTRUCTOR(VCCS)
, m_G(*this, "G", 1.0)
, m_RI(*this, "RI", 1e9)
, m_OP(*this, "OP")
, m_ON(*this, "ON")
, m_IP(*this, "IP")
, m_IN(*this, "IN")
, m_OP1(*this, "_OP1")
, m_ON1(*this, "_ON1")
, m_gfac(1.0)
{
m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
m_OP.m_otherterm = &m_IP;
m_OP1.m_otherterm = &m_IN;
m_ON.m_otherterm = &m_IP;
m_ON1.m_otherterm = &m_IN;
connect(m_OP, m_OP1);
connect(m_ON, m_ON1);
m_gfac = NL_FCONST(1.0);
}
param_double_t m_G;
param_double_t m_RI;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI()
{
NETLIB_NAME(VCCS)::reset();
}
terminal_t m_OP;
terminal_t m_ON;
terminal_t m_IP;
terminal_t m_IN;
terminal_t m_OP1;
terminal_t m_ON1;
nl_double m_gfac;
};
/* Limited Current source*/
NETLIB_OBJECT_DERIVED(LVCCS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS)
, m_cur_limit(*this, "CURLIM", 1000.0)
, m_vi(0.0)
{
}
NETLIB_IS_DYNAMIC(true)
param_double_t m_cur_limit; /* current limit */
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
NETLIB_UPDATE_TERMINALSI();
nl_double m_vi;
};
// ----------------------------------------------------------------------------------------
// nld_CCCS
// ----------------------------------------------------------------------------------------
/*
* Current controlled current source
*
* IP ---+ +------> OP
* | |
* RI I
* RI => G => I IOut = (V(IP)-V(IN)) / RI * G
* RI I
* | |
* IN ---+ +------< ON
*
* G=1 ==> 1A ==> 1A
*
* RI = 1
*
* This needs high levels of accuracy to work with 1 Ohm RI.
*
*/
NETLIB_OBJECT_DERIVED(CCCS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
, m_gfac(1.0)
{
m_gfac = NL_FCONST(1.0) / m_RI();
}
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
nl_double m_gfac;
};
// ----------------------------------------------------------------------------------------
// nld_VCVS
// ----------------------------------------------------------------------------------------
/*
* Voltage controlled voltage source
*
* Parameters:
* G Default: 1
* RO Default: 1 (would be typically 50 for an op-amp
*
* IP ---+ +--+---- OP
* | | |
* RI I RO
* RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
* RI I RO
* | | |
* IN ---+ +--+---- ON
*
* G=1 ==> 1V ==> 1V
*
* RI = 1 / NETLIST_GMIN
*
* Internal GI = G / RO
*
*/
NETLIB_OBJECT_DERIVED(VCVS, VCCS)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
, m_RO(*this, "RO", 1.0)
, m_OP2(*this, "_OP2")
, m_ON2(*this, "_ON2")
{
m_OP2.m_otherterm = &m_ON2;
m_ON2.m_otherterm = &m_OP2;
connect(m_OP2, m_OP1);
connect(m_ON2, m_ON1);
}
param_double_t m_RO;
protected:
//NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
terminal_t m_OP2;
terminal_t m_ON2;
};
}
}
#endif /* NLD_FOURTERM_H_ */

View File

@ -7,7 +7,8 @@
#include "solver/nld_solver.h"
#include "nld_twoterm.h"
#include "nlid_twoterm.h"
#include "nl_factory.h"
#include <cmath>

View File

@ -0,0 +1,447 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_twoterm.h
*
* Devices with two terminals ...
*
*
* (k)
* +-----T-----+
* | | |
* | +--+--+ |
* | | | |
* | R | |
* | R | |
* | R I |
* | | I | Device n
* | V+ I |
* | V | |
* | V- | |
* | | | |
* | +--+--+ |
* | | |
* +-----T-----+
* (l)
*
* This is a resistance in series to a voltage source and paralleled by a
* current source. This is suitable to model voltage sources, current sources,
* resistors, capacitors, inductances and diodes.
*
*/
#ifndef NLID_TWOTERM_H_
#define NLID_TWOTERM_H_
#include "nl_base.h"
#include "plib/pfunction.h"
// -----------------------------------------------------------------------------
// Implementation
// -----------------------------------------------------------------------------
namespace netlist
{
namespace analog
{
// -----------------------------------------------------------------------------
// nld_twoterm
// -----------------------------------------------------------------------------
NETLIB_OBJECT(twoterm)
{
NETLIB_CONSTRUCTOR_EX(twoterm, bool terminals_owned = false)
, m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1")
, m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
{
m_P.m_otherterm = &m_N;
m_N.m_otherterm = &m_P;
}
terminal_t m_P;
terminal_t m_N;
//NETLIB_UPDATE_TERMINALSI() { }
//NETLIB_RESETI() { }
NETLIB_UPDATEI();
public:
/* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
{
/* GO, GT, I */
m_P.set( G, G, ( V) * G - I);
m_N.set( G, G, ( -V) * G + I);
}
/* inline */ nl_double deltaV() const
{
return m_P.net().Q_Analog() - m_N.net().Q_Analog();
}
void set_mat(const nl_double a11, const nl_double a12, const nl_double r1,
const nl_double a21, const nl_double a22, const nl_double r2)
{
/* GO, GT, I */
m_P.set(-a12, a11, r1);
m_N.set(-a21, a22, r2);
}
private:
template <class C>
static core_device_t &bselect(bool b, C &d1, core_device_t &d2)
{
core_device_t *h = dynamic_cast<core_device_t *>(&d1);
return b ? *h : d2;
}
};
// -----------------------------------------------------------------------------
// nld_R
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(R_base, twoterm)
{
NETLIB_CONSTRUCTOR_DERIVED(R_base, twoterm)
{
}
public:
inline void set_R(const nl_double R)
{
const nl_double G = NL_FCONST(1.0) / R;
set_mat( G, -G, 0.0,
-G, G, 0.0);
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
};
NETLIB_OBJECT_DERIVED(R, R_base)
{
NETLIB_CONSTRUCTOR_DERIVED(R, R_base)
, m_R(*this, "R", 1e9)
{
}
param_double_t m_R;
protected:
NETLIB_RESETI();
//NETLIB_UPDATEI() { }
NETLIB_UPDATE_PARAMI();
private:
/* protect set_R ... it's a recipe to desaster when used to bypass the parameter */
using NETLIB_NAME(R_base)::set_R;
};
// -----------------------------------------------------------------------------
// nld_POT
// -----------------------------------------------------------------------------
NETLIB_OBJECT(POT)
{
NETLIB_CONSTRUCTOR(POT)
, m_R1(*this, "_R1")
, m_R2(*this, "_R2")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_DialIsLog(*this, "DIALLOG", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
register_subalias("3", m_R2.m_N);
connect(m_R2.m_P, m_R1.m_N);
}
//NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
private:
NETLIB_SUB(R_base) m_R1;
NETLIB_SUB(R_base) m_R2;
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
};
NETLIB_OBJECT(POT2)
{
NETLIB_CONSTRUCTOR(POT2)
, m_R1(*this, "_R1")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_DialIsLog(*this, "DIALLOG", 0)
, m_Reverse(*this, "REVERSE", 0)
{
register_subalias("1", m_R1.m_P);
register_subalias("2", m_R1.m_N);
}
//NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
private:
NETLIB_SUB(R_base) m_R1;
param_double_t m_R;
param_double_t m_Dial;
param_logic_t m_DialIsLog;
param_logic_t m_Reverse;
};
// -----------------------------------------------------------------------------
// nld_C
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(C, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
, m_C(*this, "C", 1e-6)
, m_GParallel(0.0)
{
//register_term("1", m_P);
//register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
param_double_t m_C;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
nl_double m_GParallel;
};
// -----------------------------------------------------------------------------
// nld_L
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(L, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
, m_L(*this, "L", 1e-6)
, m_GParallel(0.0)
, m_G(0.0)
, m_I(0.0)
{
//register_term("1", m_P);
//register_term("2", m_N);
}
NETLIB_IS_TIMESTEP(true)
NETLIB_TIMESTEPI();
param_double_t m_L;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
private:
nl_double m_GParallel;
nl_double m_G;
nl_double m_I;
};
// -----------------------------------------------------------------------------
// A generic diode model to be used in other devices (Diode, BJT ...)
// -----------------------------------------------------------------------------
class generic_diode
{
public:
generic_diode(device_t &dev, pstring name);
void update_diode(const double nVd);
void set_param(const double Is, const double n, double gmin);
inline double I() const { return m_Id; }
inline double G() const { return m_G; }
inline double Ieq() const { return (m_Id - m_Vd * m_G); }
inline double Vd() const { return m_Vd; }
/* owning object must save those ... */
private:
state_var<double> m_Vd;
state_var<double> m_Id;
state_var<double> m_G;
double m_Vt;
double m_Vmin;
double m_Is;
double m_n;
double m_gmin;
double m_VtInv;
double m_Vcrit;
};
/*! Class representing the diode model paramers.
* This is the model representation of the diode model. Typically, SPICE uses
* the following parameters. A "Y" in the first column indicates that the
* parameter is actually used in netlist.
*
* |NL? |name |parameter |units|default| example|area |
* |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
* | Y |IS |saturation current |A |1.0e-14| 1.0e-14| * |
* | |RS |ohmic resistanc |Ohm | 0| 10| * |
* | Y |N |emission coefficient |- | 1| 1| |
* | |TT |transit-time |sec | 0| 0.1ns| |
* | |CJO |zero-bias junction capacitance |F | 0| 2pF| * |
* | |VJ |junction potential |V | 1| 0.6| |
* | |M |grading coefficient |- | 0.5| 0.5| |
* | |EG |band-gap energy |eV | 1.11| 1.11 Si| |
* | |XTI |saturation-current temp.exp |- | 3|3.0 pn. 2.0 Schottky| |
* | |KF |flicker noise coefficient |- | 0| | |
* | |AF |flicker noise exponent |- | 1| | |
* | |FC |coefficient for forward-bias depletion capacitance formula|-|0.5|| |
* | |BV |reverse breakdown voltage |V |infinite| 40| |
* | |IBV |current at breakdown voltage |V | 0.001| | |
* | |TNOM |parameter measurement temperature|deg C| 27| 50| |
*
*/
class diode_model_t : public param_model_t
{
public:
diode_model_t(device_t &device, const pstring name, const pstring val)
: param_model_t(device, name, val)
, m_IS(*this, "IS")
, m_N(*this, "N")
{}
value_t m_IS; //!< saturation current.
value_t m_N; //!< emission coefficient.
};
// -----------------------------------------------------------------------------
// nld_D
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(D, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(D, twoterm)
, m_model(*this, "MODEL", "")
, m_D(*this, "m_D")
{
register_subalias("A", m_P);
register_subalias("K", m_N);
}
template <class CLASS>
NETLIB_NAME(D)(CLASS &owner, const pstring name, const pstring model)
: NETLIB_NAME(twoterm)(owner, name)
, m_model(*this, "MODEL", model)
, m_D(*this, "m_D")
{
register_subalias("A", m_P);
register_subalias("K", m_N);
}
NETLIB_IS_DYNAMIC(true)
NETLIB_UPDATE_TERMINALSI();
diode_model_t m_model;
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI();
generic_diode m_D;
};
// -----------------------------------------------------------------------------
// nld_VS - Voltage source
//
// netlist voltage source must have inner resistance
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(VS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
, m_R(*this, "R", 0.1)
, m_V(*this, "V", 0.0)
, m_func(*this,"FUNC", "")
{
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
}
NETLIB_IS_TIMESTEP(m_func() != "")
NETLIB_TIMESTEPI();
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
param_double_t m_R;
param_double_t m_V;
param_str_t m_func;
plib::pfunction m_compiled;
};
// -----------------------------------------------------------------------------
// nld_CS - Current source
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(CS, twoterm)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
, m_I(*this, "I", 1.0)
, m_func(*this,"FUNC", "")
{
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
}
NETLIB_IS_TIMESTEP(m_func() != "")
NETLIB_TIMESTEPI();
protected:
NETLIB_UPDATEI();
NETLIB_RESETI();
param_double_t m_I;
param_str_t m_func;
plib::pfunction m_compiled;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_TWOTERM_H_ */

View File

@ -64,9 +64,9 @@ NLOBJS := \
$(NLOBJ)/nl_setup.o \
$(NLOBJ)/nl_factory.o \
$(NLOBJ)/analog/nld_bjt.o \
$(NLOBJ)/analog/nld_fourterm.o \
$(NLOBJ)/analog/nlid_fourterm.o \
$(NLOBJ)/analog/nld_switches.o \
$(NLOBJ)/analog/nld_twoterm.o \
$(NLOBJ)/analog/nlid_twoterm.o \
$(NLOBJ)/analog/nld_opamps.o \
$(NLOBJ)/devices/nld_2102A.o \
$(NLOBJ)/devices/nld_2716.o \
@ -115,7 +115,7 @@ NLOBJS := \
$(NLOBJ)/devices/nld_log.o \
$(NLOBJ)/devices/nlid_proxy.o \
$(NLOBJ)/devices/nld_system.o \
$(NLOBJ)/devices/nld_truthtable.o \
$(NLOBJ)/devices/nlid_truthtable.o \
$(NLOBJ)/macro/nlm_base.o \
$(NLOBJ)/macro/nlm_cd4xxx.o \
$(NLOBJ)/macro/nlm_opamp.o \

View File

@ -28,11 +28,9 @@
namespace netlist
{
using namespace netlist::analog;
namespace devices
{
static void initialize_factory(factory::list_t &factory)
void initialize_factory(factory::list_t &factory)
{
ENTRYX(R, RES, "R")
ENTRYX(POT, POT, "R")
@ -162,10 +160,3 @@ static void initialize_factory(factory::list_t &factory)
} //namespace devices
} // namespace netlist
namespace netlist
{
void initialize_factory(factory::list_t &factory)
{
devices::initialize_factory(factory);
}
}

View File

@ -11,18 +11,13 @@
#ifndef NET_LIB_H
#define NET_LIB_H
#include "nl_base.h"
#include "nl_setup.h"
//#define NL_AUTO_DEVICES 1
#ifdef NL_AUTO_DEVICES
#include "nld_devinc.h"
#include "analog/nld_bjt.h"
#include "analog/nld_fourterm.h"
#include "analog/nld_switches.h"
#include "analog/nld_twoterm.h"
#include "analog/nld_opamps.h"
#include "solver/nld_solver.h"
#include "macro/nlm_cd4xxx.h"
@ -33,6 +28,11 @@
#include "nld_7448.h"
#else
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#include "nld_system.h"
#include "nld_2102A.h"
@ -93,13 +93,8 @@
#include "analog/nld_switches.h"
#include "analog/nld_twoterm.h"
#include "analog/nld_opamps.h"
#include "solver/nld_solver.h"
#include "nld_legacy.h"
#endif
namespace netlist {
void initialize_factory(factory::list_t &factory);
}
#endif

View File

@ -6,6 +6,7 @@
*/
#include "nld_2102A.h"
#include "nl_base.h"
#define ADDR2BYTE(a) ((a) >> 3)
#define ADDR2BIT(a) ((a) & 0x7)

View File

@ -6,6 +6,7 @@
*/
#include "nld_2716.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,7 +6,7 @@
*/
#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#include "nld_4066.h"
namespace netlist

View File

@ -6,7 +6,7 @@
*/
#include "devices/nlid_cmos.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#include "nld_4316.h"
namespace netlist { namespace devices {

View File

@ -6,6 +6,7 @@
*/
#include "nld_74107.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -5,10 +5,8 @@
*
*/
#include "nld_74123.h"
#include "nlid_system.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#include <cmath>

View File

@ -6,6 +6,7 @@
*/
#include "nld_74153.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -8,6 +8,7 @@
#define MAXCNT 15
#include "nld_74161.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74165.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74166.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74174.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74175.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -8,6 +8,7 @@
#define MAXCNT 9
#include "nld_74192.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -8,6 +8,7 @@
#define MAXCNT 15
#include "nld_74193.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74194.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -5,8 +5,9 @@
*
*/
#include "nlid_truthtable.h"
#include "nld_74279.h"
#include "nld_truthtable.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_74365.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -5,8 +5,8 @@
*
*/
#include "nlid_truthtable.h"
#include "nld_7448.h"
#include "nld_truthtable.h"
namespace netlist
{

View File

@ -24,7 +24,7 @@
#ifndef NLD_7448_H_
#define NLD_7448_H_
#include "nl_base.h"
#include "nl_setup.h"
/*
* FIXME: Using truthtable is a lot slower than the explicit device

View File

@ -6,6 +6,7 @@
*/
#include "nld_7450.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_7473.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_7474.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -7,6 +7,7 @@
*/
#include "nld_7475.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_7483.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_7485.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_7490.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,7 +6,7 @@
*/
#include "nld_7493.h"
#include "nl_setup.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -40,7 +40,7 @@
#include "nld_74ls629.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_82S115.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_82S123.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_82S126.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_82S16.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_9310.h"
#include "nl_base.h"
#define MAXCNT 9

View File

@ -20,8 +20,8 @@
* | 1 | 1 | 1 | 0 || D7|D7Q|
* +---+---+---+---++---+---+
*/
#include "nlid_truthtable.h"
#include "nld_9312.h"
#include "nld_truthtable.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_9316.h"
#include "nl_base.h"
#define MAXCNT 15

View File

@ -6,6 +6,7 @@
*/
#include "nld_9322.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_am2847.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_dm9334.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -6,7 +6,7 @@
*/
#include "nld_legacy.h"
#include "nl_setup.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -7,7 +7,7 @@
#include "nld_mm5837.h"
#include "solver/nld_matrix_solver.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#define R_LOW (1000.0)
#define R_HIGH (1000.0)

View File

@ -6,7 +6,7 @@
*/
#include "nld_ne555.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#include "solver/nld_solver.h"
#define R_OFF (1E20)

View File

@ -5,8 +5,9 @@
*
*/
#include "nld_r2r_dac.h"
#include "analog/nld_twoterm.h"
#include "nl_base.h"
#include "nl_factory.h"
#include "analog/nlid_twoterm.h"
namespace netlist
{

View File

@ -6,6 +6,7 @@
*/
#include "nld_tristate.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -9,6 +9,7 @@
#define NLID_CMOS_H_
#include "nl_setup.h"
#include "nl_base.h"
namespace netlist
{

View File

@ -112,9 +112,9 @@ namespace netlist
{
pstring devname = out_proxied->device().name();
auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
detail::core_terminal_t::type_t::INPUT, false);
detail::terminal_type::INPUT, false);
auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
detail::core_terminal_t::type_t::INPUT, false);
detail::terminal_type::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
/* alternative logic */
@ -127,7 +127,7 @@ namespace netlist
log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name());
#if (0)
printf("%s %s\n", out_proxied->name().c_str(), out_proxied->device().name().c_str());
auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::type_t::OUTPUT, false);
auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::terminal_type::OUTPUT, false);
if (x) printf("==> %s\n", x->name().c_str());
#endif
}

View File

@ -12,7 +12,7 @@
#define NLID_PROXY_H_
#include "nl_setup.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
namespace netlist
{

View File

@ -11,8 +11,9 @@
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_
#include "nl_base.h"
#include "nl_setup.h"
#include "analog/nld_twoterm.h"
#include "analog/nlid_twoterm.h"
#include "plib/putil.h"
namespace netlist

View File

@ -5,7 +5,7 @@
*
*/
#include "nld_truthtable.h"
#include "nlid_truthtable.h"
#include "plib/plists.h"
#include "nl_setup.h"
#include "plib/palloc.h"

View File

@ -7,10 +7,11 @@
* Author: andre
*/
#ifndef NLD_TRUTHTABLE_H_
#define NLD_TRUTHTABLE_H_
#ifndef NLID_TRUTHTABLE_H_
#define NLID_TRUTHTABLE_H_
#include "nl_setup.h"
#include "nl_base.h"
#include "plib/putil.h"
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
@ -381,4 +382,4 @@ namespace netlist
#endif /* NLD_TRUTHTABLE_H_ */
#endif /* NLID_TRUTHTABLE_H_ */

View File

@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_cd4xxx.h"
#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"
#include "devices/nld_4020.h"
#include "devices/nld_4066.h"

View File

@ -1,9 +1,7 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#include "nlm_opamp.h"
#include "analog/nld_opamps.h"
#include "devices/nld_system.h"
#include "devices/net_lib.h"
/*
* Generic layout with 4 opamps, VCC on pin 4 and GND on pin 11

View File

@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_other.h"
#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"
/*

View File

@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_ttl74xx.h"
#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"

View File

@ -216,22 +216,22 @@ detail::device_object_t::device_object_t(core_device_t &dev, const pstring &anam
{
}
detail::core_terminal_t::type_t detail::core_terminal_t::type() const
detail::terminal_type detail::core_terminal_t::type() const
{
if (dynamic_cast<const terminal_t *>(this) != nullptr)
return type_t::TERMINAL;
return terminal_type::TERMINAL;
else if (dynamic_cast<const logic_input_t *>(this) != nullptr)
return type_t::INPUT;
return terminal_type::INPUT;
else if (dynamic_cast<const logic_output_t *>(this) != nullptr)
return type_t::OUTPUT;
return terminal_type::OUTPUT;
else if (dynamic_cast<const analog_input_t *>(this) != nullptr)
return type_t::INPUT;
return terminal_type::INPUT;
else if (dynamic_cast<const analog_output_t *>(this) != nullptr)
return type_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
}
}

View File

@ -20,6 +20,10 @@
#include <unordered_map>
#ifdef NL_PROHIBIT_BASEH_INCLUDE
#error "nl_base.h included. Please correct."
#endif
// ----------------------------------------------------------------------------------------
// Type definitions
// ----------------------------------------------------------------------------------------
@ -224,11 +228,6 @@ namespace netlist
class core_device_t;
class device_t;
/*! Type of the model map used.
* This is used to hold all #Models in an unordered map
*/
using model_map_t = std::unordered_map<pstring, pstring>;
/*! Logic families descriptors are used to create proxy devices.
* The logic family describes the analog capabilities of logic devices,
* inputs and outputs.
@ -481,25 +480,18 @@ namespace netlist
STATE_BIDIR = 256
};
/*! Enum specifying the type of object */
enum type_t {
TERMINAL = 0, /*!< object is an analog terminal */
INPUT = 1, /*!< object is an input */
OUTPUT = 2, /*!< object is an output */
};
core_terminal_t(core_device_t &dev, const pstring &aname, const state_e state);
virtual ~core_terminal_t();
/*! The object type.
* \returns type of the object
*/
type_t type() const;
terminal_type type() const;
/*! Checks if object is of specified type.
* \param atype type to check object against.
* \returns true if object is of specified type else false.
*/
bool is_type(const type_t atype) const { return (type() == atype); }
bool is_type(const terminal_type atype) const { return (type() == atype); }
void set_net(net_t *anet);
void clear_net();
@ -980,7 +972,7 @@ namespace netlist
private:
/* hide this */
void setTo(const pstring &param) = delete;
model_map_t m_map;
detail::model_map_t m_map;
};

View File

@ -9,10 +9,7 @@
#ifndef NLCONFIG_H_
#define NLCONFIG_H_
#include <cstdint>
#include "plib/pconfig.h"
#include "plib/pchrono.h"
//============================================================
// SETUP
@ -66,20 +63,6 @@
#define HAS_OPENMP (0)
#endif
//============================================================
// Performance tracking
//============================================================
namespace netlist
{
#if NL_KEEP_STATISTICS
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, true>;
using nperfcount_t = plib::chrono::counter<true>;
#else
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
using nperfcount_t = plib::chrono::counter<false>;
#endif
}
//============================================================
// General
//============================================================

View File

@ -9,6 +9,7 @@
****************************************************************************/
#include "nl_factory.h"
#include "nl_base.h"
#include "nl_setup.h"
#include "plib/putil.h"
#include "nl_errstr.h"
@ -16,6 +17,20 @@
namespace netlist { namespace factory
{
class NETLIB_NAME(wrapper) : public device_t
{
public:
NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
{
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
};
element_t::element_t(const pstring &name, const pstring &classname,
const pstring &def_param, const pstring &sourcefile)
: m_name(name), m_classname(classname), m_def_param(def_param),

View File

@ -9,7 +9,8 @@
#ifndef NLFACTORY_H_
#define NLFACTORY_H_
#include "nl_base.h"
#include "plib/palloc.h"
#include "plib/ptypes.h"
#define NETLIB_DEVICE_IMPL(chip) \
static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
@ -27,8 +28,12 @@
} \
factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
namespace netlist { namespace factory
{
namespace netlist {
class netlist_t;
class device_t;
class setup_t;
namespace factory {
// -----------------------------------------------------------------------------
// net_dev class factory
// -----------------------------------------------------------------------------
@ -99,7 +104,7 @@ namespace netlist { namespace factory
private:
setup_t &m_setup;
};
};
// -----------------------------------------------------------------------------
// factory_creator_ptr_t
@ -119,18 +124,6 @@ namespace netlist { namespace factory
// factory_lib_entry_t: factory class to wrap macro based chips/elements
// -----------------------------------------------------------------------------
class NETLIB_NAME(wrapper) : public device_t
{
public:
NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name)
{
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
};
class library_element_t : public element_t
{
public:
@ -146,6 +139,11 @@ namespace netlist { namespace factory
private:
};
} }
}
namespace devices {
void initialize_factory(factory::list_t &factory);
}
}
#endif /* NLFACTORY_H_ */

View File

@ -15,6 +15,7 @@
#include <mutex>
#include "nl_config.h"
#include "nl_types.h"
#include "plib/plists.h"
#include "plib/pchrono.h"
#include "plib/ptypes.h"
@ -26,7 +27,6 @@
namespace netlist
{
//FIXME: move to an appropriate place
template<bool enabled_ = true>
class pspin_mutex

View File

@ -8,7 +8,6 @@
#include "nl_parser.h"
#include "nl_factory.h"
#include "nl_errstr.h"
#include "devices/nld_truthtable.h"
namespace netlist
{
@ -187,7 +186,7 @@ void parser_t::net_truthtable_start(const pstring &nlname)
require_token(token, m_tok_TRUTHTABLE_END);
require_token(m_tok_param_left);
require_token(m_tok_param_right);
netlist::devices::tt_factory_create(m_setup, desc, nlname);
m_setup.tt_factory_create(desc, nlname);
return;
}
}

View File

@ -11,12 +11,11 @@
#include "nl_setup.h"
#include "nl_parser.h"
#include "nl_factory.h"
#include "devices/net_lib.h"
#include "devices/nld_truthtable.h"
#include "devices/nlid_system.h"
#include "devices/nlid_proxy.h"
#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"
#include "devices/nlid_truthtable.h"
// ----------------------------------------------------------------------------------------
// setup_t
@ -30,7 +29,7 @@ setup_t::setup_t(netlist_t &netlist)
, m_proxy_cnt(0)
, m_frontier_cnt(0)
{
initialize_factory(m_factory);
devices::initialize_factory(m_factory);
}
setup_t::~setup_t()
@ -137,11 +136,11 @@ pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
{
switch (in.type())
{
case terminal_t::TERMINAL:
case detail::terminal_type::TERMINAL:
return pstring("TERMINAL");
case terminal_t::INPUT:
case detail::terminal_type::INPUT:
return pstring("INPUT");
case terminal_t::OUTPUT:
case detail::terminal_type::OUTPUT:
return pstring("OUTPUT");
}
// FIXME: noreturn
@ -336,12 +335,12 @@ detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool
}
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in,
detail::core_terminal_t::type_t atype, bool required)
detail::terminal_type atype, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
auto ret = m_terminals.find(tname);
/* look for default */
if (ret == m_terminals.end() && atype == detail::core_terminal_t::OUTPUT)
if (ret == m_terminals.end() && atype == detail::terminal_type::OUTPUT)
{
/* look for ".Q" std output */
ret = m_terminals.find(tname + ".Q");
@ -603,7 +602,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
{
for (auto & t : t1.net().m_core_terms)
{
if (t->is_type(detail::core_terminal_t::TERMINAL))
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t2, *t);
if (ret)
break;
@ -618,7 +617,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
{
for (auto & t : t2.net().m_core_terms)
{
if (t->is_type(detail::core_terminal_t::TERMINAL))
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t1, *t);
if (ret)
break;
@ -637,39 +636,39 @@ bool setup_t::connect(detail::core_terminal_t &t1_in, detail::core_terminal_t &t
detail::core_terminal_t &t2 = resolve_proxy(t2_in);
bool ret = true;
if (t1.is_type(detail::core_terminal_t::OUTPUT) && t2.is_type(detail::core_terminal_t::INPUT))
if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::INPUT))
{
if (t2.has_net() && t2.net().isRailNet())
log().fatal(MF_1_INPUT_1_ALREADY_CONNECTED, t2.name());
connect_input_output(t2, t1);
}
else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::OUTPUT))
else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::OUTPUT))
{
if (t1.has_net() && t1.net().isRailNet())
log().fatal(MF_1_INPUT_1_ALREADY_CONNECTED, t1.name());
connect_input_output(t1, t2);
}
else if (t1.is_type(detail::core_terminal_t::OUTPUT) && t2.is_type(detail::core_terminal_t::TERMINAL))
else if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminal_output(dynamic_cast<terminal_t &>(t2), t1);
}
else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::OUTPUT))
else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::OUTPUT))
{
connect_terminal_output(dynamic_cast<terminal_t &>(t1), t2);
}
else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::TERMINAL))
else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminal_input(dynamic_cast<terminal_t &>(t2), t1);
}
else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::INPUT))
else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::INPUT))
{
connect_terminal_input(dynamic_cast<terminal_t &>(t1), t2);
}
else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::TERMINAL))
else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminals(dynamic_cast<terminal_t &>(t1), dynamic_cast<terminal_t &>(t2));
}
else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::INPUT))
else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::INPUT))
{
ret = connect_input_input(t1, t2);
}
@ -782,7 +781,7 @@ const plib::plog_base<NL_DEBUG> &setup_t::log() const
// Model
// ----------------------------------------------------------------------------------------
static pstring model_string(model_map_t &map)
static pstring model_string(detail::model_map_t &map)
{
pstring ret = map["COREMODEL"] + "(";
for (auto & i : map)
@ -791,7 +790,7 @@ static pstring model_string(model_map_t &map)
return ret + ")";
}
void setup_t::model_parse(const pstring &model_in, model_map_t &map)
void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
{
pstring model = model_in;
pstring::iterator pos(nullptr);
@ -837,7 +836,7 @@ void setup_t::model_parse(const pstring &model_in, model_map_t &map)
}
}
const pstring setup_t::model_value_str(model_map_t &map, const pstring &entity)
const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
{
pstring ret;
@ -852,7 +851,7 @@ const pstring setup_t::model_value_str(model_map_t &map, const pstring &entity)
return ret;
}
nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
{
pstring tmp = model_value_str(map, entity);
@ -899,7 +898,7 @@ plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create
const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
{
model_map_t map;
detail::model_map_t map;
model_parse(model, map);
if (model_value_str(map, "TYPE") == "TTL")

View File

@ -8,11 +8,18 @@
#ifndef NLSETUP_H_
#define NLSETUP_H_
#include "nl_base.h"
#include "nl_factory.h"
#include "plib/pstring.h"
#include "plib/putil.h"
#include "plib/pstream.h"
#include "plib/pparser.h"
#include "nl_factory.h"
#include "nl_config.h"
#include "nl_types.h"
#include <stack>
#include <vector>
#include <memory>
//============================================================
// MACROS / inline netlist definitions
@ -100,12 +107,29 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
desc.family = x;
#define TRUTHTABLE_END() \
netlist::devices::tt_factory_create(setup, desc, __FILE__); \
setup.tt_factory_create(desc, __FILE__); \
}
namespace netlist
{
namespace detail {
class core_terminal_t;
class net_t;
}
namespace devices {
class nld_base_proxy;
}
class core_device_t;
class param_t;
class setup_t;
class netlist_t;
class logic_family_desc_t;
class terminal_t;
// -----------------------------------------------------------------------------
// truthtable desc
// -----------------------------------------------------------------------------
@ -252,10 +276,10 @@ namespace netlist
/* model / family related */
const pstring model_value_str(model_map_t &map, const pstring &entity);
nl_double model_value(model_map_t &map, const pstring &entity);
const pstring model_value_str(detail::model_map_t &map, const pstring &entity);
double model_value(detail::model_map_t &map, const pstring &entity);
void model_parse(const pstring &model, model_map_t &map);
void model_parse(const pstring &model, detail::model_map_t &map);
const logic_family_desc_t *family_from_model(const pstring &model);
@ -276,7 +300,7 @@ namespace netlist
std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
/* needed by proxy */
detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::core_terminal_t::type_t atype, bool required = true);
detail::core_terminal_t *find_terminal(const pstring &outname_in, const detail::terminal_type atype, bool required = true);
private:

View File

@ -10,6 +10,7 @@
#include <cstdint>
#include "nl_config.h"
#include "plib/ptypes.h"
#include "plib/pstate.h"
//============================================================

View File

@ -0,0 +1,54 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*!
*
* \file nl_types.h
*
*/
#ifndef NLTYPES_H_
#define NLTYPES_H_
#include <cstdint>
#include <unordered_map>
#include "nl_config.h"
#include "plib/pchrono.h"
#include "plib/pstring.h"
namespace netlist
{
//============================================================
// Performance tracking
//============================================================
#if NL_KEEP_STATISTICS
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, true>;
using nperfcount_t = plib::chrono::counter<true>;
#else
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
using nperfcount_t = plib::chrono::counter<false>;
#endif
//============================================================
// Types needed by various includes
//============================================================
namespace detail {
/*! Enum specifying the type of object */
enum terminal_type {
TERMINAL = 0, /*!< object is an analog terminal */
INPUT = 1, /*!< object is an input */
OUTPUT = 2, /*!< object is an output */
};
/*! Type of the model map used.
* This is used to hold all #Models in an unordered map
*/
using model_map_t = std::unordered_map<pstring, pstring>;
}
}
#endif /* NLTYPES_H_ */

View File

@ -13,6 +13,7 @@
#include "nl_parser.h"
#include "devices/net_lib.h"
#include "tools/nl_convert.h"
#include "solver/nld_solver.h"
class tool_options_t : public plib::options
{

View File

@ -20,10 +20,10 @@ struct mat_cr_t
typedef C index_type;
typedef T value_type;
C RESTRICT diag[N]; // diagonal index pointer n
C RESTRICT ia[N+1]; // row index pointer n + 1
C RESTRICT ja[N*N]; // column index array nz_num, initially (n * n)
T RESTRICT A[N*N]; // Matrix elements nz_num, initially (n * n)
C diag[N]; // diagonal index pointer n
C ia[N+1]; // row index pointer n + 1
C ja[N*N]; // column index array nz_num, initially (n * n)
T A[N*N]; // Matrix elements nz_num, initially (n * n)
std::size_t size;
std::size_t nz_num;

View File

@ -123,7 +123,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
switch (p->type())
{
case terminal_t::TERMINAL:
case detail::terminal_type::TERMINAL:
if (p->device().is_timestep())
if (!plib::container::contains(m_step_devices, &p->device()))
m_step_devices.push_back(&p->device());
@ -136,7 +136,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
}
log().debug("Added terminal {1}\n", p->name());
break;
case terminal_t::INPUT:
case detail::terminal_type::INPUT:
{
proxied_analog_output_t *net_proxy_output = nullptr;
for (auto & input : m_inps)
@ -160,7 +160,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
log().debug("Added input\n");
}
break;
case terminal_t::OUTPUT:
case detail::terminal_type::OUTPUT:
log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
p->name());
break;

View File

@ -280,9 +280,9 @@ void matrix_solver_direct_t<m_N, storage_N>::LE_solve()
const nl_double * RESTRICT pi = &A(i,i+1);
nl_double * RESTRICT pj = &A(j,i+1);
#if 1
vec_add_mult_scalar(kN-i,pi,f1,pj);
vec_add_mult_scalar_p(kN-i,pi,f1,pj);
#else
vec_add_mult_scalar(kN-i-1,pj,f1,pi);
vec_add_mult_scalar_p(kN-i-1,pj,f1,pi);
//for (unsigned k = i+1; k < kN; k++)
// pj[k] = pj[k] + pi[k] * f1;
//for (unsigned k = i+1; k < kN; k++)

View File

@ -319,7 +319,7 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
m_A[mat.diag[k]] += gtot_t;
}
#endif
mat.ia[iN] = mat.nz_num;
mat.ia[iN] = static_cast<mattype>(mat.nz_num);
/* now solve it */

View File

@ -166,7 +166,7 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool ne
mat.A[pi] -= go[i];
}
}
mat.ia[iN] = mat.nz_num;
mat.ia[iN] = static_cast<mattype>(mat.nz_num);
const nl_double accuracy = this->m_params.m_accuracy;

View File

@ -39,6 +39,8 @@
#include "omp.h"
#endif
#include "nl_factory.h"
#include "nld_solver.h"
#include "nld_matrix_solver.h"
@ -215,7 +217,7 @@ struct net_splitter
groups.back().push_back(n);
for (auto &p : n->m_core_terms)
{
if (p->is_type(terminal_t::TERMINAL))
if (p->is_type(detail::terminal_type::TERMINAL))
{
terminal_t *pt = static_cast<terminal_t *>(p);
analog_net_t *other_net = &pt->m_otherterm->net();

View File

@ -10,7 +10,6 @@
#include <map>
#include "nl_setup.h"
#include "nl_base.h"
#include "plib/pstream.h"
#include "solver/nld_matrix_solver.h"
@ -18,17 +17,6 @@
//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
#define ATTR_ALIGNED(N) ATTR_ALIGN
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
#ifndef NL_AUTO_DEVICES
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#endif
// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------

2
src/lib/netlist/solver/vector_base.h Normal file → Executable file
View File

@ -86,7 +86,7 @@ inline static void vec_add_mult_scalar (const std::size_t n, const T (& RESTRICT
}
template<typename T>
inline static void vec_add_mult_scalar (const std::size_t & n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
inline static void vec_add_mult_scalar_p(const std::size_t & n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
{
for ( std::size_t i = 0; i < n; i++ )
result[i] += scalar * v[i];

View File

@ -1,4 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Andrew Gardner, Couriersud
#include "netlist/nl_setup.h"
NETLIST_EXTERNAL(kidniki)

View File

@ -1,4 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
#include "netlist/nl_setup.h"
NETLIST_EXTERNAL(hazelvid)

View File

@ -7,13 +7,13 @@
***************************************************************************/
#include "netlist/devices/net_lib.h"
#ifndef __PLIB_PREPROCESSOR__
#define NL_PROHIBIT_BASEH_INCLUDE 1
#include "netlist/devices/net_lib.h"
#endif
#define FAST_CLOCK (1)
#ifndef __PLIB_PREPROCESSOR__
#endif
NETLIST_START(pong_fast)
SOLVER(Solver, 48000)

View File

@ -1,4 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
#include "netlist/nl_setup.h"
NETLIST_EXTERNAL(stuntcyc)