diff options
author | balr0g <balrog032@gmail.com> | 2016-06-07 15:15:37 -0400 |
---|---|---|
committer | couriersud <couriersud@arcor.de> | 2016-06-07 21:40:30 +0200 |
commit | b27790890530b658e178846e7da01045185f0fce (patch) | |
tree | 95c027c901b343de6600a65d8d8f1beda51cbcdf /src/lib/netlist/devices/nlid_system.h | |
parent | 9137ace16ae5bed3f7164409a8622f61a9db2b80 (diff) |
- Minor cosmetic refactoring. Added a "uninitialised array" template to
allow in-place creation (for increased locality) of netlist classes.
Main use is in truthtable class.
- Remove PLIB_NAMESPACE macros.
- Remove namespace macros. Use explicit namespace declarations.
- Moved device definitions into cpp files.
- Moved more device definitions into cpp files.
- New prefix "nlid" for include files flags purely internal include
files not to be leaked into userland.
- Fix factory code.
Diffstat (limited to 'src/lib/netlist/devices/nlid_system.h')
-rw-r--r-- | src/lib/netlist/devices/nlid_system.h | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h new file mode 100644 index 00000000000..18a1a926fef --- /dev/null +++ b/src/lib/netlist/devices/nlid_system.h @@ -0,0 +1,591 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nlid_system.h + * + * netlist devices defined in the core + * + * This file contains internal headers + */ + +#ifndef NLID_SYSTEM_H_ +#define NLID_SYSTEM_H_ + +#include "nl_setup.h" +#include "nl_base.h" +#include "nl_factory.h" +#include "analog/nld_twoterm.h" + +namespace netlist +{ + namespace devices + { + + // ----------------------------------------------------------------------------- + // netlistparams + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(netlistparams) + { + NETLIB_CONSTRUCTOR(netlistparams) + , m_use_deactivate(*this, "USE_DEACTIVATE", 0) + { + } + NETLIB_UPDATEI() { } + //NETLIB_RESETI() { } + //NETLIB_UPDATE_PARAMI() { } + public: + param_logic_t m_use_deactivate; + }; + + // ----------------------------------------------------------------------------- + // mainclock + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(mainclock) + { + NETLIB_CONSTRUCTOR(mainclock) + , m_freq(*this, "FREQ", 7159000.0 * 5) + { + enregister("Q", m_Q); + + m_inc = netlist_time::from_hz(m_freq.Value()*2); + } + + NETLIB_RESETI() + { + m_Q.net().set_time(netlist_time::zero); + } + + NETLIB_UPDATE_PARAMI() + { + m_inc = netlist_time::from_hz(m_freq.Value()*2); + } + + NETLIB_UPDATEI() + { + logic_net_t &net = m_Q.net().as_logic(); + // this is only called during setup ... + net.toggle_new_Q(); + net.set_time(netlist().time() + m_inc); + } + + public: + logic_output_t m_Q; + + param_double_t m_freq; + netlist_time m_inc; + + ATTR_HOT inline static void mc_update(logic_net_t &net); + }; + + // ----------------------------------------------------------------------------- + // clock + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(clock) + { + NETLIB_CONSTRUCTOR(clock) + , m_freq(*this, "FREQ", 7159000.0 * 5.0) + + { + enregister("Q", m_Q); + enregister("FB", m_feedback); + + m_inc = netlist_time::from_hz(m_freq.Value()*2); + + connect_late(m_feedback, m_Q); + } + NETLIB_UPDATEI(); + //NETLIB_RESETI(); + NETLIB_UPDATE_PARAMI(); + + protected: + logic_input_t m_feedback; + logic_output_t m_Q; + + param_double_t m_freq; + netlist_time m_inc; + }; + + // ----------------------------------------------------------------------------- + // extclock + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(extclock) + { + NETLIB_CONSTRUCTOR(extclock) + , m_freq(*this, "FREQ", 7159000.0 * 5.0) + , m_pattern(*this, "PATTERN", "1,1") + , m_offset(*this, "OFFSET", 0.0) + { + enregister("Q", m_Q); + enregister("FB", m_feedback); + + m_inc[0] = netlist_time::from_hz(m_freq.Value()*2); + + connect_late(m_feedback, m_Q); + { + netlist_time base = netlist_time::from_hz(m_freq.Value()*2); + plib::pstring_vector_t pat(m_pattern.Value(),","); + m_off = netlist_time::from_double(m_offset.Value()); + + int pati[256]; + m_size = pat.size(); + int total = 0; + for (int i=0; i<m_size; i++) + { + pati[i] = pat[i].as_long(); + total += pati[i]; + } + netlist_time ttotal = netlist_time::zero; + for (int i=0; i<m_size - 1; i++) + { + m_inc[i] = base * pati[i]; + ttotal += m_inc[i]; + } + m_inc[m_size - 1] = base * total - ttotal; + } + save(NLNAME(m_cnt)); + save(NLNAME(m_off)); + } + NETLIB_UPDATEI(); + NETLIB_RESETI(); + //NETLIB_UPDATE_PARAMI(); + protected: + + param_double_t m_freq; + param_str_t m_pattern; + param_double_t m_offset; + + logic_input_t m_feedback; + logic_output_t m_Q; + UINT32 m_cnt; + UINT32 m_size; + netlist_time m_inc[32]; + netlist_time m_off; + }; + + // ----------------------------------------------------------------------------- + // Special support devices ... + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(logic_input) + { + NETLIB_CONSTRUCTOR(logic_input) + , m_IN(*this, "IN", 0) + /* make sure we get the family first */ + , m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)") + { + set_logic_family(netlist().setup().family_from_model(m_FAMILY.Value())); + + enregister("Q", m_Q); + } + NETLIB_UPDATE_AFTER_PARAM_CHANGE() + + NETLIB_UPDATEI(); + NETLIB_RESETI(); + NETLIB_UPDATE_PARAMI(); + + protected: + logic_output_t m_Q; + + param_logic_t m_IN; + param_model_t m_FAMILY; + }; + + NETLIB_OBJECT(analog_input) + { + NETLIB_CONSTRUCTOR(analog_input) + , m_IN(*this, "IN", 0.0) + { + enregister("Q", m_Q); + } + NETLIB_UPDATE_AFTER_PARAM_CHANGE() + + NETLIB_UPDATEI(); + NETLIB_RESETI(); + NETLIB_UPDATE_PARAMI(); + protected: + analog_output_t m_Q; + param_double_t m_IN; + }; + + // ----------------------------------------------------------------------------- + // nld_gnd + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(gnd) + { + NETLIB_CONSTRUCTOR(gnd) + { + enregister("Q", m_Q); + } + NETLIB_UPDATEI() + { + OUTANALOG(m_Q, 0.0); + } + NETLIB_RESETI() { } + protected: + analog_output_t m_Q; + }; + + // ----------------------------------------------------------------------------- + // nld_dummy_input + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT_DERIVED(dummy_input, base_dummy) + { + public: + NETLIB_CONSTRUCTOR_DERIVED(dummy_input, base_dummy) + { + enregister("I", m_I); + } + + protected: + + NETLIB_RESETI() { } + NETLIB_UPDATEI() { } + + private: + analog_input_t m_I; + + }; + + // ----------------------------------------------------------------------------- + // nld_frontier + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT_DERIVED(frontier, base_dummy) + { + public: + NETLIB_CONSTRUCTOR_DERIVED(frontier, base_dummy) + , m_RIN(netlist(), "m_RIN") + , m_ROUT(netlist(), "m_ROUT") + , m_p_RIN(*this, "RIN", 1.0e6) + , m_p_ROUT(*this, "ROUT", 50.0) + + { + enregister("_I", m_I); + enregister("I",m_RIN.m_P); + enregister("G",m_RIN.m_N); + connect_late(m_I, m_RIN.m_P); + + enregister("_Q", m_Q); + enregister("_OP",m_ROUT.m_P); + enregister("Q",m_ROUT.m_N); + connect_late(m_Q, m_ROUT.m_P); + } + + NETLIB_RESETI() + { + m_RIN.set(1.0 / m_p_RIN.Value(),0,0); + m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0); + } + + NETLIB_UPDATEI() + { + OUTANALOG(m_Q, INPANALOG(m_I)); + } + + private: + NETLIB_NAME(twoterm) m_RIN; + NETLIB_NAME(twoterm) m_ROUT; + analog_input_t m_I; + analog_output_t m_Q; + + param_double_t m_p_RIN; + param_double_t m_p_ROUT; + }; + + /* ----------------------------------------------------------------------------- + * nld_function + * + * FIXME: Currently a proof of concept to get congo bongo working + * ----------------------------------------------------------------------------- */ + + NETLIB_OBJECT(function) + { + NETLIB_CONSTRUCTOR(function) + , m_N(*this, "N", 2) + , m_func(*this, "FUNC", "") + { + enregister("Q", m_Q); + + for (int i=0; i < m_N; i++) + enregister(plib::pfmt("A{1}")(i), m_I[i]); + + plib::pstring_vector_t cmds(m_func.Value(), " "); + m_precompiled.clear(); + + for (std::size_t i=0; i < cmds.size(); i++) + { + pstring cmd = cmds[i]; + rpn_inst rc; + if (cmd == "+") + rc.m_cmd = ADD; + else if (cmd == "-") + rc.m_cmd = SUB; + else if (cmd == "*") + rc.m_cmd = MULT; + else if (cmd == "/") + rc.m_cmd = DIV; + else if (cmd.startsWith("A")) + { + rc.m_cmd = PUSH_INPUT; + rc.m_param = cmd.substr(1).as_long(); + } + else + { + bool err = false; + rc.m_cmd = PUSH_CONST; + rc.m_param = cmd.as_double(&err); + if (err) + netlist().log().fatal("nld_function: unknown/misformatted token <{1}> in <{2}>", cmd, m_func.Value()); + } + m_precompiled.push_back(rc); + } + + + } + + protected: + + NETLIB_RESETI(); + NETLIB_UPDATEI(); + + private: + + enum rpn_cmd + { + ADD, + MULT, + SUB, + DIV, + PUSH_CONST, + PUSH_INPUT + }; + + struct rpn_inst + { + rpn_inst() : m_cmd(ADD), m_param(0.0) { } + rpn_cmd m_cmd; + nl_double m_param; + }; + + param_int_t m_N; + param_str_t m_func; + analog_output_t m_Q; + analog_input_t m_I[10]; + + plib::pvector_t<rpn_inst> m_precompiled; + }; + + // ----------------------------------------------------------------------------- + // nld_res_sw + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(res_sw) + { + public: + NETLIB_CONSTRUCTOR(res_sw) + , m_R(*this, "R") + , m_RON(*this, "RON", 1.0) + , m_ROFF(*this, "ROFF", 1.0E20) + , m_last_state(0) + { + enregister("I", m_I); + + register_subalias("1", m_R.m_P); + register_subalias("2", m_R.m_N); + + save(NLNAME(m_last_state)); + } + + NETLIB_SUB(R) m_R; + logic_input_t m_I; + param_double_t m_RON; + param_double_t m_ROFF; + + NETLIB_RESETI() + { + m_last_state = 0; + m_R.set_R(m_ROFF.Value()); + } + //NETLIB_UPDATE_PARAMI(); + NETLIB_UPDATEI(); + + private: + + UINT8 m_last_state; + }; + + // ----------------------------------------------------------------------------- + // nld_base_proxy + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(base_proxy) + { + public: + nld_base_proxy(netlist_t &anetlist, const pstring &name, logic_t *inout_proxied, core_terminal_t *proxy_inout) + : device_t(anetlist, name) + { + m_logic_family = inout_proxied->logic_family(); + m_term_proxied = inout_proxied; + m_proxy_term = proxy_inout; + } + + virtual ~nld_base_proxy() {} + + logic_t &term_proxied() const { return *m_term_proxied; } + core_terminal_t &proxy_term() const { return *m_proxy_term; } + + protected: + + virtual const logic_family_desc_t &logic_family() const + { + return *m_logic_family; + } + + private: + const logic_family_desc_t *m_logic_family; + logic_t *m_term_proxied; + core_terminal_t *m_proxy_term; + }; + + // ----------------------------------------------------------------------------- + // nld_a_to_d_proxy + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_proxy) + { + public: + nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied) + : nld_base_proxy(anetlist, name, in_proxied, &m_I) + { + enregister("I", m_I); + enregister("Q", m_Q); + } + + virtual ~nld_a_to_d_proxy() {} + + analog_input_t m_I; + logic_output_t m_Q; + + protected: + + NETLIB_RESETI() { } + + NETLIB_UPDATEI() + { + if (m_I.Q_Analog() > logic_family().m_high_thresh_V) + OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1)); + else if (m_I.Q_Analog() < logic_family().m_low_thresh_V) + OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1)); + else + { + // do nothing + } + } + private: + }; + + // ----------------------------------------------------------------------------- + // nld_base_d_to_a_proxy + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy) + { + public: + virtual ~nld_base_d_to_a_proxy() {} + + virtual logic_input_t &in() { return m_I; } + + protected: + nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied, core_terminal_t &proxy_out) + : nld_base_proxy(anetlist, name, out_proxied, &proxy_out) + { + enregister("I", m_I); + } + + logic_input_t m_I; + + private: + }; + + NETLIB_OBJECT_DERIVED(d_to_a_proxy, base_d_to_a_proxy) + { + public: + nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied) + : nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P) + , m_RV(*this, "RV") + , m_last_state(-1) + , m_is_timestep(false) + { + //register_sub(m_RV); + enregister("1", m_RV.m_P); + enregister("2", m_RV.m_N); + + enregister("_Q", m_Q); + register_subalias("Q", m_RV.m_P); + + connect_late(m_RV.m_N, m_Q); + + save(NLNAME(m_last_state)); + } + + virtual ~nld_d_to_a_proxy() {} + + protected: + + NETLIB_RESETI(); + NETLIB_UPDATEI(); + + private: + analog_output_t m_Q; + NETLIB_SUB(twoterm) m_RV; + int m_last_state; + bool m_is_timestep; + }; + + + class factory_lib_entry_t : public base_factory_t + { + P_PREVENT_COPYING(factory_lib_entry_t) + public: + + ATTR_COLD factory_lib_entry_t(setup_t &setup, const pstring &name, const pstring &classname, + const pstring &def_param) + : base_factory_t(name, classname, def_param), m_setup(setup) { } + + class wrapper : public device_t + { + public: + wrapper(const pstring &devname, netlist_t &anetlist, const pstring &name) + : device_t(anetlist, name), m_devname(devname) + { + anetlist.setup().namespace_push(name); + anetlist.setup().include(m_devname); + anetlist.setup().namespace_pop(); + } + protected: + NETLIB_RESETI() { } + NETLIB_UPDATEI() { } + + pstring m_devname; + }; + + plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override + { + return plib::owned_ptr<device_t>::Create<wrapper>(this->name(), anetlist, name); + } + + private: + setup_t &m_setup; + }; + + + } //namespace devices +} // namespace netlist + +#endif /* NLD_SYSTEM_H_ */ |