diff options
Diffstat (limited to 'src/lib/netlist/devices')
124 files changed, 7183 insertions, 8488 deletions
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp index 4fe03f81534..e2f437aabca 100644 --- a/src/lib/netlist/devices/net_lib.cpp +++ b/src/lib/netlist/devices/net_lib.cpp @@ -1,172 +1,33 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/*************************************************************************** - netlib.c - - Discrete netlist implementation. - -****************************************************************************/ +// *************************************************************************** +// +// net_lib.cpp +// +// *************************************************************************** #include "net_lib.h" -#include "netlist/nl_factory.h" -#include "netlist/solver/nld_solver.h" - +#include "nl_factory.h" +#include "solver/nld_solver.h" -#define xstr(s) # s #define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip +#define LIB_DECL(decl) factory.add( decl () ); +#define LIB_ENTRY(nic) { NETLIB_DEVICE_DECL(nic); LIB_DECL(decl_ ## nic) } -#define LIB_DECL(nic, decl) factory.register_device( decl ( pstring(xstr(nic))) ); -#define LIB_ENTRY(nic) { NETLIB_DEVICE_DECL(nic); LIB_DECL(NETLIB_NAME(nic), decl_ ## nic) } - -namespace netlist -{ -namespace devices -{ +namespace netlist::devices { void initialize_factory(factory::list_t &factory) { - LIB_ENTRY(R) - LIB_ENTRY(POT) - LIB_ENTRY(POT2) - LIB_ENTRY(C) - LIB_ENTRY(L) - LIB_ENTRY(D) - LIB_ENTRY(VS) - LIB_ENTRY(CS) - LIB_ENTRY(VCVS) - LIB_ENTRY(VCCS) - LIB_ENTRY(CCCS) - LIB_ENTRY(LVCCS) - LIB_ENTRY(opamp) - LIB_ENTRY(dummy_input) - LIB_ENTRY(frontier) // not intended to be used directly - LIB_ENTRY(function) // only for macro devices - NO FEEDBACK loops - LIB_ENTRY(QBJT_EB) - LIB_ENTRY(QBJT_switch) - LIB_ENTRY(MOSFET) - LIB_ENTRY(logic_input_ttl) - LIB_ENTRY(logic_input) - LIB_ENTRY(analog_input) - LIB_ENTRY(log) - LIB_ENTRY(logD) - LIB_ENTRY(clock) - LIB_ENTRY(varclock) - LIB_ENTRY(extclock) - LIB_ENTRY(mainclock) - LIB_ENTRY(gnd) - LIB_ENTRY(netlistparams) - LIB_ENTRY(solver) - LIB_ENTRY(res_sw) - LIB_ENTRY(switch1) - LIB_ENTRY(switch2) - LIB_ENTRY(nicRSFF) - LIB_ENTRY(nicDelay) - LIB_ENTRY(2102A) - LIB_ENTRY(2102A_dip) - LIB_ENTRY(2716) - LIB_ENTRY(2716_dip) -#if !(USE_TRUTHTABLE_7448) - LIB_ENTRY(7448) - LIB_ENTRY(7448_dip) -#endif - LIB_ENTRY(7450) - LIB_ENTRY(7450_dip) - LIB_ENTRY(7473) - LIB_ENTRY(7473_dip) - LIB_ENTRY(7473A) - LIB_ENTRY(7473A_dip) - LIB_ENTRY(7474) - LIB_ENTRY(7474_dip) - LIB_ENTRY(7475) - LIB_ENTRY(7475_dip) - LIB_ENTRY(7477) - LIB_ENTRY(7477_dip) - LIB_ENTRY(7483) - LIB_ENTRY(7483_dip) - LIB_ENTRY(7485) - LIB_ENTRY(7485_dip) - LIB_ENTRY(7490) - LIB_ENTRY(7490_dip) - LIB_ENTRY(7493) - LIB_ENTRY(7493_dip) - LIB_ENTRY(7497) - LIB_ENTRY(7497_dip) -#if (!USE_TRUTHTABLE_74107) - LIB_ENTRY(74107) - LIB_ENTRY(74107_dip) -#endif - LIB_ENTRY(74107A) // FIXME: implement missing DIP - LIB_ENTRY(74123) - LIB_ENTRY(74123_dip) - LIB_ENTRY(74153) - LIB_ENTRY(74153_dip) - LIB_ENTRY(74161) - LIB_ENTRY(74161_dip) - LIB_ENTRY(74164) - LIB_ENTRY(74164_dip) - LIB_ENTRY(74165) - LIB_ENTRY(74165_dip) - LIB_ENTRY(74166) - LIB_ENTRY(74166_dip) - LIB_ENTRY(74174) - LIB_ENTRY(74175) - LIB_ENTRY(74192) - LIB_ENTRY(74193) - LIB_ENTRY(74194) - LIB_ENTRY(74365) - //ENTRY(74279, TTL_74279, "") // only dip available - LIB_ENTRY(SN74LS629) - LIB_ENTRY(82S16) - LIB_ENTRY(82S115) - LIB_ENTRY(82S123) - LIB_ENTRY(82S126) - LIB_ENTRY(9310) - LIB_ENTRY(9314) - LIB_ENTRY(9316) - LIB_ENTRY(9322) - LIB_ENTRY(9334) - LIB_ENTRY(AM2847) - // FIXME: duplicate? - LIB_ENTRY(CD4020_WI) - LIB_ENTRY(CD4020) - LIB_ENTRY(CD4066_GATE) - LIB_ENTRY(CD4316_GATE) - LIB_ENTRY(4538_dip) - LIB_ENTRY(schmitt_trigger) - /* entries with suffix WI are legacy only */ - //ENTRY(4066, CD_4066, "+A,B") - LIB_ENTRY(NE555) - LIB_ENTRY(NE555_dip) - LIB_ENTRY(MC1455P) - LIB_ENTRY(MC1455P_dip) - LIB_ENTRY(TMS4800) - LIB_ENTRY(TMS4800_dip) - LIB_ENTRY(r2r_dac) - LIB_ENTRY(tristate) - LIB_ENTRY(tristate3) - LIB_ENTRY(74174_dip) - LIB_ENTRY(74175_dip) - LIB_ENTRY(74192_dip) - LIB_ENTRY(74193_dip) - LIB_ENTRY(74194_dip) - LIB_ENTRY(74365_dip) - LIB_ENTRY(82S16_dip) - LIB_ENTRY(82S115_dip) - LIB_ENTRY(82S123_dip) - LIB_ENTRY(82S126_dip) - LIB_ENTRY(9602_dip) - LIB_ENTRY(9310_dip) - LIB_ENTRY(9314_dip) - LIB_ENTRY(9316_dip) - LIB_ENTRY(9322_dip) - LIB_ENTRY(9334_dip) - LIB_ENTRY(AM2847_dip) - LIB_ENTRY(SN74LS629_dip) - LIB_ENTRY(MM5837_dip) + // The following is from a script which automatically creates + // the entries. + // FIXME: the list should be either included or the whole + // initialize factory code should be created programmatically. + + #include "../generated/lib_entries.hxx" + } -} //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h index abf58ccee16..f3487fc2740 100644 --- a/src/lib/netlist/devices/net_lib.h +++ b/src/lib/netlist/devices/net_lib.h @@ -1,103 +1,35 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/*************************************************************************** - - net_lib.h - - Discrete netlist implementation. - -****************************************************************************/ #ifndef NET_LIB_H #define NET_LIB_H -#include "netlist/nl_setup.h" - -//#define NL_AUTO_DEVICES 1 - -#define SOLVER(name, freq) \ - NET_REGISTER_DEV(SOLVER, name) \ - PARAM(name.FREQ, freq) - -#ifdef NL_AUTO_DEVICES -#include "nld_devinc.h" - -#include "macro/nlm_cd4xxx.h" -#include "macro/nlm_ttl74xx.h" -#include "macro/nlm_opamp.h" -#include "macro/nlm_other.h" - -#include "nld_7448.h" - -#else - -#include "nld_system.h" +/// +/// \file net_lib.h +/// +/// This file is included by all netlist implementations. +/// -#include "nld_2102A.h" -#include "nld_2716.h" -#include "nld_4020.h" -#include "nld_4066.h" -#include "nld_74107.h" -#include "nld_74123.h" -#include "nld_74153.h" -#include "nld_74161.h" -#include "nld_74164.h" -#include "nld_74165.h" -#include "nld_74166.h" -#include "nld_74174.h" -#include "nld_74175.h" -#include "nld_74192.h" -#include "nld_74193.h" -#include "nld_74194.h" -#include "nld_74365.h" -#include "nld_7448.h" -#include "nld_7450.h" -#include "nld_7473.h" -#include "nld_7474.h" -#include "nld_7475.h" -#include "nld_7483.h" -#include "nld_7485.h" -#include "nld_7490.h" -#include "nld_7493.h" -#include "nld_7497.h" -#include "nld_74ls629.h" -#include "nld_82S115.h" -#include "nld_82S123.h" -#include "nld_82S126.h" -#include "nld_82S16.h" -#include "nld_9310.h" -#include "nld_9316.h" -#include "nld_9322.h" -#include "nld_tms4800.h" +#include "../nl_setup.h" -#include "nld_am2847.h" -#include "nld_dm9314.h" -#include "nld_dm9334.h" - -#include "nld_mm5837.h" -#include "nld_ne555.h" - -#include "nld_r2r_dac.h" - -#include "nld_schmitt.h" - -#include "nld_tristate.h" - -#include "nld_log.h" +#ifdef RES_R +#warning "Do not include `rescap.h` in a netlist environment" +#endif +#ifndef RES_R +#define RES_R(res) (res) +#define RES_K(res) ((res) * 1e3) +#define RES_M(res) ((res) * 1e6) +#define CAP_U(cap) ((cap) * 1e-6) +//#define CAP_U(cap) ((cap) * 1μ) +#define CAP_N(cap) ((cap) * 1e-9) +#define CAP_P(cap) ((cap) * 1e-12) +#define IND_U(ind) ((ind) * 1e-6) +#define IND_N(ind) ((ind) * 1e-9) +#define IND_P(ind) ((ind) * 1e-12) +#endif -#include "netlist/macro/nlm_cd4xxx.h" -#include "netlist/macro/nlm_opamp.h" -#include "netlist/macro/nlm_other.h" -#include "netlist/macro/nlm_ttl74xx.h" +#include "../generated/nld_devinc.h" -#include "netlist/analog/nld_bjt.h" -#include "netlist/analog/nld_fourterm.h" -#include "netlist/analog/nld_mosfet.h" -#include "netlist/analog/nld_opamps.h" -#include "netlist/analog/nld_switches.h" -#include "netlist/analog/nld_twoterm.h" +NETLIST_EXTERNAL(base_lib) -#include "nld_legacy.h" -#endif - -#endif +#endif // NET_LIB_H diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp deleted file mode 100644 index 54922ad71cf..00000000000 --- a/src/lib/netlist/devices/nld_2102A.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_2102A.cpp - * - */ - -#include "nld_2102A.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -#define ADDR2BYTE(a) ((a) >> 3) -#define ADDR2BIT(a) ((a) & 0x7) - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(2102A) - { - NETLIB_CONSTRUCTOR(2102A) - , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9" }}) - , m_CEQ(*this, "CEQ") - , m_RWQ(*this, "RWQ") - , m_DI(*this, "DI") - , m_DO(*this, "DO") - , m_ram(*this, "m_ram", 0) - , m_RAM(*this, "m_RAM", &m_ram[0]) - , m_power_pins(*this) - { - } - - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 10> m_A; - logic_input_t m_CEQ; - logic_input_t m_RWQ; - logic_input_t m_DI; - - logic_output_t m_DO; - - state_array<uint8_t, 128> m_ram; // 1024x1 bits - param_ptr_t m_RAM; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(2102A_dip, 2102A) - { - NETLIB_CONSTRUCTOR_DERIVED(2102A_dip, 2102A) - { - register_subalias("8", m_A[0]); - register_subalias("4", m_A[1]); - register_subalias("5", m_A[2]); - register_subalias("6", m_A[3]); - register_subalias("7", m_A[4]); - register_subalias("2", m_A[5]); - register_subalias("1", m_A[6]); - register_subalias("16", m_A[7]); - register_subalias("15", m_A[8]); - register_subalias("14", m_A[9]); - - register_subalias("13", m_CEQ); - register_subalias("3", m_RWQ); - - register_subalias("11", m_DI); - register_subalias("12", m_DO); - - register_subalias("10", "VCC"); - register_subalias("9", "GND"); - - } - }; - - NETLIB_UPDATE(2102A) - { - netlist_time max_delay = NLTIME_FROM_NS(350); - - if (!m_CEQ()) - { - unsigned a = 0; - for (std::size_t i=0; i<10; i++) - { - a |= (m_A[i]() << i); - } - const unsigned byte = ADDR2BYTE(a); - const unsigned bit = ADDR2BIT(a); - - if (!m_RWQ()) - { - m_ram[byte] &= ~(static_cast<uint8_t>(1) << bit); - m_ram[byte] |= (static_cast<uint8_t>(m_DI()) << bit); - } - - m_DO.push((m_ram[byte] >> bit) & 1, max_delay); - } - } - - NETLIB_RESET(2102A) - { - m_RAM.setTo(&m_ram[0]); - for (std::size_t i=0; i<128; i++) - m_ram[i] = 0; - } - - NETLIB_DEVICE_IMPL(2102A, "RAM_2102A", "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI,@VCC,@GND") - NETLIB_DEVICE_IMPL(2102A_dip,"RAM_2102A_DIP","") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_2102A.h b/src/lib/netlist/devices/nld_2102A.h deleted file mode 100644 index 9d2279445f1..00000000000 --- a/src/lib/netlist/devices/nld_2102A.h +++ /dev/null @@ -1,50 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_2102A.h - * - * 2102: 1024 x 1-bit Static RAM - * - * +--------------+ - * A6 |1 ++ 16| A7 - * A5 |2 15| A8 - * RWQ |3 14| A9 - * A1 |4 82S16 13| CEQ - * A2 |5 12| DO - * A3 |6 11| DI - * A4 |7 10| VCC - * A0 |8 9| GND - * +--------------+ - * - * - * Naming conventions follow Intel datasheet - * - */ - -#ifndef NLD_2102A_H_ -#define NLD_2102A_H_ - -#include "netlist/nl_setup.h" - -#define RAM_2102A(name, cCEQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cRWQ, cDI) \ - NET_REGISTER_DEV(RAM_2102A, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CEQ, cCEQ) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) \ - NET_CONNECT(name, A7, cA7) \ - NET_CONNECT(name, A8, cA8) \ - NET_CONNECT(name, A9, cA9) \ - NET_CONNECT(name, RWQ, cRWQ) \ - NET_CONNECT(name, DI, cDI) - -#define RAM_2102A_DIP(name) \ - NET_REGISTER_DEV(RAM_2102A_DIP, name) - -#endif /* NLD_2102A_H_ */ diff --git a/src/lib/netlist/devices/nld_2102a.cpp b/src/lib/netlist/devices/nld_2102a.cpp new file mode 100644 index 00000000000..dd03560a32d --- /dev/null +++ b/src/lib/netlist/devices/nld_2102a.cpp @@ -0,0 +1,91 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/* + * nld_2102A.cpp + * + * 2102: 1024 x 1-bit Static RAM + * + * +--------------+ + * A6 |1 ++ 16| A7 + * A5 |2 15| A8 + * RWQ |3 14| A9 + * A1 |4 82S16 13| CEQ + * A2 |5 12| DO + * A3 |6 11| DI + * A4 |7 10| VCC + * A0 |8 9| GND + * +--------------+ + * + * + * Naming conventions follow Intel datasheet + * + */ + +#include "nl_base.h" + +#define ADDR2BYTE(a) ((a) >> 3) +#define ADDR2BIT(a) ((a) & 0x7) + +namespace netlist::devices { + + NETLIB_OBJECT(2102A) + { + NETLIB_CONSTRUCTOR(2102A) + , m_A(*this, {"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9" }, NETLIB_DELEGATE(inputs)) + , m_CEQ(*this, "CEQ", NETLIB_DELEGATE(inputs)) + , m_RWQ(*this, "RWQ", NETLIB_DELEGATE(inputs)) + , m_DI(*this, "DI", NETLIB_DELEGATE(inputs)) + , m_DO(*this, "DO") + , m_ram(*this, "m_ram", 0) + , m_RAM(*this, "m_RAM", &m_ram[0]) + , m_power_pins(*this) + { + } + + NETLIB_RESETI() + { + m_RAM.set(&m_ram[0]); + for (std::size_t i=0; i<128; i++) + m_ram[i] = 0; + } + + NETLIB_HANDLERI(inputs) + { + netlist_time max_delay = NLTIME_FROM_NS(350); + + if (!m_CEQ()) + { + unsigned a = 0; + for (std::size_t i=0; i<10; i++) + { + a |= (m_A[i]() << i); + } + const unsigned byte = ADDR2BYTE(a); + const unsigned bit = ADDR2BIT(a); + + if (!m_RWQ()) + { + m_ram[byte] &= ~(static_cast<uint8_t>(1) << bit); + m_ram[byte] |= (static_cast<uint8_t>(m_DI()) << bit); + } + + m_DO.push((m_ram[byte] >> bit) & 1, max_delay); + } + } + + private: + object_array_t<logic_input_t, 10> m_A; + logic_input_t m_CEQ; + logic_input_t m_RWQ; + logic_input_t m_DI; + + logic_output_t m_DO; + + state_container<std::array<uint8_t, 128>> m_ram; // 1024x1 bits + param_ptr_t m_RAM; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(2102A, "RAM_2102A", "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_2716.cpp b/src/lib/netlist/devices/nld_2716.cpp deleted file mode 100644 index 02fbec5b4d0..00000000000 --- a/src/lib/netlist/devices/nld_2716.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_2716.cpp - * - */ - -#include "nld_2716.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(2716) - { - NETLIB_CONSTRUCTOR(2716) - , m_A(*this, {{ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10" }}) - , m_GQ(*this, "GQ") - , m_EPQ(*this, "EPQ") - , m_D(*this, {{ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7" }}) - , m_last_EPQ(*this, "m_last_EPQ", 1) - , m_ROM(*this, "ROM") - , m_power_pins(*this) - { - } - - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 11> m_A; - logic_input_t m_GQ; - logic_input_t m_EPQ; - object_array_t<logic_output_t, 8> m_D; - - state_var<unsigned> m_last_EPQ; - - param_rom_t<uint8_t, 11, 8> m_ROM; // 16 Kbits, used as 2 Kbit x 8 - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(2716_dip, 2716) - { - NETLIB_CONSTRUCTOR_DERIVED(2716_dip, 2716) - { - register_subalias("8", m_A[0]); - register_subalias("7", m_A[1]); - register_subalias("6", m_A[2]); - register_subalias("5", m_A[3]); - register_subalias("4", m_A[4]); - register_subalias("3", m_A[5]); - register_subalias("2", m_A[6]); - register_subalias("1", m_A[7]); - register_subalias("23", m_A[8]); - register_subalias("22", m_A[9]); - register_subalias("19", m_A[10]); - - register_subalias("20", m_GQ); - register_subalias("18", m_EPQ); - - register_subalias("9", m_D[0]); - register_subalias("10", m_D[1]); - register_subalias("11", m_D[2]); - register_subalias("13", m_D[3]); - register_subalias("14", m_D[4]); - register_subalias("15", m_D[5]); - register_subalias("16", m_D[6]); - register_subalias("17", m_D[7]); - - register_subalias("12", "GND"); - register_subalias("24", "VCC"); - } - }; - - // FIXME: timing! - NETLIB_UPDATE(2716) - { - unsigned d = 0xff; - - netlist_time delay = NLTIME_FROM_NS(450); - if (!m_GQ() && !m_EPQ()) - { - unsigned a = 0; - for (std::size_t i=0; i<11; i++) - a |= (m_A[i]() << i); - - d = m_ROM[a]; - - if (m_last_EPQ) - delay = NLTIME_FROM_NS(120); - } - - m_last_EPQ = m_EPQ(); - - // FIXME: Outputs are tristate. This needs to be properly implemented - for (std::size_t i=0; i<8; i++) - m_D[i].push((d >> i) & 1, delay); - } - - NETLIB_DEVICE_IMPL(2716, "EPROM_2716", "+GQ,+EPQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10,@VCC,@GND") - NETLIB_DEVICE_IMPL(2716_dip, "EPROM_2716_DIP", "") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_2716.h b/src/lib/netlist/devices/nld_2716.h deleted file mode 100644 index c5e039e1421..00000000000 --- a/src/lib/netlist/devices/nld_2716.h +++ /dev/null @@ -1,54 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S126.h - * - * 2716: 16 Kbit (2Kb x 8) UV EPROM - * - * +----------------+ - * A7 |1 ++ 24| VCC - * A6 |2 23| A8 - * A5 |3 22| A9 - * A4 |4 2716 21| VPP - * A3 |5 20| GQ - * A2 |6 19| A10 - * A1 |7 18| EPQ - * A0 |8 17| D7 - * D0 |9 16| D6 - * D1 |10 15| D5 - * D2 |11 14| D4 - * VSS |12 13| D3 - * +----------------+ - * - * - * Naming conventions follow STMicro datasheet - * - */ - -#ifndef NLD_2716_H_ -#define NLD_2716_H_ - -#include "netlist/nl_setup.h" - -#define EPROM_2716(name, cGQ, cEPQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cA10) \ - NET_REGISTER_DEV(EPROM_2716, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, GQ, cGQ) \ - NET_CONNECT(name, EPQ, cEPQ) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) \ - NET_CONNECT(name, A7, cA7) \ - NET_CONNECT(name, A8, cA8) \ - NET_CONNECT(name, A9, cA9) \ - NET_CONNECT(name, A10, cA10) - -#define EPROM_2716_DIP(name) \ - NET_REGISTER_DEV(EPROM_2716_DIP, name) - -#endif /* NLD_2716_H_ */ diff --git a/src/lib/netlist/devices/nld_4006.cpp b/src/lib/netlist/devices/nld_4006.cpp new file mode 100644 index 00000000000..94a3685032c --- /dev/null +++ b/src/lib/netlist/devices/nld_4006.cpp @@ -0,0 +1,114 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_4006.cpp + * + * CD4006: CMOS 18-Stage Static Register + * + * Description + * + * CD4006BMS types are composed of 4 separate shift register sections: two + * sections of four stages and two sections of five stages with an output tap + * at the fourth stage. Each section has an independent single-rail data path. + * + * A common clock signal is used for all stages. Data are shifted to the next + * stages on negative-going transitions of the clock. Through appropriate + * connections of inputs and outputs, multiple register sections of 4, 5, 8, + * and 9 stages or single register sections of 10, 12, 13, 14, 16, 17 and 18 + * stages can be implemented using one CD4006BMS package. Longer shift register + * sections can be assembled by using more than one CD4006BMS. + * + * To facilitate cascading stages when clock rise and fall times are slow, + * an optional output (D1 + 4’) that is delayed one-half clockcycle, is + * provided. + * + * +--------------+ + * D1 |1 ++ 14| VDD + * D1+4' |2 13| D1+4 + * CLOCK |3 12| D2+5 + * D2 |4 4006 11| D2+4 + * D3 |5 10| D3+4 + * D4 |6 9| D4+5 + * VSS |7 8| D4+4 + * +--------------+ + * + * + * Naming conventions follow SYC datasheet + * + * FIXME: Timing depends on VDD-VSS - partially done + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + // FIXME: optimize clock input + + NETLIB_OBJECT(CD4006) + { + NETLIB_CONSTRUCTOR_MODEL(CD4006, "CD4XXX") + , m_CLOCK(*this, "CLOCK", NETLIB_DELEGATE(inputs)) + , m_I(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(inputs)) + , m_Q(*this, {"D1P4", "D1P4S", "D2P4", "D2P5", "D3P4", "D4P4", "D4P5"}) + , m_d(*this, "m_d", 0) + , m_last_clock(*this, "m_last_clock", 0) + , m_tp(*this, "m_tp", netlist_time::from_nsec(200)) + , m_supply(*this, NETLIB_DELEGATE(vdd_vss)) + { + } + + private: + NETLIB_HANDLERI(inputs) + { + if (m_last_clock && !m_CLOCK()) + { + m_d[0] >>= 1; + m_d[1] >>= 1; + m_d[2] >>= 1; + m_d[3] >>= 1; + // falling, output all but D1P4S + m_Q[0].push(m_d[0] & 1, m_tp); + m_Q[2].push((m_d[1] >> 1) & 1, m_tp); // D2 + 4 + m_Q[3].push( m_d[1] & 1, m_tp); // D2 + 5 + m_Q[4].push( m_d[2] & 1, m_tp); // D3 + 4 + m_Q[5].push((m_d[3] >> 1) & 1, m_tp); // D4 + 4 + m_Q[6].push( m_d[3] & 1, m_tp); // D5 + 5 + m_last_clock = m_CLOCK(); + } + else if (!m_last_clock && m_CLOCK()) + { + // rising, output D1P4S + m_Q[1].push(m_d[0] & 1, m_tp); + m_last_clock = m_CLOCK(); + } + else + { + m_d[0] = static_cast<uint8_t>((m_d[0] & 0x0f) | (m_I[0]() << 4)); + m_d[1] = static_cast<uint8_t>((m_d[1] & 0x1f) | (m_I[1]() << 5)); + m_d[2] = static_cast<uint8_t>((m_d[2] & 0x0f) | (m_I[2]() << 4)); + m_d[3] = static_cast<uint8_t>((m_d[3] & 0x1f) | (m_I[3]() << 5)); + } + } + + NETLIB_HANDLERI(vdd_vss) + { + auto d = m_supply.VCC()() - m_supply.GND()(); + if (d > 0.1) // avoid unrealistic values + { + m_tp = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(923.0 / d + 13.0)); // calculated from datasheet + } + } + + logic_input_t m_CLOCK; + object_array_t<logic_input_t, 4> m_I; + object_array_t<logic_output_t, 7> m_Q; + state_container<std::array<uint8_t, 4>> m_d; + state_var<netlist_sig_t> m_last_clock; + state_var<netlist_time> m_tp; // propagation time + nld_power_pins m_supply; + }; + + NETLIB_DEVICE_IMPL(CD4006, "CD4006", "+CLOCK,+D1,+D2,+D3,+D4,+D1P4,+D1P4S,+D2P4,+D2P5,+D3P4,+D4P4,+D4P5,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4013.cpp b/src/lib/netlist/devices/nld_4013.cpp new file mode 100644 index 00000000000..5fa3aa25586 --- /dev/null +++ b/src/lib/netlist/devices/nld_4013.cpp @@ -0,0 +1,122 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_4013.cpp + * + * CD4013: Dual Positive-Edge-Triggered D Flip-Flops + * with Set, Reset and Complementary Outputs + * + * +--------------+ + * Q1 |1 ++ 14| VDD + * Q1Q |2 13| Q2 + * CLOCK1 |3 12| Q2Q + * RESET1 |4 4013 11| CLOCK2 + * DATA1 |5 10| RESET2 + * SET1 |6 9| DATA2 + * VSS |7 8| SET2 + * +--------------+ + * + * +-----+-----+-----+---++---+-----+ + * | SET | RES | CLK | D || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 1 | 0 | X | X || 1 | 0 | + * | 0 | 1 | X | X || 0 | 1 | + * | 1 | 1 | X | X || 1 | 1 | (*) + * | 0 | 0 | R | 1 || 1 | 0 | + * | 0 | 0 | R | 0 || 0 | 1 | + * | 0 | 0 | 0 | X || Q0| Q0Q | + * +-----+-----+-----+---++---+-----+ + * + * (*) This configuration is not stable, i.e. it will not persist + * when either the preset and or clear inputs return to their inactive (high) level + * + * Q0 The output logic level of Q before the indicated input conditions were established + * + * R: 0 -. 1 + * + * Naming conventions follow National Semiconductor datasheet + * + * FIXME: Check that (*) is emulated properly + */ + +#include "nl_base.h" +#include "nl_factory.h" + +namespace netlist::devices { + + NETLIB_OBJECT(CD4013) + { + NETLIB_CONSTRUCTOR_MODEL(CD4013, "CD4XXX") + , m_D(*this, "DATA", NETLIB_DELEGATE(inputs)) + , m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs)) + , m_SET(*this, "SET", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLOCK", NETLIB_DELEGATE(clk)) + , m_Q(*this, "Q") + , m_QQ(*this, "QQ") + , m_nextD(*this, "m_nextD", 0) + , m_power_pins(*this) + { + } + + private: + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_D.set_state(logic_t::STATE_INP_ACTIVE); + m_nextD = 0; + } + + NETLIB_HANDLERI(inputs) + { + const auto set(m_SET()); + const auto reset(m_RESET()); + if ((set ^ 1) & (reset ^ 1)) + { + m_D.activate(); + m_nextD = m_D(); + m_CLK.activate_lh(); + } + else + { + set_reset(set, reset); + m_CLK.inactivate(); + m_D.inactivate(); + } + } + + NETLIB_HANDLERI(clk) + { + set_output(m_nextD); + m_CLK.inactivate(); + } + + logic_input_t m_D; + logic_input_t m_RESET; + logic_input_t m_SET; + logic_input_t m_CLK; + logic_output_t m_Q; + logic_output_t m_QQ; + + state_var<netlist_sig_t> m_nextD; + + nld_power_pins m_power_pins; + + void set_output(const netlist_sig_t stateQ) + { + static constexpr const auto delay = NLTIME_FROM_NS(150); + m_Q.push(stateQ, delay); + m_QQ.push(!stateQ, delay); + } + + void set_reset(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) + { + // Q: 150 ns, QQ: 200 ns + static constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(150), NLTIME_FROM_NS(200) }; + m_Q.push(stateQ, delay[0]); + m_QQ.push(stateQQ, delay[1]); + } + }; + + NETLIB_DEVICE_IMPL(CD4013, "CD4013", "+CLOCK,+DATA,+RESET,+SET,@VDD,@VSS") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4017.cpp b/src/lib/netlist/devices/nld_4017.cpp new file mode 100644 index 00000000000..36162e764b5 --- /dev/null +++ b/src/lib/netlist/devices/nld_4017.cpp @@ -0,0 +1,113 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_4017.cpp + * + * CD4017: Decade Counter/Divider with 10 Decoded Outputs + * + * +--------------+ + * Q5 |1 ++ 16| VDD + * Q1 |2 15| RESET + * Q0 |3 14| CLOCK + * Q2 |4 4017 13| CLOCK ENABLE + * Q6 |5 12| CARRY OUT + * Q7 |6 11| Q9 + * Q3 |7 10| Q4 + * VSS |8 9| Q8 + * +--------------+ + * + * + * CD4022: Divide-by-8 Counter/Divider with 8 Decoded Outputs + * + * +--------------+ + * Q1 |1 ++ 16| VDD + * Q0 |2 15| RESET + * Q2 |3 14| CLOCK + * Q5 |4 4022 13| CLOCK ENABLE + * Q6 |5 12| CARRY OUT + * NC |6 11| Q4 + * Q3 |7 10| Q7 + * VSS |8 9| NC + * +--------------+ + * + * Naming conventions follow Fairchild datasheet + * + * FIXME: Timing depends on VDD-VSS + * This needs a cmos d-a/a-d proxy implementation. + * + */ + +#include "nl_base.h" +#include "nl_factory.h" + +namespace netlist::devices { + + template <std::size_t MaxCount> + NETLIB_OBJECT(CD4017_base) + { + NETLIB_CONSTRUCTOR_MODEL(CD4017_base, "CD4XXX") + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_CLKEN(*this, "CLKEN", NETLIB_DELEGATE(inputs)) + , m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs)) + , m_CO(*this, "CO") + , m_Q(*this, 0, "Q{}") + , m_cnt(*this, "m_cnt", 0) + , m_supply(*this) + { + } + + private: + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_cnt = 0; + } + + NETLIB_HANDLERI(clk) + { + ++m_cnt; + update_outputs(m_cnt); + } + + NETLIB_HANDLERI(inputs) + { + if (m_RESET()) + { + m_CLK.inactivate(); + m_cnt = 0; + update_outputs(m_cnt); + } + else if (m_CLKEN()) + { + m_CLK.inactivate(); + } + else + { + m_CLK.activate_lh(); + } + } + + void update_outputs(const unsigned cnt) noexcept + { + for (std::size_t i = 0; i < MaxCount; i++) + m_Q[i].push(i == cnt, NLTIME_FROM_NS(200)); + m_CO.push(cnt < MaxCount / 2, NLTIME_FROM_NS(160)); + } + logic_input_t m_CLK; + logic_input_t m_CLKEN; + logic_input_t m_RESET; + logic_output_t m_CO; + object_array_t<logic_output_t, MaxCount> m_Q; + + state_var<unsigned> m_cnt; + nld_power_pins m_supply; + }; + + using NETLIB_NAME(CD4017) = NETLIB_NAME(CD4017_base)<10>; + using NETLIB_NAME(CD4022) = NETLIB_NAME(CD4017_base)<8>; + + + NETLIB_DEVICE_IMPL(CD4017, "CD4017", "") + NETLIB_DEVICE_IMPL(CD4022, "CD4022", "") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp index d0e35f502b7..626a22f7d05 100644 --- a/src/lib/netlist/devices/nld_4020.cpp +++ b/src/lib/netlist/devices/nld_4020.cpp @@ -1,27 +1,58 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_4020.c + * nld_4020.cpp + * + * CD4020: 14-Stage Ripple Carry Binary Counters + * + * +--------------+ + * Q12 |1 ++ 16| VDD + * Q13 |2 15| Q11 + * Q14 |3 14| Q10 + * Q6 |4 4020 13| Q8 + * Q5 |5 12| Q9 + * Q7 |6 11| RESET + * Q4 |7 10| IP (Input pulses) + * VSS |8 9| Q1 + * +--------------+ + * + * + * CD4024: 7-Stage Ripple Carry Binary Counters + * + * +--------------+ + * IP |1 ++ 14| VDD + * RESET |2 13| NC + * Q7 |3 12| Q1 + * Q6 |4 4024 11| Q2 + * Q5 |5 10| NC + * Q4 |6 9| Q3 + * VSS |7 8| NC + * +--------------+ + * + * + * Naming conventions follow Texas Instruments datasheet + * + * FIXME: Timing depends on VDD-VSS + * This needs a cmos d-a/a-d proxy implementation. * */ -//#include "nlid_cmos.h" -#include "nld_4020.h" -#include "nlid_system.h" +#include "nl_base.h" +#include "nl_factory.h" -namespace netlist -{ - namespace devices - { +namespace netlist::devices { + + template <unsigned TotalBits, unsigned LiveBitmask> NETLIB_OBJECT(CD4020_sub) { - NETLIB_CONSTRUCTOR(CD4020_sub) - NETLIB_FAMILY("CD4XXX") - , m_IP(*this, "IP") - , m_Q(*this, {{"Q1", "_Q2", "_Q3", "Q4", "Q5", "Q6", "Q7", "Q8", "Q9", - "Q10", "Q11", "Q12", "Q13", "Q14"}}) + static_assert((LiveBitmask >> TotalBits) == 0, "Live bitmask too large"); + + NETLIB_CONSTRUCTOR_MODEL(CD4020_sub, "CD4XXX") + , m_IP(*this, "IP", NETLIB_DELEGATE(ip)) + , m_RESET(*this, "RESET", NETLIB_DELEGATE(reseti)) + , m_Q(*this, 1, "Q{}") , m_cnt(*this, "m_cnt", 0) - , m_supply(*this, "VDD", "VSS") + , m_supply(*this) { } @@ -31,91 +62,57 @@ namespace netlist m_cnt = 0; } - NETLIB_UPDATEI(); - - public: - void update_outputs(const unsigned cnt); - - logic_input_t m_IP; - object_array_t<logic_output_t, 14> m_Q; - - state_var<unsigned> m_cnt; - nld_power_pins m_supply; - }; - - NETLIB_OBJECT(CD4020) - { - NETLIB_CONSTRUCTOR(CD4020) - NETLIB_FAMILY("CD4XXX") - , m_sub(*this, "sub") - , m_RESET(*this, "RESET") + NETLIB_HANDLERI(ip) { - register_subalias("IP", m_sub.m_IP); - register_subalias("Q1", m_sub.m_Q[0]); - register_subalias("Q4", m_sub.m_Q[3]); - register_subalias("Q5", m_sub.m_Q[4]); - register_subalias("Q6", m_sub.m_Q[5]); - register_subalias("Q7", m_sub.m_Q[6]); - register_subalias("Q8", m_sub.m_Q[7]); - register_subalias("Q9", m_sub.m_Q[8]); - register_subalias("Q10", m_sub.m_Q[9]); - register_subalias("Q11", m_sub.m_Q[10]); - register_subalias("Q12", m_sub.m_Q[11]); - register_subalias("Q13", m_sub.m_Q[12]); - register_subalias("Q14", m_sub.m_Q[13]); - register_subalias("VDD", "sub.VDD"); - register_subalias("VSS", "sub.VSS"); + ++m_cnt; + update_outputs(m_cnt); } - NETLIB_RESETI() { } - NETLIB_UPDATEI(); - private: - NETLIB_SUB(CD4020_sub) m_sub; - logic_input_t m_RESET; - }; - - - NETLIB_UPDATE(CD4020_sub) - { - ++m_cnt; - m_cnt &= 0x3fff; - update_outputs(m_cnt); - } + NETLIB_HANDLERI(reseti) + { + if (m_RESET()) + { + m_cnt = 0; + m_IP.inactivate(); + /* static */ const netlist_time reset_time = netlist_time::from_nsec(140); + for (unsigned i = 0; i < TotalBits; i++) + if (((LiveBitmask >> i) & 1) != 0) + m_Q[i].push(0, reset_time); + } + else + m_IP.activate_hl(); + } - NETLIB_UPDATE(CD4020) - { - if (m_RESET()) + public: + void update_outputs(const unsigned cnt) noexcept { - m_sub.m_cnt = 0; - m_sub.m_IP.inactivate(); - /* static */ const netlist_time reset_time = netlist_time::from_nsec(140); - m_sub.m_Q[0].push(0, reset_time); - for (std::size_t i=3; i<14; i++) - m_sub.m_Q[i].push(0, reset_time); + static constexpr const std::array<netlist_time, 14> out_delayQn = { + NLTIME_FROM_NS(180), NLTIME_FROM_NS(280), + NLTIME_FROM_NS(380), NLTIME_FROM_NS(480), + NLTIME_FROM_NS(580), NLTIME_FROM_NS(680), + NLTIME_FROM_NS(780), NLTIME_FROM_NS(880), + NLTIME_FROM_NS(980), NLTIME_FROM_NS(1080), + NLTIME_FROM_NS(1180), NLTIME_FROM_NS(1280), + NLTIME_FROM_NS(1380), NLTIME_FROM_NS(1480), + }; + + for (unsigned i = 0; i < TotalBits; i++) + if (((LiveBitmask >> i) & 1) != 0) + m_Q[i].push((cnt >> i) & 1, out_delayQn[i]); } - else - m_sub.m_IP.activate_hl(); - } + logic_input_t m_IP; + logic_input_t m_RESET; + object_array_t<logic_output_t, TotalBits> m_Q; - NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const unsigned cnt)) - { - static constexpr const std::array<netlist_time, 14> out_delayQn = { - NLTIME_FROM_NS(180), NLTIME_FROM_NS(280), - NLTIME_FROM_NS(380), NLTIME_FROM_NS(480), - NLTIME_FROM_NS(580), NLTIME_FROM_NS(680), - NLTIME_FROM_NS(780), NLTIME_FROM_NS(880), - NLTIME_FROM_NS(980), NLTIME_FROM_NS(1080), - NLTIME_FROM_NS(1180), NLTIME_FROM_NS(1280), - NLTIME_FROM_NS(1380), NLTIME_FROM_NS(1480), - }; + state_var<unsigned> m_cnt; + nld_power_pins m_supply; + }; - m_Q[0].push(cnt & 1, out_delayQn[0]); - for (std::size_t i=3; i<14; i++) - m_Q[i].push((cnt >> i) & 1, out_delayQn[i]); - } + // FIXME: Exposes Q2 and Q3 as well + using NETLIB_NAME(CD4020_impl) = nld_CD4020_sub<14, 0x3ff9>; + NETLIB_DEVICE_IMPL_ALIAS(CD4020, CD4020_impl,"CD4020", "+IP,+RESET,+VDD,+VSS") - NETLIB_DEVICE_IMPL(CD4020, "CD4020", "") - NETLIB_DEVICE_IMPL_ALIAS(CD4020_WI, CD4020, "CD4020_WI", "+IP,+RESET,+VDD,+VSS") + using NETLIB_NAME(CD4024_impl) = nld_CD4020_sub<7, 0x7f>; + NETLIB_DEVICE_IMPL_ALIAS(CD4024, CD4024_impl, "CD4024", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4020.h b/src/lib/netlist/devices/nld_4020.h deleted file mode 100644 index f24251fb1dc..00000000000 --- a/src/lib/netlist/devices/nld_4020.h +++ /dev/null @@ -1,43 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_4020.h - * - * CD4020: 14-Stage Ripple Carry Binary Counters - * - * +--------------+ - * Q12 |1 ++ 16| VDD - * Q13 |2 15| Q11 - * Q14 |3 14| Q10 - * Q6 |4 4020 13| Q8 - * Q5 |5 12| Q9 - * Q7 |6 11| RESET - * Q4 |7 10| IP (Input pulses) - * VSS |8 9| Q1 - * +--------------+ - * - * - * Naming conventions follow Texas Instruments datasheet - * - * FIXME: Timing depends on VDD-VSS - * This needs a cmos d-a/a-d proxy implementation. - * - */ - -#ifndef NLD_4020_H_ -#define NLD_4020_H_ - -#include "netlist/nl_setup.h" - -/* FIXME: only used in mario.c */ -#define CD4020_WI(name, cIP, cRESET, cVDD, cVSS) \ - NET_REGISTER_DEV(CD4020_WI, name) \ - NET_CONNECT(name, IP, cIP) \ - NET_CONNECT(name, RESET, cRESET) \ - NET_CONNECT(name, VDD, cVDD) \ - NET_CONNECT(name, VSS, cVSS) - -#define CD4020(name) \ - NET_REGISTER_DEV(CD4020, name) - -#endif /* NLD_4020_H_ */ diff --git a/src/lib/netlist/devices/nld_4029.cpp b/src/lib/netlist/devices/nld_4029.cpp new file mode 100644 index 00000000000..e6f1b6856a3 --- /dev/null +++ b/src/lib/netlist/devices/nld_4029.cpp @@ -0,0 +1,268 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud, Jonathan Gevaryahu +/* + * nld_4029.cpp + * + * CD4029BM/CD4029BC Presettable Binary/Decade Up/Down Counter + * + * +--------------+ + * PE |1 ++ 16| VDD + * Q4 |2 15| CLK + * J4 |3 14| Q3 + * J1 |4 4029 13| J3 + * CI |5 12| J2 + * Q1 |6 11| Q2 + * CO |7 10| U/D + * VSS |8 9| B/D + * +--------------+ + * + * Counter Sequences: + * + * B/D high (Binary), U/D high (Up) + * +-------++----+----+----+----+----++-------+ + * | COUNT || Q4 | Q3 | Q2 | Q1 | CO || NEXT | + * +=======++====+====+====+====+====++=======+ + * | 0 || 0 | 0 | 0 | 0 | 1 || 1 | + * | 1 || 0 | 0 | 0 | 1 | 1 || 2 | + * | 2 || 0 | 0 | 1 | 0 | 1 || 3 | + * | 3 || 0 | 0 | 1 | 1 | 1 || 4 | + * | 4 || 0 | 1 | 0 | 0 | 1 || 5 | + * | 5 || 0 | 1 | 0 | 1 | 1 || 6 | + * | 6 || 0 | 1 | 1 | 0 | 1 || 7 | + * | 7 || 0 | 1 | 1 | 1 | 1 || 8 | + * | 8 || 1 | 0 | 0 | 0 | 1 || 9 | + * | 9 || 1 | 0 | 0 | 1 | 1 || A | + * | A || 1 | 0 | 1 | 0 | 1 || B | + * | B || 1 | 0 | 1 | 1 | 1 || C | + * | C || 1 | 1 | 0 | 0 | 1 || D | + * | D || 1 | 1 | 0 | 1 | 1 || E | + * | E || 1 | 1 | 1 | 0 | 1 || F | + * | F || 1 | 1 | 1 | 1 |0|CI|| 0 | + * | 0 || 0 | 0 | 0 | 0 | 1 || 1 | + * +-------++----+----+----+----+----++-------+ + * + * B/D high (Binary), U/D low (Down) + * +-------++----+----+----+----+----++-------+ + * | COUNT || Q4 | Q3 | Q2 | Q1 | CO || NEXT | + * +=======++====+====+====+====+====++=======+ + * | F || 1 | 1 | 1 | 1 | 1 || E | + * | E || 1 | 1 | 1 | 0 | 1 || D | + * | D || 1 | 1 | 0 | 1 | 1 || C | + * | C || 1 | 1 | 0 | 0 | 1 || B | + * | B || 1 | 0 | 1 | 1 | 1 || A | + * | A || 1 | 0 | 1 | 0 | 1 || 9 | + * | 9 || 1 | 0 | 0 | 1 | 1 || 8 | + * | 8 || 1 | 0 | 0 | 0 | 1 || 7 | + * | 7 || 0 | 1 | 1 | 1 | 1 || 6 | + * | 6 || 0 | 1 | 1 | 0 | 1 || 5 | + * | 5 || 0 | 1 | 0 | 1 | 1 || 4 | + * | 4 || 0 | 1 | 0 | 0 | 1 || 3 | + * | 3 || 0 | 0 | 1 | 1 | 1 || 2 | + * | 2 || 0 | 0 | 1 | 0 | 1 || 1 | + * | 1 || 0 | 0 | 0 | 1 | 1 || 0 | + * | 0 || 0 | 0 | 0 | 0 |0|CI|| F | + * | F || 1 | 1 | 1 | 1 | 1 || E | + * +-------++----+----+----+----+----++-------+ + * + * B/D low (Decimal), U/D high (Up) + * +-------++----+----+----+----+----++-------+ + * | COUNT || Q4 | Q3 | Q2 | Q1 | CO || NEXT | + * +=======++====+====+====+====+====++=======+ + * | 0 || 0 | 0 | 0 | 0 | 1 || 1 | + * | 1 || 0 | 0 | 0 | 1 | 1 || 2 | + * | 2 || 0 | 0 | 1 | 0 | 1 || 3 | + * | 3 || 0 | 0 | 1 | 1 | 1 || 4 | + * | 4 || 0 | 1 | 0 | 0 | 1 || 5 | + * | 5 || 0 | 1 | 0 | 1 | 1 || 6 | + * | 6 || 0 | 1 | 1 | 0 | 1 || 7 | + * | 7 || 0 | 1 | 1 | 1 | 1 || 8 | + * | 8 || 1 | 0 | 0 | 0 | 1 || 9 | + * | 9 || 1 | 0 | 0 | 1 |0|CI|| 0 | + * | A || 1 | 0 | 1 | 0 | 1 || B | + * | B || 1 | 0 | 1 | 1 |0|CI|| 6 | + * | C || 1 | 1 | 0 | 0 | 1 || D | + * | D || 1 | 1 | 0 | 1 |0|CI|| 4 | + * | E || 1 | 1 | 1 | 0 | 1 || F | + * | F || 1 | 1 | 1 | 1 |0|CI|| 2 | + * | 0 || 0 | 0 | 0 | 0 | 1 || 1 | + * +-------++----+----+----+----+----++-------+ + * + * B/D low (Decimal), U/D low (Down) + * +-------++----+----+----+----+----++-------+ + * | COUNT || Q4 | Q3 | Q2 | Q1 | CO || NEXT | + * +=======++====+====+====+====+====++=======+ + * | F || 1 | 1 | 1 | 1 | 1 || E | + * | E || 1 | 1 | 1 | 0 | 1 || D | + * | D || 1 | 1 | 0 | 1 | 1 || C | + * | C || 1 | 1 | 0 | 0 | 1 || B | + * | B || 1 | 0 | 1 | 1 | 1 || A | + * | A || 1 | 0 | 1 | 0 | 1 || 9 | + * | 9 || 1 | 0 | 0 | 1 | 1 || 8 | + * | 8 || 1 | 0 | 0 | 0 | 1 || 7 | + * | 7 || 0 | 1 | 1 | 1 | 1 || 6 | + * | 6 || 0 | 1 | 1 | 0 | 1 || 5 | + * | 5 || 0 | 1 | 0 | 1 | 1 || 4 | + * | 4 || 0 | 1 | 0 | 0 | 1 || 3 | + * | 3 || 0 | 0 | 1 | 1 | 1 || 2 | + * | 2 || 0 | 0 | 1 | 0 | 1 || 1 | + * | 1 || 0 | 0 | 0 | 1 | 1 || 0 | + * | 0 || 0 | 0 | 0 | 0 |0|CI|| 9 | + * | 9 || 1 | 0 | 0 | 1 | 1 || 8 | + * +-------++----+----+----+----+----++-------+ + * + * Note that in all cases where Carry-out is generating a non-1 signal (0 | Carry-in), + * this signal is asynchronous, so if carry-in changes the carry-out value will + * change immediately. + * + * + * Preset/Carry in function table + * +-----+-----+-----++----+----+----+----+ + * | PE | CLK | CI || Q1 | Q2 | Q3 | Q4 | + * +=====+=====+=====++====+====+====+====+ + * | 1 | X | X || J1 | J2 | J3 | J4 | + * | 0 | X | 1 || Q1 | Q2 | Q3 | Q4 | + * | 0 | ./` | 0 || COUNT | + * +-----+-----+-----++----+----+----+----+ + * + * Naming conventions follow National Semiconductor datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + NETLIB_OBJECT(CD4029) + { + NETLIB_CONSTRUCTOR_MODEL(CD4029, "CD4XXX") + , m_PE(*this, "PE", NETLIB_DELEGATE(inputs)) + , m_J(*this, {"J1", "J2", "J3", "J4"}, NETLIB_DELEGATE(inputs)) + , m_CI(*this, "CI", NETLIB_DELEGATE(inputs)) + , m_UD(*this, "UD", NETLIB_DELEGATE(inputs)) + , m_BD(*this, "BD", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_clk_old(*this, "m_clk_old", false) + , m_Q(*this, {"Q1", "Q2", "Q3", "Q4"}) + , m_CO(*this, "CO", false) + , m_cnt(*this, "m_cnt", 0) + , m_power_pins(*this) + { + } + + private: + NETLIB_HANDLERI(inputs) // pe causes an asynchronous counter load on level so has to be handled separately; if pe is high, then J changing will asynchronously change the Q state. changing J in this state does affect CO as well; CI will affect CO asynchronously if there is currently a carry + { + if (m_PE()) + { + m_cnt = m_J()&0xf; + } + m_Q.push(m_cnt, NLTIME_FROM_NS(200)); + // figure out CO + if (!m_UD()) // downward is the same for binary and decimal + { + m_CO.push(m_cnt||m_CI(),NLTIME_FROM_NS(320)); + } + else // upward mode differs + { + if (!m_BD()) // decimal mode + { + m_CO.push((m_cnt<8)||(~m_cnt&1)||m_CI(),NLTIME_FROM_NS(320)); + } + else // binary mode + { + m_CO.push((m_cnt!=0xf)||m_CI(),NLTIME_FROM_NS(320)); + } + } + } + + NETLIB_HANDLERI(clk) + { + // clocking only happens if m_clk_old was low, m_CLK is high, m_PE is NOT high, and m_CI is NOT high. + if (!m_PE() && !m_CI() && !m_clk_old && m_CLK()) + { + if (m_BD()) // binary + { + m_cnt += (m_UD() ? 1 : -1); + m_cnt &= 0xf; + } + else // decimal + { + if (m_UD()) // upward + { + switch(m_cnt) + { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + case 8: case 0xa: case 0xc: case 0xe: + m_cnt++; + break; + case 9: + m_cnt = 0; + break; + case 0xb: + m_cnt = 6; + break; + case 0xd: + m_cnt = 4; + break; + case 0xf: + m_cnt = 2; + break; + } + } + else // downward + { + if (m_cnt>0) + { + m_cnt--; + } + else // m_cnt == 0 + { + m_cnt = 9; + } + } + } + } + m_clk_old = m_CLK(); + m_Q.push(m_cnt, NLTIME_FROM_NS(200)); + // figure out CO + if (!m_UD()) // downward is the same for binary and decimal + { + m_CO.push(m_cnt||m_CI(),NLTIME_FROM_NS(320)); + } + else // upward mode differs + { + if (!m_BD()) // decimal mode + { + m_CO.push((m_cnt<8)||(~m_cnt&1)||m_CI(),NLTIME_FROM_NS(320)); + } + else // binary mode + { + m_CO.push((m_cnt!=0xf)||m_CI(),NLTIME_FROM_NS(320)); + } + } + } + + NETLIB_RESETI() + { + m_cnt = 0; + m_clk_old = false; + } + + logic_input_t m_PE; + object_array_t<logic_input_t, 4> m_J; + logic_input_t m_CI; + logic_input_t m_UD; + logic_input_t m_BD; + logic_input_t m_CLK; + + state_var<netlist_sig_t> m_clk_old; + object_array_t<logic_output_t, 4> m_Q; + logic_output_t m_CO; + state_var_u8 m_cnt; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(CD4029, "CD4029", "+PE,+J1,+J2,+J3,+J4,+CI,+UD,+BD,+CLK,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4042.cpp b/src/lib/netlist/devices/nld_4042.cpp new file mode 100644 index 00000000000..14b80b5b53a --- /dev/null +++ b/src/lib/netlist/devices/nld_4042.cpp @@ -0,0 +1,116 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud, Jonathan Gevaryahu +/* + * nld_4042.cpp + * + * CD4042BM/CD4042BC Quad Clocked D Latch + * + * +--------------+ + * Q4 |1 ++ 16| VDD + * Q1 |2 15| Q4Q + * Q1Q |3 14| D4 + * D1 |4 4042 13| D3 + * CLK |5 12| Q3Q + * POL |6 11| Q3 + * D2 |7 10| Q2 + * VSS |8 9| Q2Q + * +--------------+ + * + * + * Function table + * +-----+-----+----++----+-----+ + * | POL | CLK | Dx || Qx | QQx | + * +=====+=====+====++====+=====+ + * | 0 | 0 | X || Qx | /Qx | + * | 0 | 1 | D || D | /D | + * | 1 | 1 | X || Qx | /Qx | + * | 1 | 0 | D || D | /D | + * +-----+-----+----++----+-----+ + * Note that since this is a level triggered transparent latch, + * as long as POL ^ CLK == true, the latch is transparent, and + * if D changes Q and QQ(/Q) will instantly change. + * + * Naming conventions follow National Semiconductor datasheet + * + * National Semiconductor Datasheet: http://pdf.datasheetcatalog.com/datasheet/nationalsemiconductor/DS005966.PDF + * TI Datasheet: https://www.ti.com/lit/ds/symlink/cd4042b.pdf + */ + +#include "nl_base.h" + +namespace netlist::devices { + + + NETLIB_OBJECT(CD4042) + { + NETLIB_CONSTRUCTOR_MODEL(CD4042, "CD4XXX") + , m_D(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(inputs)) + , m_POL(*this, "POL", NETLIB_DELEGATE(clk)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_Q(*this, {"Q1", "Q2", "Q3", "Q4"}) + , m_QQ(*this, {"Q1Q", "Q2Q", "Q3Q", "Q4Q"}) + , m_latch(*this, "m_latch", 0) + , m_tpdq(*this, "m_tpd", netlist_time::from_nsec(175)) + , m_tpdqq(*this, "m_tpd", netlist_time::from_nsec(150)) + , m_tpcq(*this, "m_tpc", netlist_time::from_nsec(250)) + , m_tpcqq(*this, "m_tpc", netlist_time::from_nsec(250)) + , m_power_pins(*this, NETLIB_DELEGATE(vdd_vss)) + { + } + + private: + NETLIB_HANDLERI(clk) + { + if (m_POL() ^ m_CLK()) // are we in transparent mode? if so latch the data and push it. + { + m_latch = m_D()&0xf; + m_Q.push(m_latch&0xf, m_tpcq); + m_QQ.push((~m_latch)&0xf, m_tpcqq); + } + // if not, the data inputs are ignored and just do nothing + } + + NETLIB_HANDLERI(inputs) + { + if ((m_POL() ^ m_CLK())&&(m_latch != (m_D()&0xf))) // are we in transparent mode? if so latch the data and push it. only do this if the data actually changed + { + m_latch = m_D()&0xf; + m_Q.push(m_latch&0xf, m_tpdq); + m_QQ.push((~m_latch)&0xf, m_tpdqq); + } + } + + NETLIB_HANDLERI(vdd_vss) + { + auto d = m_power_pins.VCC()() - m_power_pins.GND()(); + if (d > 0.1) // avoid unrealistic values + { + m_tpdq = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(894.0 / d - 6.0)); + m_tpdqq = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(750.0 / d + 0.0)); + m_tpcq = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(1327.0 / d - 18.8)); + m_tpcqq = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(1234.5 / d + 0.8)); + } + } + + NETLIB_RESETI() + { + m_latch = 0; + } + + object_array_t<logic_input_t, 4> m_D; + logic_input_t m_POL; + logic_input_t m_CLK; + + object_array_t<logic_output_t, 4> m_Q; + object_array_t<logic_output_t, 4> m_QQ; + state_var_u8 m_latch; + state_var<netlist_time> m_tpdq; // propagation time for data alone when in transparent mode, Q + state_var<netlist_time> m_tpdqq; // propagation time for data alone when in transparent mode, /Q + state_var<netlist_time> m_tpcq; // propagation time for data vs CLK, Q + state_var<netlist_time> m_tpcqq; // propagation time for data vs CLK, /Q + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(CD4042, "CD4042", "+D1,+D2,+D3,+D4,+POL,+CLK,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4053.cpp b/src/lib/netlist/devices/nld_4053.cpp new file mode 100644 index 00000000000..a199fedf7fc --- /dev/null +++ b/src/lib/netlist/devices/nld_4053.cpp @@ -0,0 +1,142 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_4053.cpp + * + * CD4053: Triple 2-Channel Analog Multiplexer/Demultiplexer + * + * +--------------+ + * INOUTBY |1 ++ 16| VDD + * INOUTBX |2 15| OUTINB + * INOUTCY |3 14| OUTINA + * OUTINC |4 4053 13| INOUTAY + * INOUTCX |5 12| INOUTAX + * INH |6 11| A + * VEE |7 10| B + * VSS |8 9| C + * +--------------+ + * + * FIXME: These devices are slow (~125 ns). This is currently not reflected + * + * Naming conventions follow National semiconductor datasheet + * + */ + + +#include "analog/nlid_twoterm.h" +#include "solver/nld_solver.h" + +namespace netlist::devices { + + NETLIB_OBJECT(CD4053_GATE) + { + NETLIB_CONSTRUCTOR_MODEL(CD4053_GATE, "CD4XXX") + , m_RX(*this, "RX") + , m_RY(*this, "RY") + , m_select(*this, "S", NETLIB_DELEGATE(controls)) + , m_inhibit(*this, "INH", NETLIB_DELEGATE(controls)) + , m_VEE(*this, "VEE", NETLIB_DELEGATE(controls)) + , m_base_r(*this, "BASER", nlconst::magic(270.0)) + , m_last_x(*this, "m_lastx", false) + , m_last_y(*this, "m_lasty", false) + , m_select_state(*this, "m_select_state", false) + , m_inhibit_state(*this, "m_inhibit_state", false) + , m_supply(*this) + { + connect("RX.2", "RY.2"); + register_sub_alias("X", "RX.1"); + register_sub_alias("Y", "RY.1"); + register_sub_alias("XY", "RX.2"); + } + + NETLIB_RESETI() + { + update_state(true, false); + } + + private: + NETLIB_HANDLERI(controls) + { + bool new_x = false; + bool new_y = false; + if (!on(m_inhibit, m_inhibit_state)) + { + if (!on(m_select, m_select_state)) + { + new_x = true; + } + else + { + new_y = true; + } + } + + if (new_x != m_last_x || new_y != m_last_y) + update_state(new_x, new_y); + } + + bool on(analog_input_t &input, bool &state) + { + // digital inputs are based on VDD + nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog()); + nl_fptype in = input() - m_supply.GND().Q_Analog(); + nl_fptype low = nlconst::magic(0.3) * sup; + nl_fptype high = nlconst::magic(0.7) * sup; + if (in < low) + { + state = false; + } + else if (in > high) + { + state = true; + } + return state; + } + + void update_state(bool newx, bool newy) + { + // analog output is based on VEE + const nl_fptype sup = (m_VEE() - m_supply.GND().Q_Analog()); + const nl_fptype Ron = m_base_r() * nlconst::magic(5.0) / sup; + const nl_fptype Roff = plib::reciprocal(exec().gmin()); + const nl_fptype RX = newx ? Ron : Roff; + const nl_fptype RY = newy ? Ron : Roff; + if (m_RX().solver() == m_RY().solver()) + { + m_RX().change_state([this, &RX, &RY]() + { + m_RX().set_R(RX); + m_RY().set_R(RY); + }); + } + else + { + m_RX().change_state([this, &RX]() + { + m_RX().set_R(RX); + }); + m_RY().change_state([this, &RY]() + { + m_RY().set_R(RY); + }); + } + m_last_x = newx; + m_last_y = newy; + } + + NETLIB_SUB_NS(analog, R_base) m_RX; + NETLIB_SUB_NS(analog, R_base) m_RY; + analog_input_t m_select; + analog_input_t m_inhibit; + analog_input_t m_VEE; + param_fp_t m_base_r; + state_var<bool> m_last_x; + state_var<bool> m_last_y; + state_var<bool> m_select_state; + state_var<bool> m_inhibit_state; + nld_power_pins m_supply; + }; + + NETLIB_DEVICE_IMPL(CD4053_GATE, "CD4053_GATE", "") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp index 96200688400..bd2a0a13196 100644 --- a/src/lib/netlist/devices/nld_4066.cpp +++ b/src/lib/netlist/devices/nld_4066.cpp @@ -1,76 +1,83 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_4066.c + * nld_4066.cpp + * + * CD4066: Quad Bilateral Switch + * + * +--------------+ + * INOUTA |1 ++ 14| VDD + * OUTINA |2 13| CONTROLA + * OUTINB |3 12| CONTROLD + * INOUTB |4 4066 11| INOUTD + * CONTROLB |5 10| OUTIND + * CONTROLC |6 9| OUTINC + * VSS |7 8| INOUTC + * +--------------+ + * + * FIXME: These devices are slow (~125 ns). This is currently not reflected + * + * Naming conventions follow National semiconductor datasheet * */ -#include "nld_4066.h" +#include "analog/nlid_twoterm.h" +#include "solver/nld_solver.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/solver/nld_solver.h" -#include "nlid_system.h" -namespace netlist -{ - namespace devices - { +namespace netlist::devices { + NETLIB_OBJECT(CD4066_GATE) { - NETLIB_CONSTRUCTOR(CD4066_GATE) - NETLIB_FAMILY("CD4XXX") - , m_supply(*this, "VDD", "VSS", true) + NETLIB_CONSTRUCTOR_MODEL(CD4066_GATE, "CD4XXX") , m_R(*this, "R") - , m_control(*this, "CTL") - , m_base_r(*this, "BASER", 270.0) + , m_control(*this, "CTL", NETLIB_DELEGATE(control)) + , m_base_r(*this, "BASER", nlconst::magic(270.0)) + , m_last(*this, "m_last", false) + , m_supply(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + // Start in off condition + // FIXME: is ROFF correct? + m_R().set_R(plib::reciprocal(exec().gmin())); + } private: - nld_power_pins m_supply; - analog::NETLIB_SUB(R_base) m_R; + NETLIB_HANDLERI(control) + { + nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog()); + nl_fptype in = m_control() - m_supply.GND().Q_Analog(); + nl_fptype rON = m_base_r() * nlconst::magic(5.0) / sup; + nl_fptype R = -nlconst::one(); + nl_fptype low = nlconst::magic(0.45) * sup; + nl_fptype high = nlconst::magic(0.55) * sup; + bool new_state(false); + if (in < low) + { + R = plib::reciprocal(exec().gmin()); + } + else if (in > high) + { + R = rON; + new_state = true; + } + if (R > nlconst::zero() && (m_last != new_state)) + { + m_last = new_state; + m_R().change_state([this, &R]() -> void { this->m_R().set_R(R);}); + } + } + NETLIB_SUB_NS(analog, R_base) m_R; analog_input_t m_control; - param_double_t m_base_r; + param_fp_t m_base_r; + state_var<bool> m_last; + nld_power_pins m_supply; }; - NETLIB_RESET(CD4066_GATE) - { - // Start in off condition - // FIXME: is ROFF correct? - m_R.set_R(plib::constants<nl_double>::one() / exec().gmin()); - - } - - NETLIB_UPDATE(CD4066_GATE) - { - nl_double sup = (m_supply.VCC() - m_supply.GND()); - nl_double low = plib::constants<nl_double>::cast(0.45) * sup; - nl_double high = plib::constants<nl_double>::cast(0.55) * sup; - nl_double in = m_control() - m_supply.GND(); - nl_double rON = m_base_r() * plib::constants<nl_double>::cast(5.0) / sup; - nl_double R = -1.0; - - if (in < low) - { - R = plib::constants<nl_double>::one() / exec().gmin(); - } - else if (in > high) - { - R = rON; - } - if (R > plib::constants<nl_double>::zero()) - { - m_R.update(); - m_R.set_R(R); - m_R.solve_later(); - } - } - NETLIB_DEVICE_IMPL(CD4066_GATE, "CD4066_GATE", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4066.h b/src/lib/netlist/devices/nld_4066.h deleted file mode 100644 index 0a43911d3ce..00000000000 --- a/src/lib/netlist/devices/nld_4066.h +++ /dev/null @@ -1,34 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_4066.h - * - * CD4066: Quad Bilateral Switch - * - * +--------------+ - * INOUTA |1 ++ 14| VDD - * OUTINA |2 13| CONTROLA - * OUTINB |3 12| CONTROLD - * INOUTB |4 4066 11| INOUTD - * CONTROLB |5 10| OUTIND - * CONTROLC |6 9| OUTINC - * VSS |7 8| INOUTC - * +--------------+ - * - * FIXME: These devices are slow (~125 ns). This is currently not reflected - * - * Naming conventions follow National semiconductor datasheet - * - */ - -#ifndef NLD_4066_H_ -#define NLD_4066_H_ - -#include "netlist/nl_setup.h" - -// FIXME: Implement pure CMOS version - -#define CD4066_GATE(name) \ - NET_REGISTER_DEV(CD4066_GATE, name) - -#endif /* NLD_4066_H_ */ diff --git a/src/lib/netlist/devices/nld_4076.cpp b/src/lib/netlist/devices/nld_4076.cpp new file mode 100644 index 00000000000..41abfbc7711 --- /dev/null +++ b/src/lib/netlist/devices/nld_4076.cpp @@ -0,0 +1,127 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud, Jonathan Gevaryahu +/* + * nld_4076.cpp + * + * CD4076BM/CD4076BC TRI-STATE(R) Quad D Flip-Flop + * + * +--------------+ + * OD1 |1 ++ 16| VDD + * OD2 |2 15| CLR + * OA |3 14| IA + * OB |4 4076 13| IB + * OC |5 12| IC + * OD |6 11| ID + * CLK |7 10| ID2 + * VSS |8 9| ID1 + * +--------------+ + * + * + * Function table for ID1/2 pins + * +-----+-----+-----+----+-----++-----+ + * | ID1 | ID2 | CLR | Ix | CLK || iOx | + * +=====+=====+=====+====+=====++=====+ + * | X | X | 0 | X | 0 || iOx | + * | X | X | 0 | X | 1 || iOx | + * | 1 | X | 0 | X | 0>1 || iOx | + * | X | 1 | 0 | X | 0>1 || iOx | + * | 0 | 0 | 0 | 0 | 0>1 || 0 | + * | 0 | 0 | 0 | 1 | 0>1 || 1 | + * | X | X | 1 | X | X || 0 | + * +-----+-----+-----+----+-----++-----+ + * Note: iOX is an internal signal, the output of each D-latch + * + * Function table for OD1/2 pins vs output of the internal D-latches + * +-----+-----+-----++-----+ + * | OD1 | OD2 | iOx || Ox | + * +=====+=====+=====++=====+ + * | 1 | X | X || Z | + * | X | 1 | X || Z | + * | 0 | 0 | 0 || 0 | + * | 0 | 0 | 1 || 1 | + * +-----+-----+-----++-----+ + * + * Naming conventions follow National Semiconductor datasheet + * http://www.bitsavers.org/components/national/_dataBooks/1981_Natonal_CMOS_Databook.pdf 5-186 (pdf page 567) + * + * TODO: the 74C173 is 100% identical to this CMOS part. + */ + +#include "nl_base.h" + +namespace netlist::devices { + + NETLIB_OBJECT(CD4076) + { + NETLIB_CONSTRUCTOR_MODEL(CD4076, "CD4XXX") + , m_I(*this, {"IA", "IB", "IC", "ID"}, NETLIB_DELEGATE(id)) // if the d-pins change absolutely nothing happens, as they are clock-latched. + , m_ID1(*this, "ID1", NETLIB_DELEGATE(id)) + , m_ID2(*this, "ID2", NETLIB_DELEGATE(id)) + , m_enable_in(*this, "m_enable_in", true) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_clk_old(*this, "m_clk_old", 0) + , m_OD1(*this, "OD1", NETLIB_DELEGATE(od)) // if the OD pins change nothing about the internal state changes directly, but the outputs can change from driven to tri-state or vice-versa + , m_OD2(*this, "OD2", NETLIB_DELEGATE(od)) // "" + , m_enable_out(*this, "m_enable_out", true) + , m_O(*this, {"OA", "OB", "OC", "OD"}) + , m_latch(*this, "m_latch", 0) + , m_power_pins(*this) + { + } + + private: + NETLIB_HANDLERI(id) + { + m_enable_in = (!(m_ID1() || m_ID2())); + } + + NETLIB_HANDLERI(clk) + { + if ((!m_clk_old) && m_CLK() && m_enable_in) // clock rising edge and input is enabled; otherwise the latch just re-latches its own value + { + m_latch = m_I()&0xf; + } + m_clk_old = m_CLK(); + // update the pin output state + for (std::size_t i=0; i<4; i++) + { + m_O.set_tristate(m_enable_out, NLTIME_FROM_NS(170), NLTIME_FROM_NS(170)); + m_O[i].push((m_latch >> i) & 1, NLTIME_FROM_NS(220)); + } + } + + NETLIB_HANDLERI(od) + { + m_enable_out = (!(m_OD1() || m_OD2())); + // update the pin output state + for (std::size_t i=0; i<4; i++) + { + m_O.set_tristate(m_enable_out, NLTIME_FROM_NS(170), NLTIME_FROM_NS(170)); + m_O[i].push((m_latch >> i) & 1, NLTIME_FROM_NS(220)); + } + } + + NETLIB_RESETI() + { + m_latch = 0; + m_enable_in = true; + m_enable_out = true; + } + + object_array_t<logic_input_t, 4> m_I; + logic_input_t m_ID1; + logic_input_t m_ID2; + state_var<bool> m_enable_in; + logic_input_t m_CLK; + state_var<netlist_sig_t> m_clk_old; + logic_input_t m_OD1; + logic_input_t m_OD2; + state_var<bool> m_enable_out; + object_array_t<logic_output_t, 4> m_O; + state_var_u8 m_latch; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(CD4076, "CD4076", "+I1,+I2,+I3,+I4,+ID1,+ID2,+OD1,+OD2,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp index bf04882fa27..c875a4e5840 100644 --- a/src/lib/netlist/devices/nld_4316.cpp +++ b/src/lib/netlist/devices/nld_4316.cpp @@ -1,57 +1,70 @@ // license:BSD-3-Clause // copyright-holders:Vas Crabb /* - * nld_4316.c + * nld_4316.cpp + * + * CD74HC4316: Quad Analog Switch with Level Translation + * + * +--------------+ + * 1Z |1 ++ 16| VCC + * 1Y |2 15| 1S + * 2Y |3 14| 4S + * 2Z |4 4316 13| 4Z + * 2S |5 12| 4Y + * 3S |6 11| 3Y + * /E |7 10| 3Z + * GND |8 9| VEE + * +--------------+ + * + * FIXME: These devices are slow (can be over 200 ns in HC types). This is currently not reflected + * + * Naming conventions follow Texas Instruments datasheet * */ -#include "nld_4316.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/solver/nld_solver.h" -#include "nlid_system.h" +#include "analog/nlid_twoterm.h" +#include "solver/nld_solver.h" -namespace netlist { namespace devices { +namespace netlist::devices { + + // FIXME: tristate outputs? NETLIB_OBJECT(CD4316_GATE) { - NETLIB_CONSTRUCTOR(CD4316_GATE) - NETLIB_FAMILY("CD4XXX") - , m_supply(*this, "VDD", "VSS") + NETLIB_CONSTRUCTOR_MODEL(CD4316_GATE, "CD4XXX") , m_R(*this, "_R") - , m_S(*this, "S") - , m_E(*this, "E") - , m_base_r(*this, "BASER", 45.0) + , m_S(*this, "S", NETLIB_DELEGATE(inputs)) + , m_E(*this, "E", NETLIB_DELEGATE(inputs)) + , m_base_r(*this, "BASER", nlconst::magic(45.0)) + , m_supply(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - public: - nld_power_pins m_supply; - analog::NETLIB_SUB(R_base) m_R; + NETLIB_RESETI() + { + m_R().set_R(plib::reciprocal(exec().gmin())); + } - logic_input_t m_S; - logic_input_t m_E; - param_double_t m_base_r; - }; + NETLIB_HANDLERI(inputs) + { + m_R().change_state([this]() + { + if (m_S() && !m_E()) + m_R().set_R(m_base_r()); + else + m_R().set_R(plib::reciprocal(exec().gmin())); + }); + } - NETLIB_RESET(CD4316_GATE) - { - m_R.set_R(plib::constants<nl_double>::one() / exec().gmin()); - } + private: + NETLIB_SUB_NS(analog, R_base) m_R; - NETLIB_UPDATE(CD4316_GATE) - { - m_R.update(); - if (m_S() && !m_E()) - m_R.set_R(m_base_r()); - else - m_R.set_R(plib::constants<nl_double>::one() / exec().gmin()); - m_R.solve_later(NLTIME_FROM_NS(1)); - } + logic_input_t m_S; + logic_input_t m_E; + param_fp_t m_base_r; + nld_power_pins m_supply; + }; NETLIB_DEVICE_IMPL(CD4316_GATE, "CD4316_GATE", "") -} // namespace devices - } // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_4316.h b/src/lib/netlist/devices/nld_4316.h deleted file mode 100644 index 3cf05aeb9cf..00000000000 --- a/src/lib/netlist/devices/nld_4316.h +++ /dev/null @@ -1,33 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/* - * nld_4316.h - * - * CD4066: Quad Analog Switch with Level Translation - * - * +--------------+ - * 1Z |1 ++ 16| VCC - * 1Y |2 15| 1S - * 2Y |3 14| 4S - * 2Z |4 4066 13| 4Z - * 2S |5 12| 4Y - * 3S |6 11| 3Y - * /E |7 10| 3Z - * GND |8 9| VEE - * +--------------+ - * - * FIXME: These devices are slow (can be over 200 ns in HC types). This is currently not reflected - * - * Naming conventions follow Texas Instruments datasheet - * - */ - -#ifndef NLD_4316_H_ -#define NLD_4316_H_ - -#include "netlist/nl_setup.h" - -#define CD4316_GATE(name) \ - NET_REGISTER_DEV(CD4316_GATE, name) - -#endif /* NLD_4316_H_ */ diff --git a/src/lib/netlist/devices/nld_74107.cpp b/src/lib/netlist/devices/nld_74107.cpp index 8bc6ca4bc7a..1501be4763e 100644 --- a/src/lib/netlist/devices/nld_74107.cpp +++ b/src/lib/netlist/devices/nld_74107.cpp @@ -1,155 +1,155 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74107.c + * nld_74107.cpp + * + * DM74107: DUAL J-K FLIP-FLOPS WITH CLEAR + * + * +--------------+ + * 1J |1 ++ 14| VCC + * 1QQ |2 13| 1CLRQ + * 1Q |3 12| 1CLK + * 1K |4 74107 11| 2K + * 2Q |5 10| 2CLRQ + * 2QQ |6 9| 2CLK + * GND |7 8| 2J + * +--------------+ + * + * + * Function table 107 + * + * +-----+-----+-----+---++---+-----+ + * | CLRQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 0 | 1 | + * | 1 | * | 0 | 0 || Q0| Q0Q | + * | 1 | * | 1 | 0 || 1 | 0 | + * | 1 | * | 0 | 1 || 0 | 1 | + * | 1 | * | 1 | 1 || TOGGLE | + * +-----+-----+-----+---++---+-----+ + * _ + * * = _| |_ + * + * This is positive triggered, J and K + * are latched during clock high and + * transferred when CLK falls. The + * datasheet requires J and K to be + * stable during clock high. + * + * Function table 107A + * + * +-----+-----+-----+---++---+-----+ + * | CLRQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 0 | 1 | + * | 1 | F | 0 | 0 || Q0| Q0Q | + * | 1 | F | 1 | 0 || 1 | 0 | + * | 1 | F | 0 | 1 || 0 | 1 | + * | 1 | F | 1 | 1 || TOGGLE | + * | 1 | 1 | X | X || Q0| Q0Q | + * +-----+-----+-----+---++---+-----+ + * + * THe 107A is negative triggered. + * + * Naming conventions follow Texas instruments datasheet + * + * TODO: Currently, only the 107A is implemented. + * The 107 uses the same model, but different timings. + * The requirement that J and K must be stable during + * clock high indicates that the chip may exhibit undefined + * behaviour. * */ -#include "nld_74107.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { +#include "nl_base.h" - static constexpr const netlist_time delay_107[2] = { NLTIME_FROM_NS(16), NLTIME_FROM_NS(25) }; - static constexpr const netlist_time delay_107A[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(15) }; +namespace netlist::devices { - NETLIB_OBJECT(74107A) + template <typename D> + NETLIB_OBJECT(74107_base) { - NETLIB_CONSTRUCTOR(74107A) - , m_clk(*this, "CLK", NETLIB_DELEGATE(74107A, clk)) + NETLIB_CONSTRUCTOR(74107_base) + , m_clk(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_J(*this, "J", NETLIB_DELEGATE(other)) + , m_K(*this, "K", NETLIB_DELEGATE(other)) + , m_clrQ(*this, "CLRQ", NETLIB_DELEGATE(other)) , m_Q(*this, "Q") , m_QQ(*this, "QQ") - , m_J(*this, "J") - , m_K(*this, "K") - , m_clrQ(*this, "CLRQ") , m_power_pins(*this) { - m_delay[0] = delay_107A[0]; - m_delay[1] = delay_107A[1]; } - friend class NETLIB_NAME(74107_dip); - friend class NETLIB_NAME(74107); - //friend class NETLIB_NAME(74107A_dip); - - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_HANDLERI(clk); - private: - logic_input_t m_clk; - - logic_output_t m_Q; - logic_output_t m_QQ; - - netlist_time m_delay[2]; - - logic_input_t m_J; - logic_input_t m_K; - logic_input_t m_clrQ; - - nld_power_pins m_power_pins; - void newstate(const netlist_sig_t state) + NETLIB_RESETI() { - m_Q.push(state, m_delay[state]); - m_QQ.push(state ^ 1, m_delay[state ^ 1]); + m_clk.set_state(logic_t::STATE_INP_HL); + //m_Q.initial(0); + //m_QQ.initial(1); } - }; - NETLIB_OBJECT_DERIVED(74107, 74107A) - { - public: - NETLIB_CONSTRUCTOR_DERIVED(74107, 74107A) + NETLIB_HANDLERI(other) { - m_delay[0] = delay_107[0]; - m_delay[1] = delay_107[1]; + if (!m_clrQ()) + { + m_clk.inactivate(); + newstate(0); + } + else if (m_J() | m_K()) + m_clk.activate_hl(); } - }; - NETLIB_OBJECT(74107_dip) - { - NETLIB_CONSTRUCTOR(74107_dip) - , m_A(*this, "A") - , m_B(*this, "B") + NETLIB_HANDLERI(clk) { - register_subalias("1", m_A.m_J); - register_subalias("2", m_A.m_QQ); - register_subalias("3", m_A.m_Q); - - register_subalias("4", m_A.m_K); - register_subalias("5", m_B.m_Q); - register_subalias("6", m_B.m_QQ); - - register_subalias("7", "A.GND"); - - register_subalias("8", m_B.m_J); - register_subalias("9", m_B.m_clk); - register_subalias("10", m_B.m_clrQ); + const netlist_sig_t J(m_J()); + const netlist_sig_t K(m_K()); + const netlist_sig_t t(m_Q.net().Q()); + /* + * J K Q1 Q2 F t Q + * 0 0 0 1 0 0 0 + * 0 1 0 0 0 0 0 + * 1 0 0 0 1 0 1 + * 1 1 1 0 0 0 1 + * 0 0 0 1 0 1 1 + * 0 1 0 0 0 1 0 + * 1 0 0 0 1 1 1 + * 1 1 1 0 0 1 0 + */ + if ((J & K) ^ 1) + m_clk.inactivate(); + newstate(((t ^ 1) & J) | (t & (K ^ 1))); + } - register_subalias("11", m_B.m_K); - register_subalias("12", m_A.m_clk); - register_subalias("13", m_A.m_clrQ); + void newstate(const netlist_sig_t state) noexcept + { + m_Q.push(state, D::delay::value(state)); + m_QQ.push(state ^ 1, D::delay::value(state ^ 1)); + } - register_subalias("14", "A.VCC" ); + logic_input_t m_clk; - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); + logic_input_t m_J; + logic_input_t m_K; + logic_input_t m_clrQ; - } - //NETLIB_RESETI(); - //NETLIB_UPDATEI(); + logic_output_t m_Q; + logic_output_t m_QQ; - private: - NETLIB_SUB(74107) m_A; - NETLIB_SUB(74107) m_B; + nld_power_pins m_power_pins; }; - NETLIB_RESET(74107A) + struct desc_74107 : public desc_base { - m_clk.set_state(logic_t::STATE_INP_HL); - //m_Q.initial(0); - //m_QQ.initial(1); - } - - NETLIB_HANDLER(74107A, clk) + using delay = times_ns2<16, 25>; + }; + struct desc_74107A : public desc_base { - const netlist_sig_t t(m_Q.net().Q()); - /* - * J K Q1 Q2 F t Q - * 0 0 0 1 0 0 0 - * 0 1 0 0 0 0 0 - * 1 0 0 0 1 0 1 - * 1 1 1 0 0 0 1 - * 0 0 0 1 0 1 1 - * 0 1 0 0 0 1 0 - * 1 0 0 0 1 1 1 - * 1 1 1 0 0 1 0 - */ - if ((m_J() & m_K()) ^ 1) - m_clk.inactivate(); - newstate(((t ^ 1) & m_J()) | (t & (m_K() ^ 1))); - } + using delay = times_ns2<15, 15>; + }; - NETLIB_UPDATE(74107A) - { - if (!m_clrQ()) - { - m_clk.inactivate(); - newstate(0); - } - else if (m_J() | m_K()) - m_clk.activate_hl(); - } + using NETLIB_NAME(74107) = NETLIB_NAME(74107_base)<desc_74107>; + using NETLIB_NAME(74107A) = NETLIB_NAME(74107_base)<desc_74107A>; -#if (!USE_TRUTHTABLE_74107) NETLIB_DEVICE_IMPL(74107, "TTL_74107", "+CLK,+J,+K,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(74107_dip, "TTL_74107_DIP", "") -#endif NETLIB_DEVICE_IMPL(74107A, "TTL_74107A", "+CLK,+J,+K,+CLRQ,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74107.h b/src/lib/netlist/devices/nld_74107.h deleted file mode 100644 index ae1adf33546..00000000000 --- a/src/lib/netlist/devices/nld_74107.h +++ /dev/null @@ -1,87 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74107.h - * - * DM74107: DUAL J-K FLIP-FLOPS WITH CLEAR - * - * +--------------+ - * 1J |1 ++ 14| VCC - * 1QQ |2 13| 1CLRQ - * 1Q |3 12| 1CLK - * 1K |4 74107 11| 2K - * 2Q |5 10| 2CLRQ - * 2QQ |6 9| 2CLK - * GND |7 8| 2J - * +--------------+ - * - * - * Function table 107 - * - * +-----+-----+-----+---++---+-----+ - * | CLRQ| CLK | J | K || Q | QQ | - * +=====+=====+=====+===++===+=====+ - * | 0 | X | X | X || 0 | 1 | - * | 1 | * | 0 | 0 || Q0| Q0Q | - * | 1 | * | 1 | 0 || 1 | 0 | - * | 1 | * | 0 | 1 || 0 | 1 | - * | 1 | * | 1 | 1 || TOGGLE | - * +-----+-----+-----+---++---+-----+ - * _ - * * = _| |_ - * - * This is positive triggered, J and K - * are latched during clock high and - * transferred when CLK falls. The - * datasheet requires J and K to be - * stable during clock high. - * - * Function table 107A - * - * +-----+-----+-----+---++---+-----+ - * | CLRQ| CLK | J | K || Q | QQ | - * +=====+=====+=====+===++===+=====+ - * | 0 | X | X | X || 0 | 1 | - * | 1 | F | 0 | 0 || Q0| Q0Q | - * | 1 | F | 1 | 0 || 1 | 0 | - * | 1 | F | 0 | 1 || 0 | 1 | - * | 1 | F | 1 | 1 || TOGGLE | - * | 1 | 1 | X | X || Q0| Q0Q | - * +-----+-----+-----+---++---+-----+ - * - * THe 107A is negative triggered. - * - * Naming conventions follow Texas instruments datasheet - * - * TODO: Currently, only the 107A is implemented. - * The 107 uses the same model, but different timings. - * The requirement that J and K must be stable during - * clock high indicates that the chip may exhibit undefined - * behaviour. - * - */ - -#ifndef NLD_74107_H_ -#define NLD_74107_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74107A(name, cCLK, cJ, cK, cCLRQ) \ - NET_REGISTER_DEV(TTL_74107A, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, J, cJ) \ - NET_CONNECT(name, K, cK) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#if (!USE_TRUTHTABLE_74107) -#define TTL_74107(name, cCLK, cJ, cK, cCLRQ) \ - TTL_74107A(name, cCLK, cJ, cK, cCLRQ) - -#define TTL_74107_DIP(name) \ - NET_REGISTER_DEV(TTL_74107_DIP, name) - -#endif - -#endif /* NLD_74107_H_ */ diff --git a/src/lib/netlist/devices/nld_74113.cpp b/src/lib/netlist/devices/nld_74113.cpp new file mode 100644 index 00000000000..32f96d87c12 --- /dev/null +++ b/src/lib/netlist/devices/nld_74113.cpp @@ -0,0 +1,142 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_74113.cpp + * + * 74113: Dual Master-Slave J-K Flip-Flops with Set and Complementary Outputs + * 74113A: Dual Negative-Edge-Triggered Master-Slave J-K Flip-Flops with Set and Complementary Outputs + * + * +----------+ + * 1CLK |1 ++ 14| VCC + * 1K |2 13| 2CLK + * 1J |3 12| 2K + * 1SETQ |4 74113 11| 2J + * 1Q |5 10| 2SETQ + * 1QQ |6 9| 2Q + * GND |7 8| 2QQ + * +----------+ + * + * + * Function table 113 + * + * +-----+-----+-----+---++---+-----+ + * | SETQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 1 | 0 | + * | 1 | * | 0 | 0 || Q0| Q0Q | + * | 1 | * | 1 | 0 || 1 | 0 | + * | 1 | * | 0 | 1 || 0 | 1 | + * | 1 | * | 1 | 1 || TOGGLE | + * +-----+-----+-----+---++---+-----+ + * _ + * * = _| |_ + * + * This is positive triggered, J and K + * are latched during clock high and + * transferred when CLK falls. + * + * Function table 113A + * + * +-----+-----+-----+---++---+-----+ + * | CLRQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 0 | 1 | + * | 1 | F | 0 | 0 || Q0| Q0Q | + * | 1 | F | 1 | 0 || 1 | 0 | + * | 1 | F | 0 | 1 || 0 | 1 | + * | 1 | F | 1 | 1 || TOGGLE | + * | 1 | 1 | X | X || Q0| Q0Q | + * +-----+-----+-----+---++---+-----+ + * + * THe 113A is negative triggered. + * + * Naming conventions follow Texas instruments datasheet + * + * FIXME: Currently, only the 113 is implemented. + * The 113A uses the same model. + * + */ + +#include "nl_base.h" + +// FIXME: this can probably be merged with nld_7473.cpp +// FIXME: timing, see 74107 for example, use template + +namespace netlist::devices { + + NETLIB_OBJECT(74113) + { + NETLIB_CONSTRUCTOR(74113) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs)) + , m_J(*this, "J", NETLIB_DELEGATE(inputs)) + , m_K(*this, "K", NETLIB_DELEGATE(inputs)) + , m_SETQ(*this, "SETQ", NETLIB_DELEGATE(inputs)) + , m_last_CLK(*this, "m_last_CLK", 0) + , m_q(*this, "m_q", 0) + , m_Q(*this, "Q") + , m_QQ(*this, "QQ") + , m_power_pins(*this) + { + } + + private: + NETLIB_RESETI() + { + m_last_CLK = 0; + } + + NETLIB_HANDLERI(inputs) + { + const auto JK = (m_J() << 1) | m_K(); + + if (m_SETQ()) + { + if (!m_CLK() && m_last_CLK) + { + switch (JK) + { + case 1: // (!m_J) & m_K)) + m_q = 0; + break; + case 2: // (m_J) & !m_K)) + m_q = 1; + break; + case 3: // (m_J) & m_K)) + m_q ^= 1; + break; + default: + case 0: + break; + } + } + } + else + { + m_q = 1; + } + + m_last_CLK = m_CLK(); + + m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing + m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing + } + + logic_input_t m_CLK; + logic_input_t m_J; + logic_input_t m_K; + logic_input_t m_SETQ; + + state_var<unsigned> m_last_CLK; + state_var<unsigned> m_q; + + logic_output_t m_Q; + logic_output_t m_QQ; + nld_power_pins m_power_pins; + }; + + using NETLIB_NAME(74113A) = NETLIB_NAME(74113); + + NETLIB_DEVICE_IMPL(74113, "TTL_74113", "+CLK,+J,+K,+CLRQ,@VCC,@GND") + NETLIB_DEVICE_IMPL(74113A, "TTL_74113A", "+CLK,+J,+K,+CLRQ,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp index 889ba019f78..fc0beef9972 100644 --- a/src/lib/netlist/devices/nld_74123.cpp +++ b/src/lib/netlist/devices/nld_74123.cpp @@ -1,72 +1,215 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74123.c + * nld_74123.cpp + * + * 74123: Dual Retriggerable One-Shot with Clear and Complementary Outputs + * + * +--------------+ + * A1 |1 ++ 16| VCC + * B1 |2 15| RC1 + * CLR1 |3 14| C1 + * Q1Q |4 74123 13| Q1 + * Q2 |5 12| Q2Q + * C2 |6 11| CLR2 + * RC2 |7 10| B2 + * GND |8 9| A2 + * +--------------+ + * + * Naming conventions follow Fairchild Semiconductor datasheet + * + * DM9602: Dual Retriggerable, Resettable One Shots + * + * +--------------+ + * C1 |1 ++ 16| VCC + * RC1 |2 15| C2 + * CLR1 |3 14| RC2 + * B1 |4 9602 13| CLR2 + * A1 |5 12| B2 + * Q1 |6 11| A2 + * Q1Q |7 10| Q2 + * GND |8 9| Q2Q + * +--------------+ + * + * CD4538: Dual Retriggerable, Resettable One Shots + * + * +--------------+ + * C1 |1 ++ 16| VCC + * RC1 |2 15| C2 + * CLR1 |3 14| RC2 + * A1 |4 4538 13| CLR2 + * B1 |5 12| A2 + * Q1 |6 11| B2 + * Q1Q |7 10| Q2 + * GND |8 9| Q2Q + * +--------------+ * */ +#include "analog/nlid_twoterm.h" #include "nlid_system.h" -#include "netlist/analog/nlid_twoterm.h" - -#include <cmath> -namespace netlist -{ - namespace devices +namespace netlist::devices { + + /// \brief Base monostable device + /// + /// The basic operation is the following: + /// + /// After a trigger signal has been detected, the output changes to high. + /// The capacitor is quickly discharged until it reaches Vlow. + /// The device toggles into charging mode until Vhigh is reached. At this + /// point, the output is set to low. Charging continues until VCC - or + /// more specific VRC is reached. + /// + /// Using + /// + /// - Vlow = alpha * VCC + /// - Vhigh = (1-alpha) * VCC + /// - Ignoring Rext during discharge + /// + /// we have calculate the following time constants: + /// + /// - tD = - X*C * ln(alpha) + /// - tC = - R*C * ln(alhpa) + /// - tL = - R*C * ln(1.0 - alpha) + /// + /// where tD denotes the time to discharge from VCC to Vlow, tC denotes + /// the time to charge from 0.0 to Vhigh and tL denotes the time to charge + /// from 0 to Vlow. X denotes the internal resistance used to discharge the + /// capacitor. The total impulse duration is thus + /// + /// tP = tD + tC - tL + /// + /// Using K = ln(1 - alpha) - ln (alpha) = ln(1/alpha - 1) + /// + /// we get + /// + /// tP = R*C*K * (1 + X/R * ln(alpha) / K) + /// + /// and alpha = 1 / (1 + exp(K)) + /// + /// Datasheets express the right term usually as + /// + /// (1 + f * 1000 / R) = (1 + X/R * ln(alpha) / K) + /// + /// and thus + /// + /// X = f * 1000 * K / ln(alpha) + /// + /// FIXME: Currently X is given directly (as RI). It would be better to use + /// f (usually 0.7) and K to calculate X. + /// + template <typename D> + NETLIB_OBJECT(74123_base) { - NETLIB_OBJECT(74123) - { - NETLIB_CONSTRUCTOR_EX(74123, int dev_type = 74123) - , m_dev_type(dev_type) + NETLIB_CONSTRUCTOR(74123_base) , m_RP(*this, "RP") , m_RN(*this, "RN") , m_RP_Q(*this, "_RP_Q") , m_RN_Q(*this, "_RN_Q") - , m_A(*this, "A") - , m_B(*this, "B") - , m_CLRQ(*this, "CLRQ") + , m_I(*this, D::names(), NETLIB_DELEGATE(ab_clear)) , m_Q(*this, "Q") , m_QQ(*this, "QQ") - , m_CV(*this, "_CV") // internal + , m_CV(*this, "_CV", NETLIB_DELEGATE(cv)) // internal , m_last_trig(*this, "m_last_trig", 0) , m_state(*this, "m_state", 0) - , m_KP(*this, "m_KP", 0) - , m_K(*this, "K", (m_dev_type == 4538) ? 1.0 : 0.4) // CD4538 datasheet states PW=RC - , m_RI(*this, "RI", 400.0) // around 250 for HC series, 400 on LS/TTL, estimated from datasheets + , m_KP(plib::reciprocal(nlconst::one() + plib::exp(D::K()))) + //, m_power_pins(*this) { - if ((m_dev_type != 9602) && (m_dev_type != 4538) ) - m_dev_type = 74123; - register_subalias("GND", m_RN.m_R.m_N); - register_subalias("VCC", m_RP.m_R.m_P); - register_subalias("C", m_RN.m_R.m_N); - register_subalias("RC", m_RN.m_R.m_P); + register_sub_alias(pstring(D::gnd()), "RN.2"); + register_sub_alias(pstring(D::vcc()), "RP.1"); + register_sub_alias("C", "RN.2"); + register_sub_alias("RC", "RN.1"); - connect(m_RP_Q, m_RP.m_I); - connect(m_RN_Q, m_RN.m_I); + connect("_RP_Q", "RP.I"); + connect("_RN_Q", "RN.I"); - connect(m_RN.m_R.m_P, m_RP.m_R.m_N); - connect(m_CV, m_RN.m_R.m_P); + connect("RN.1", "RP.2"); + connect("_CV", "RN.1"); - m_RP.m_RON.setTo(m_RI()); - m_RN.m_RON.setTo(m_RI()); + m_RP().m_RON.set(D::RI()); + m_RN().m_RON.set(D::RI()); } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_HANDLERI(ab_clear) + { + netlist_sig_t m_trig(0); + + m_trig = D::trigfunc(m_I); + + if (!D::clear(m_I)) + { + m_Q.push(0, D::t_C_to_Q::value()); + m_QQ.push(1, D::t_C_to_Q::value()); + /* quick charge until trigger */ + /* FIXME: SGS datasheet shows quick charge to 5V, + * though schematics indicate quick charge to Vhigh only. + */ + m_RP_Q.push(1, D::t_C_to_Q::value()); // R_ON + m_RN_Q.push(0, D::t_C_to_Q::value()); // R_OFF + m_state = 2; //charging (quick) + } + else if (!m_last_trig && m_trig) + { + // FIXME: Timing! + m_Q.push(1, D::t_AB_to_Q::value()); + m_QQ.push(0, D::t_AB_to_Q::value()); + + m_RN_Q.push(1, D::t_AB_to_Q::value()); // R_ON + m_RP_Q.push(0, D::t_AB_to_Q::value()); // R_OFF + + m_state = 1; // discharging + } + + m_last_trig = m_trig; + } + + NETLIB_HANDLERI(cv) + { + if (m_state == 1) + { + const nl_fptype vLow = m_KP * m_RP().P()(); + if (m_CV() < vLow) + { + m_RN_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF + m_state = 2; // charging + } + } + if (m_state == 2) + { + const nl_fptype vHigh = (nlconst::one() - m_KP) * m_RP().P()(); + if (m_CV() > vHigh) + { + m_RP_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF + + m_Q.push(0, NLTIME_FROM_NS(10)); + m_QQ.push(1, NLTIME_FROM_NS(10)); + m_state = 0; // waiting + } + } + } + + NETLIB_RESETI() + { + m_RP().reset(); + m_RN().reset(); + + //m_RP.set_R(R_OFF); + //m_RN.set_R(R_OFF); + + m_last_trig = 0; + m_state = 0; + } private: - int m_dev_type; - public: - NETLIB_SUB(res_sw) m_RP; - NETLIB_SUB(res_sw) m_RN; + NETLIB_SUB(sys_dsw1) m_RP; + NETLIB_SUB(sys_dsw1) m_RN; logic_output_t m_RP_Q; logic_output_t m_RN_Q; - logic_input_t m_A; - logic_input_t m_B; - logic_input_t m_CLRQ; + object_array_t<logic_input_t, 3> m_I; logic_output_t m_Q; logic_output_t m_QQ; @@ -74,242 +217,74 @@ namespace netlist state_var<netlist_sig_t> m_last_trig; state_var<unsigned> m_state; - state_var<double> m_KP; - - param_double_t m_K; - param_double_t m_RI; + nl_fptype m_KP; + //nld_power_pins m_power_pins; // not needed, device exposes VCC and GND }; - NETLIB_OBJECT(74123_dip) + struct desc_74123 : public desc_base { - NETLIB_CONSTRUCTOR(74123_dip) - , m_A(*this, "A", 74123) - , m_B(*this, "B", 74123) + using t_AB_to_Q = time_ns<10>; + using t_C_to_Q = time_ns<10>; + static constexpr nl_fptype K() { return nlconst::magic(0.4); } + static constexpr nl_fptype RI() { return nlconst::magic(400.0); } + + static constexpr std::array<const char *, 3> names() { return {"CLRQ", "A", "B"};} + template<typename T> + static netlist_sig_t trigfunc(const T &in) { - register_subalias("1", m_A.m_A); - register_subalias("2", m_A.m_B); - register_subalias("3", m_A.m_CLRQ); - register_subalias("4", m_A.m_QQ); - register_subalias("5", m_B.m_Q); - register_subalias("6", m_B.m_RN.m_R.m_N); - register_subalias("7", m_B.m_RN.m_R.m_P); - register_subalias("8", m_A.m_RN.m_R.m_N); - connect(m_A.m_RN.m_R.m_N, m_B.m_RN.m_R.m_N); - - register_subalias("9", m_B.m_A); - register_subalias("10", m_B.m_B); - register_subalias("11", m_B.m_CLRQ); - register_subalias("12", m_B.m_QQ); - register_subalias("13", m_A.m_Q); - register_subalias("14", m_A.m_RN.m_R.m_N); - register_subalias("15", m_A.m_RN.m_R.m_P); - register_subalias("16", m_A.m_RP.m_R.m_P); - connect(m_A.m_RP.m_R.m_P, m_B.m_RP.m_R.m_P); + return ((in[1]() | (in[2]() ^ 1)) ^ 1) & in[0](); // ((m_A() | (m_B() ^ 1)) ^ 1) & m_CLRQ() } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - private: - NETLIB_SUB(74123) m_A; - NETLIB_SUB(74123) m_B; + template<typename T> static constexpr netlist_sig_t clear(const T &in) { return in[0]();} + + static constexpr const char *vcc() { return "VCC"; } + static constexpr const char *gnd() { return "GND"; } }; - NETLIB_OBJECT(9602_dip) + struct desc_74121 : public desc_74123 { - NETLIB_CONSTRUCTOR(9602_dip) - , m_A(*this, "A", 9602) - , m_B(*this, "B", 9602) + static constexpr nl_fptype K() { return nlconst::magic(0.7); } + + static constexpr std::array<const char *, 3> names() { return {"A1", "A2", "B"};} + template<typename T> + static netlist_sig_t trigfunc(const T &in) { - register_subalias("1", m_A.m_RN.m_R.m_N); // C1 - register_subalias("2", m_A.m_RN.m_R.m_P); // RC1 - register_subalias("3", m_A.m_CLRQ); - register_subalias("4", m_A.m_B); - register_subalias("5", m_A.m_A); - register_subalias("6", m_A.m_Q); - register_subalias("7", m_A.m_QQ); - register_subalias("8", m_A.m_RN.m_R.m_N); - connect(m_A.m_RN.m_R.m_N, m_B.m_RN.m_R.m_N); - - register_subalias("9", m_B.m_QQ); - register_subalias("10", m_B.m_Q); - register_subalias("11", m_B.m_A); - register_subalias("12", m_B.m_B); - register_subalias("13", m_B.m_CLRQ); - register_subalias("14", m_B.m_RN.m_R.m_P); // RC2 - register_subalias("15", m_B.m_RN.m_R.m_N); // C2 - register_subalias("16", m_A.m_RP.m_R.m_P); - connect(m_A.m_RP.m_R.m_P, m_B.m_RP.m_R.m_P); + return ((in[0]() ^ 1) | (in[1]() ^ 1)) & in[2](); // (~A1 | ~A2) & B } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - private: - NETLIB_SUB(74123) m_A; - NETLIB_SUB(74123) m_B; + template<typename T> static constexpr netlist_sig_t clear([[maybe_unused]] const T &in) { return 1; } }; - NETLIB_OBJECT(4538_dip) + struct desc_9602 : public desc_74123 { - NETLIB_CONSTRUCTOR(4538_dip) - NETLIB_FAMILY("CD4XXX") - , m_A(*this, "A", 4538) - , m_B(*this, "B", 4538) + template<typename T> + static netlist_sig_t trigfunc(const T &in) { - register_subalias("1", m_A.m_RN.m_R.m_N); // C1 - register_subalias("2", m_A.m_RN.m_R.m_P); // RC1 - register_subalias("3", m_A.m_CLRQ); - register_subalias("4", m_A.m_A); - register_subalias("5", m_A.m_B); - register_subalias("6", m_A.m_Q); - register_subalias("7", m_A.m_QQ); - register_subalias("8", m_A.m_RN.m_R.m_N); - connect(m_A.m_RN.m_R.m_N, m_B.m_RN.m_R.m_N); - - register_subalias("9", m_B.m_QQ); - register_subalias("10", m_B.m_Q); - register_subalias("11", m_B.m_B); - register_subalias("12", m_B.m_A); - register_subalias("13", m_B.m_CLRQ); - register_subalias("14", m_B.m_RN.m_R.m_P); // RC2 - register_subalias("15", m_B.m_RN.m_R.m_N); // C2 - register_subalias("16", m_A.m_RP.m_R.m_P); - connect(m_A.m_RP.m_R.m_P, m_B.m_RP.m_R.m_P); + return ((in[1]() ^ 1) | in[2]()); // (m_A() ^ 1) | m_B() } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - private: - NETLIB_SUB(74123) m_A; - NETLIB_SUB(74123) m_B; }; - NETLIB_UPDATE(74123) + struct desc_4538 : public desc_74123 { - netlist_sig_t m_trig; - netlist_sig_t res = !m_CLRQ(); - netlist_time t_AB_to_Q = NLTIME_FROM_NS(10); - netlist_time t_C_to_Q = NLTIME_FROM_NS(10); + using t_AB_to_Q = time_ns<300>; + using t_C_to_Q = time_ns<250>; + static constexpr nl_fptype K() { return nlconst::one(); } // CD4538 datasheet states PW=RC - if (m_dev_type == 74123) + template<typename T> + static netlist_sig_t trigfunc(const T &in) { - m_trig = (m_A() ^ 1) & m_B() & m_CLRQ(); + return (in[1]() | (in[2]() ^ 1)); // m_A() | (m_B() ^ 1) } - else if (m_dev_type == 9602) - { - m_trig = (m_A() ^ 1) | m_B(); - } - else // 4538 - { - m_trig = (m_B() ^ 1) | m_A(); - // The line below is from the datasheet truthtable ... doesn't make sense at all - //res = res | m_A) | (m_B) ^ 1); - t_AB_to_Q = NLTIME_FROM_NS(300); - t_C_to_Q = NLTIME_FROM_NS(250); - } - - if (res) - { - m_Q.push(0, t_C_to_Q); - m_QQ.push(1, t_C_to_Q); - /* quick charge until trigger */ - /* FIXME: SGS datasheet shows quick charge to 5V, - * though schematics indicate quick charge to Vhigh only. - */ - m_RP_Q.push(1, t_C_to_Q); // R_ON - m_RN_Q.push(0, t_C_to_Q); // R_OFF - m_state = 2; //charging (quick) - } - else if (!m_last_trig && m_trig) - { - // FIXME: Timing! - m_Q.push(1, t_AB_to_Q); - m_QQ.push(0,t_AB_to_Q); - - m_RN_Q.push(1, t_AB_to_Q); // R_ON - m_RP_Q.push(0, t_AB_to_Q); // R_OFF - - m_state = 1; // discharging - } - - m_last_trig = m_trig; - - if (m_state == 1) - { - const nl_double vLow = m_KP * m_RP.m_R.m_P(); - if (m_CV() < vLow) - { - m_RN_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF - m_state = 2; // charging - } - } - if (m_state == 2) - { - const nl_double vHigh = m_RP.m_R.m_P() * (1.0 - m_KP); - if (m_CV() > vHigh) - { - m_RP_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF - - m_Q.push(0, NLTIME_FROM_NS(10)); - m_QQ.push(1, NLTIME_FROM_NS(10)); - m_state = 0; // waiting - } - } - } - - NETLIB_RESET(74123) - { - m_KP = 1.0 / (1.0 + exp(m_K())); - - m_RP.reset(); - m_RN.reset(); - - //m_RP.set_R(R_OFF); - //m_RN.set_R(R_OFF); - - m_last_trig = 0; - m_state = 0; - } - - NETLIB_UPDATE(74123_dip) - { - /* only called during startup */ - //_1.update_dev(); - //m_2.update_dev(); - } - - NETLIB_RESET(74123_dip) - { - //m_1.reset(); - //m_2.reset(); - } - - NETLIB_UPDATE(9602_dip) - { - /* only called during startup */ - //m_1.update_dev(); - //m_2.update_dev(); - } - - NETLIB_RESET(9602_dip) - { - //m_1.reset(); - //m_2.reset(); - } - - NETLIB_UPDATE(4538_dip) - { - /* only called during startup */ - //m_1.update_dev(); - //m_2.update_dev(); - } + static constexpr const char *vcc() { return "VDD"; } + static constexpr const char *gnd() { return "VSS"; } + }; - NETLIB_RESET(4538_dip) - { - m_A.reset(); - m_B.reset(); - } + using NETLIB_NAME(74123) = NETLIB_NAME(74123_base)<desc_74123>; + using NETLIB_NAME(74121) = NETLIB_NAME(74123_base)<desc_74121>; + using NETLIB_NAME(4538) = NETLIB_NAME(74123_base)<desc_4538>; + using NETLIB_NAME(9602) = NETLIB_NAME(74123_base)<desc_9602>; NETLIB_DEVICE_IMPL(74123, "TTL_74123", "") - NETLIB_DEVICE_IMPL(74123_dip, "TTL_74123_DIP", "") - NETLIB_DEVICE_IMPL(4538_dip, "CD4538_DIP", "") - NETLIB_DEVICE_IMPL(9602_dip, "TTL_9602_DIP", "") + NETLIB_DEVICE_IMPL(74121, "TTL_74121", "") + NETLIB_DEVICE_IMPL(4538, "CD4538", "") + NETLIB_DEVICE_IMPL(9602, "TTL_9602", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74123.h b/src/lib/netlist/devices/nld_74123.h deleted file mode 100644 index 3eca141b613..00000000000 --- a/src/lib/netlist/devices/nld_74123.h +++ /dev/null @@ -1,74 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74123.h - * - * 74123: Dual Retriggerable One-Shot with Clear and Complementary Outputs - * - * +--------------+ - * A1 |1 ++ 16| VCC - * B1 |2 15| RC1 - * CLR1 |3 14| C1 - * Q1Q |4 74123 13| Q1 - * Q2 |5 12| Q2Q - * C2 |6 11| CLR2 - * RC2 |7 10| B2 - * GND |8 9| A2 - * +--------------+ - * - * Naming conventions follow Fairchild Semiconductor datasheet - * - * DM9602: Dual Retriggerable, Resettable One Shots - * - * +--------------+ - * C1 |1 ++ 16| VCC - * RC1 |2 15| C2 - * CLR1 |3 14| RC2 - * B1 |4 9602 13| CLR2 - * A1 |5 12| B2 - * Q1 |6 11| A2 - * Q1Q |7 10| Q2 - * GND |8 9| Q2Q - * +--------------+ - * - * CD4538: Dual Retriggerable, Resettable One Shots - * - * +--------------+ - * C1 |1 ++ 16| VCC - * RC1 |2 15| C2 - * CLR1 |3 14| RC2 - * A1 |4 4538 13| CLR2 - * B1 |5 12| A2 - * Q1 |6 11| B2 - * Q1Q |7 10| Q2 - * GND |8 9| Q2Q - * +--------------+ - * - */ - -#ifndef NLD_74123_H_ -#define NLD_74123_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74123(name) \ - NET_REGISTER_DEV(TTL_74123, name) - -#define TTL_74123_DIP(name) \ - NET_REGISTER_DEV(TTL_74123_DIP, name) - -/* The 9602 is very similar to the 123. Input triggering is slightly different - * The 9602 uses an OR gate instead of an AND gate. - */ - -#define TTL_9602_DIP(name) \ - NET_REGISTER_DEV(TTL_9602_DIP, name) - -/* - * The CD4538 is pretty similar to the 9602 - */ - -#define CD4538_DIP(name) \ - NET_REGISTER_DEV(CD4538_DIP, name) - -#endif /* NLD_74123_H_ */ diff --git a/src/lib/netlist/devices/nld_74125.cpp b/src/lib/netlist/devices/nld_74125.cpp new file mode 100644 index 00000000000..aca9f4175e2 --- /dev/null +++ b/src/lib/netlist/devices/nld_74125.cpp @@ -0,0 +1,77 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_74125.cpp + * + */ + +#include "nl_base.h" + +#include <type_traits> + +namespace netlist::devices { + + template <typename D> + NETLIB_OBJECT(74125_base) + { + NETLIB_CONSTRUCTOR(74125_base) + , m_TE(*this, "FORCE_TRISTATE_LOGIC", 0) + , m_A(*this, "A", NETLIB_DELEGATE(A)) + , m_G(*this, pstring(D::invert_g::value ? "G" : "GQ"), NETLIB_DELEGATE(G)) + , m_Y(*this, "Y", m_TE()) + //, m_Y(*this, "Y") + , m_power_pins(*this) + { + } + + private: + //NETLIB_RESETI() {} + + NETLIB_UPDATE_PARAMI() + { + // this one is only called during startup. Ensure all outputs + // are in a consistent state. + m_Y.set_tristate(m_G() ^ D::invert_g::value, + D::ts_off_on::value(), D::ts_on_off::value()); + m_Y.push(m_A(), m_A() ? D::sig_off_on::value() : D::sig_on_off::value()); + } + + NETLIB_HANDLERI(A) + { + m_Y.push(m_A(), m_A() ? D::sig_off_on::value() : D::sig_on_off::value()); + } + + NETLIB_HANDLERI(G) + { + m_Y.set_tristate(m_G() ^ D::invert_g::value, + D::ts_off_on::value(), D::ts_on_off::value()); + } + + param_logic_t m_TE; + logic_input_t m_A; + logic_input_t m_G; + tristate_output_t m_Y; + nld_power_pins m_power_pins; + }; + + struct desc_74125 : public desc_base + { + using invert_g = desc_const<0>; + using ts_off_on = time_ns<11>; + using ts_on_off = time_ns<13>; + using sig_off_on = time_ns<8>; + using sig_on_off = time_ns<12>; + }; + + struct desc_74126 : public desc_74125 + { + using invert_g = desc_const<1>; + }; + + using NETLIB_NAME(74125) = NETLIB_NAME(74125_base)<desc_74125>; + using NETLIB_NAME(74126) = NETLIB_NAME(74125_base)<desc_74126>; + + NETLIB_DEVICE_IMPL(74125, "TTL_74125_GATE", "") + NETLIB_DEVICE_IMPL(74126, "TTL_74126_GATE", "") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74153.cpp b/src/lib/netlist/devices/nld_74153.cpp index ce2e25cb3f3..c68a8537811 100644 --- a/src/lib/netlist/devices/nld_74153.cpp +++ b/src/lib/netlist/devices/nld_74153.cpp @@ -1,43 +1,75 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74153.c + * nld_74153.cpp + * + * DM74153: Dual 4-Line to 1-Line Data Selectors Multiplexers + * + * +--------------+ + * G1 |1 ++ 16| VCC + * B |2 15| G2 + * 1C3 |3 14| A + * 1C2 |4 74153 13| 2C3 + * 1C1 |5 12| 2C2 + * 1C0 |6 11| 2C1 + * Y1 |7 10| 2C0 + * GND |8 9| Y2 + * +--------------+ + * + * + * Function table + * + * +-----+-----++----+----+----+----++----+----+ + * | B | A || C0 | C1 | C2 | C3 || G | Y | + * +=====+=====++====+====+====+====++====+====+ + * | X | X || X | X | X | X || H | L | + * | L | L || L | X | X | X || L | L | + * | L | L || H | X | X | X || L | H | + * | L | H || X | L | X | X || L | L | + * | L | H || X | H | X | X || L | H | + * | H | L || X | X | L | X || L | L | + * | H | L || X | X | H | X || L | H | + * | H | H || X | X | X | L || L | L | + * | H | H || X | X | X | H || L | H | + * +-----+-----++----+----+----+----++----+----+ + * + * A, B : Select Inputs + * C* : Data inputs + * G : Strobe + * Y : Output + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_74153.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ -namespace devices -{ +namespace netlist::devices { - /* FIXME: timing is not 100% accurate, Strobe and Select inputs have a - * slightly longer timing. - * Convert this to sub-devices at some time. - */ + // FIXME: timing is not 100% accurate, Strobe and Select inputs have a + // slightly longer timing . + // FIXME: Truth table candidate NETLIB_OBJECT(74153) { NETLIB_CONSTRUCTOR(74153) - , m_C(*this, {{"C0", "C1", "C2", "C3"}}, NETLIB_DELEGATE(74153, sub)) - , m_G(*this, "G", NETLIB_DELEGATE(74153, sub)) + , m_C(*this, {"C0", "C1", "C2", "C3"}, NETLIB_DELEGATE(sub)) + , m_G(*this, "G", NETLIB_DELEGATE(sub)) , m_Y(*this, "AY") //FIXME: Change netlists , m_chan(*this, "m_chan", 0) - , m_A(*this, "A") - , m_B(*this, "B") + , m_A(*this, "A", NETLIB_DELEGATE(other)) + , m_B(*this, "B", NETLIB_DELEGATE(other)) , m_power_pins(*this) { } + private: NETLIB_RESETI() { m_chan = 0; } - NETLIB_UPDATEI() + NETLIB_HANDLERI(other) { m_chan = (m_A() | (m_B()<<1)); sub(); @@ -45,7 +77,7 @@ namespace devices NETLIB_HANDLERI(sub) { - constexpr const netlist_time delay[2] = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) }; + constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) }; if (!m_G()) { auto t = m_C[m_chan](); @@ -57,7 +89,6 @@ namespace devices } } - public: object_array_t<logic_input_t, 4> m_C; logic_input_t m_G; @@ -71,46 +102,6 @@ namespace devices nld_power_pins m_power_pins; }; - NETLIB_OBJECT(74153_dip) - { - NETLIB_CONSTRUCTOR(74153_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", m_A.m_G); - register_subalias("2", m_A.m_B); - register_subalias("3", m_A.m_C[3]); - register_subalias("4", m_A.m_C[2]); - register_subalias("5", m_A.m_C[1]); - register_subalias("6", m_A.m_C[0]); - register_subalias("7", m_A.m_Y); - register_subalias("8", "A.GND"); - - register_subalias("9", m_B.m_Y); - register_subalias("10", m_B.m_C[0]); - register_subalias("11", m_B.m_C[1]); - register_subalias("12", m_B.m_C[2]); - register_subalias("13", m_B.m_C[3]); - register_subalias("14", m_A.m_A); - - register_subalias("15", m_B.m_G); - register_subalias("16", "A.VCC"); - - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - connect(m_A.m_A, m_B.m_A); - connect(m_A.m_B, m_B.m_B); - } - //NETLIB_RESETI(); - //NETLIB_UPDATEI(); - - protected: - NETLIB_SUB(74153) m_A; - NETLIB_SUB(74153) m_B; - }; - NETLIB_DEVICE_IMPL(74153, "TTL_74153", "+C0,+C1,+C2,+C3,+A,+B,+G,@VCC,@GND") - NETLIB_DEVICE_IMPL(74153_dip, "TTL_74153_DIP", "") -} //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74153.h b/src/lib/netlist/devices/nld_74153.h deleted file mode 100644 index 996ca5931af..00000000000 --- a/src/lib/netlist/devices/nld_74153.h +++ /dev/null @@ -1,65 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74153.h - * - * DM74153: Dual 4-Line to 1-Line Data Selectors Multiplexers - * - * +--------------+ - * G1 |1 ++ 16| VCC - * B |2 15| G2 - * 1C3 |3 14| A - * 1C2 |4 74153 13| 2C3 - * 1C1 |5 12| 2C2 - * 1C0 |6 11| 2C1 - * Y1 |7 10| 2C0 - * GND |8 9| Y2 - * +--------------+ - * - * - * Function table - * - * +-----+-----++----+----+----+----++----+----+ - * | B | A || C0 | C1 | C2 | C3 || G | Y | - * +=====+=====++====+====+====+====++====+====+ - * | X | X || X | X | X | X || H | L | - * | L | L || L | X | X | X || L | L | - * | L | L || H | X | X | X || L | H | - * | L | H || X | L | X | X || L | L | - * | L | H || X | H | X | X || L | H | - * | H | L || X | X | L | X || L | L | - * | H | L || X | X | H | X || L | H | - * | H | H || X | X | X | L || L | L | - * | H | H || X | X | X | H || L | H | - * +-----+-----++----+----+----+----++----+----+ - * - * A, B : Select Inputs - * C* : Data inputs - * G : Strobe - * Y : Output - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74153_H_ -#define NLD_74153_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74153(name, cC0, cC1, cC2, cC3, cA, cB, cG) \ - NET_REGISTER_DEV(TTL_74153, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, C0, cC0) \ - NET_CONNECT(name, C1, cC1) \ - NET_CONNECT(name, C2, cC2) \ - NET_CONNECT(name, C3, cC3) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, G, cG) - -#define TTL_74153_DIP(name) \ - NET_REGISTER_DEV(TTL_74153_DIP, name) - -#endif /* NLD_74153_H_ */ diff --git a/src/lib/netlist/devices/nld_74161.cpp b/src/lib/netlist/devices/nld_74161.cpp index ae58a43feba..357746d102f 100644 --- a/src/lib/netlist/devices/nld_74161.cpp +++ b/src/lib/netlist/devices/nld_74161.cpp @@ -1,141 +1,26 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Couriersud /* * nld_74161.cpp * */ -#include "nld_74161.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" +#include "nl_factory.h" -#include <array> +#include "nld_9316_base.hxx" -namespace netlist -{ - namespace devices - { +// FIXME: All detail can be found in nld_9316_base.hxx +// At least gcc-7.x needs the implementations of the base device +// in different compilation units. If created in the same file +// performance degrades horrible. - static constexpr const unsigned MAXCNT = 15; +// FIXME: this file could be created programmatically - NETLIB_OBJECT(74161) - { - NETLIB_CONSTRUCTOR(74161) - , m_A(*this, "A") - , m_B(*this, "B") - , m_C(*this, "C") - , m_D(*this, "D") - , m_CLRQ(*this, "CLRQ") - , m_LOADQ(*this, "LOADQ") - , m_CLK(*this, "CLK") - , m_ENABLEP(*this, "ENABLEP") - , m_ENABLET(*this, "ENABLET") - , m_cnt(*this, "m_cnt", 0) - , m_last_CLK(*this, "m_last_CLK", 0) - , m_Q(*this, {{"QA", "QB", "QC", "QD"}}) - , m_RCO(*this, "RCO") - , m_power_pins(*this) - { - } +namespace netlist::devices { - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_DEVICE_IMPL(74161, "TTL_74161", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D,@VCC,@GND") + // FIXME: This happens on copy/paste + NETLIB_DEVICE_IMPL(74161_fixme, "TTL_74161_FIXME", "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENP,+ENT,@VCC,@GND") - protected: - logic_input_t m_A; - logic_input_t m_B; - logic_input_t m_C; - logic_input_t m_D; - logic_input_t m_CLRQ; - logic_input_t m_LOADQ; - logic_input_t m_CLK; - logic_input_t m_ENABLEP; - logic_input_t m_ENABLET; - - state_var<unsigned> m_cnt; - state_var<unsigned> m_last_CLK; - - object_array_t<logic_output_t, 4> m_Q; - logic_output_t m_RCO; - - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(74161_dip, 74161) - { - NETLIB_CONSTRUCTOR_DERIVED(74161_dip, 74161) - { - register_subalias("1", m_CLRQ); - register_subalias("2", m_CLK); - register_subalias("3", m_A); - register_subalias("4", m_B); - register_subalias("5", m_C); - register_subalias("6", m_D); - register_subalias("7", m_ENABLEP); - register_subalias("8", "GND"); - - register_subalias("9", m_LOADQ); - register_subalias("10", m_ENABLET); - register_subalias("11", m_Q[3]); - register_subalias("12", m_Q[2]); - register_subalias("13", m_Q[1]); - register_subalias("14", m_Q[0]); - register_subalias("15", m_RCO); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_RESET(74161) - { - m_cnt = 0; - m_last_CLK = 0; - } - - // FIXME: Timing - static constexpr const std::array<netlist_time, 4> delay = - { - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40) - }; - - NETLIB_UPDATE(74161) - { - netlist_sig_t tRippleCarryOut = 0; - if (!m_CLRQ()) - { - m_cnt = 0; - } - else if (m_CLK() && !m_last_CLK) - { - if (!m_LOADQ()) - { - m_cnt = (m_D() << 3) | (m_C() << 2) - | (m_B() << 1) | (m_A() << 0); - } - else if (m_ENABLET() && m_ENABLEP()) - { - ++m_cnt &= MAXCNT; - } - } - - if (m_ENABLET() && (m_cnt == MAXCNT)) - { - tRippleCarryOut = 1; - } - - m_last_CLK = m_CLK(); - - for (std::size_t i=0; i<4; i++) - m_Q[i].push((m_cnt >> i) & 1, delay[i]); - - m_RCO.push(tRippleCarryOut, NLTIME_FROM_NS(20)); //FIXME - } - - NETLIB_DEVICE_IMPL(74161, "TTL_74161", "+A,+B,+C,+D,+CLRQ,+LOADQ,+CLK,+ENABLEP,+ENABLET,@VCC,@GND") - NETLIB_DEVICE_IMPL(74161_dip, "TTL_74161_DIP", "") - - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74161.h b/src/lib/netlist/devices/nld_74161.h deleted file mode 100644 index 91025446891..00000000000 --- a/src/lib/netlist/devices/nld_74161.h +++ /dev/null @@ -1,47 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_74161.h - * - * DM74161: Synchronous 4-Bit Binary Counter with Clock - * - * +--------------+ - * CLEAR |1 ++ 16| VCC - * CLK |2 15| RCO - * A |3 14| QA - * B |4 74161 13| QB - * C |5 12| QC - * D |6 11| QD - * ENABLEP |7 10| ENABLET - * GND |8 9| LOAD - * +--------------+ - * - * RCO: Ripple carry output - * - * Naming convention attempts to follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74161_H_ -#define NLD_74161_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74161(name, cA, cB, cC, cD, cCLRQ, cLOADQ, cCLK, cENABLEP, cENABLET) \ - NET_REGISTER_DEV(TTL_74161, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, CLRQ, cCLRQ) \ - NET_CONNECT(name, LOADQ, cLOADQ) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, ENABLEP, cENABLEP) \ - NET_CONNECT(name, ENABLET, cENABLET) - -#define TTL_74161_DIP(name) \ - NET_REGISTER_DEV(TTL_74161_DIP, name) - -#endif /* NLD_74161_H_ */ diff --git a/src/lib/netlist/devices/nld_74163.cpp b/src/lib/netlist/devices/nld_74163.cpp new file mode 100644 index 00000000000..5044b0aa7c4 --- /dev/null +++ b/src/lib/netlist/devices/nld_74163.cpp @@ -0,0 +1,24 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_74163.cpp + * + */ + +#include "nl_base.h" +#include "nl_factory.h" + +#include "nld_9316_base.hxx" + +// FIXME: All detail can be found in nld_9316_base.hxx +// At least gcc-7.x needs the implementations of the base device +// in different compilation units. If created in the same file +// performance degrades horrible. + +// FIXME: this file could be created programmatically + +namespace netlist::devices { + + NETLIB_DEVICE_IMPL(74163, "TTL_74163", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74164.cpp b/src/lib/netlist/devices/nld_74164.cpp index ed401603181..878e333df0f 100644 --- a/src/lib/netlist/devices/nld_74164.cpp +++ b/src/lib/netlist/devices/nld_74164.cpp @@ -7,106 +7,110 @@ * implementing this was simple. * */ +/***************************************************************************** + + 5/74164 8-bit parallel-out serial shift registers + +*********************************************************************** + + Connection Diagram: + ___ ___ + A 1 |* u | 14 Vcc + B 2 | | 13 QH + QA 3 | | 12 QG + QB 4 | | 11 QF + QC 5 | | 10 QE + QD 6 | | 9 *Clear + GND 7 |_______| 8 Clock + +*********************************************************************** + Function Table: + +-------------------------+----------------+ + | Inputs | Outputs* | + +-------+-------+---------+----------------+ + | Clear | Clock | A B | QA QB ... QH | + +-------+-------+---------+----------------+ + | L | X | X X | L L L | + | H | L | X X | QA0 QB0 QH0 | + | H | ^ | H H | H QAn QGn | + | H | ^ | L X | L QAn QGn | + | H | ^ | X L | L QAn QGn | + +-------+-------+---------+----------------+ + + H = High Level (steady state) + L = Low Level (steady state) + X = Don't Care + ^ = Transition from low to high level + QA0, QB0 ... QH0 = The level of QA, QB ... QH before the indicated steady-state input conditions were established. + QAn, QGn = The level of QA or QG before the most recent ^ transition of the clock; indicates a 1 bit shift. + +**********************************************************************/ + +#include "nl_base.h" + +// FIXME: clk input to be separated - only falling edge relevant + +namespace netlist::devices { -#include "nld_74164.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(74164) { NETLIB_CONSTRUCTOR(74164) - , m_A(*this, "A") - , m_B(*this, "B") - , m_CLRQ(*this, "CLRQ") - , m_CLK(*this, "CLK") + , m_AB(*this, {"A", "B"}, NETLIB_DELEGATE(ab)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(clrq)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) , m_cnt(*this, "m_cnt", 0) - , m_last_CLK(*this, "m_last_CLK", 0) - , m_Q(*this, {{"QA", "QB", "QC", "QD", "QE", "QF", "QG", "QH"}}) + , m_ab(*this, "m_ab", 0) + , m_Q(*this, {"QA", "QB", "QC", "QD", "QE", "QF", "QG", "QH"}) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - protected: - logic_input_t m_A; - logic_input_t m_B; - logic_input_t m_CLRQ; - logic_input_t m_CLK; - - state_var<unsigned> m_cnt; - state_var<unsigned> m_last_CLK; - - object_array_t<logic_output_t, 8> m_Q; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(74164_dip, 74164) - { - NETLIB_CONSTRUCTOR_DERIVED(74164_dip, 74164) - { - register_subalias("1", m_A); - register_subalias("2", m_B); - register_subalias("3", m_Q[0]); - register_subalias("4", m_Q[1]); - register_subalias("5", m_Q[2]); - register_subalias("6", m_Q[3]); - register_subalias("7", "A.GND"); - - register_subalias("8", m_CLK); - register_subalias("9", m_CLRQ); - register_subalias("10", m_Q[4]); - register_subalias("11", m_Q[5]); - register_subalias("12", m_Q[6]); - register_subalias("13", m_Q[7]); - register_subalias("14", "A.VCC"); - - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - - } - }; - - NETLIB_RESET(74164) - { - m_cnt = 0; - m_last_CLK = 0; - } - - NETLIB_UPDATE(74164) - { - if (!m_CLRQ()) + private: + NETLIB_RESETI() { + m_CLK.set_state(logic_t::STATE_INP_LH); m_cnt = 0; } - else if (m_CLK() && !m_last_CLK) + + NETLIB_HANDLERI(clrq) { - m_cnt = (m_cnt << 1) & 0xfe; - if (m_A() && m_B()) + if (m_CLRQ()) { - m_cnt |= 0x01; + m_CLK.activate_lh(); } else { - m_cnt &= 0xfe; + m_CLK.inactivate(); + if (m_cnt != 0) + { + m_cnt = 0; + m_Q.push(0, NLTIME_FROM_NS(30)); + } } } - m_last_CLK = m_CLK(); + NETLIB_HANDLERI(clk) + { + m_cnt = (m_cnt << 1) | m_ab; + m_Q.push(m_cnt, NLTIME_FROM_NS(30)); + } - for (std::size_t i=0; i<8; i++) + NETLIB_HANDLERI(ab) { - m_Q[i].push((m_cnt >> i) & 1, NLTIME_FROM_NS(30)); + m_ab = static_cast<unsigned>((m_AB() == 3) ? 1 : 0); } - } + + object_array_t<logic_input_t, 2> m_AB; + logic_input_t m_CLRQ; + logic_input_t m_CLK; + + state_var<unsigned> m_cnt; + state_var<unsigned> m_ab; + + object_array_t<logic_output_t, 8> m_Q; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(74164, "TTL_74164", "+A,+B,+CLRQ,+CLK,@VCC,@GND") - NETLIB_DEVICE_IMPL(74164_dip, "TTL_74164_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74164.h b/src/lib/netlist/devices/nld_74164.h deleted file mode 100644 index 2efe339df2b..00000000000 --- a/src/lib/netlist/devices/nld_74164.h +++ /dev/null @@ -1,59 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Joakim Larsson Edstrom -/***************************************************************************** - - 5/74164 8-bit parallel-out serial shift registers - -*********************************************************************** - - Connection Diagram: - ___ ___ - A 1 |* u | 14 Vcc - B 2 | | 13 QH - QA 3 | | 12 QG - QB 4 | | 11 QF - QC 5 | | 10 QE - QD 6 | | 9 *Clear - GND 7 |_______| 8 Clock - -*********************************************************************** - Function Table: - +-------------------------+----------------+ - | Inputs | Qutputs* | - +-------+-------+---------+----------------+ - | Clear | Clock | A B | QA QB ... QH | - +-------+-------+---------+----------------+ - | L | X | X X | L L L | - | H | L | X X | QA0 QB0 QH0 | - | H | ^ | H H | H QAn QGn | - | H | ^ | L X | L QAn QGn | - | H | ^ | X L | L QAn QGn | - +-------+-------+---------+----------------+ - - H = High Level (steady state) - L = Low Level (steady state) - X = Don't Care - ^ = Transition from low to high level - QA0, QB0 ... QH0 = The level of QA, QB ... QH before the indicated steady-state input conditions were established. - QAn, QGn = The level of QA or QG before the most recent ^ transition of the clock; indicates a 1 bit shift. - -**********************************************************************/ - -#ifndef NLD_74164_H_ -#define NLD_74164_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74164(name, cA, cB, cCLRQ, cCLK) \ - NET_REGISTER_DEV(TTL_74164, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, CLRQ, cCLRQ) \ - NET_CONNECT(name, CLK, cCLK) - -#define TTL_74164_DIP(name) \ - NET_REGISTER_DEV(TTL_74164_DIP, name) - -#endif /* NLD_74164_H_ */ diff --git a/src/lib/netlist/devices/nld_74165.cpp b/src/lib/netlist/devices/nld_74165.cpp index 9e5d6607fbd..63fee9fdb13 100644 --- a/src/lib/netlist/devices/nld_74165.cpp +++ b/src/lib/netlist/devices/nld_74165.cpp @@ -3,36 +3,82 @@ /* * nld_74165.cpp * + * 74165: Parallel-Load 8-Bit Shift Register + * + * +--------------+ + * SH/LDQ |1 ++ 16| VCC + * CLK |2 15| CLKINH + * E |3 14| D + * F |4 74165 13| C + * G |5 12| B + * H |6 11| A + * QHQ |7 10| SER + * GND |8 9| QH + * +--------------+ + * + * SH/LDQ: Shift / !Load + * CLKINH: Clock Inhibit + * SER: Serial In + * + * Naming convention attempts to follow NTE Electronics datasheet + * */ -#include "nld_74165.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(74165) { NETLIB_CONSTRUCTOR(74165) - , m_DATA(*this, {{ "H", "G", "F", "E", "D", "C", "B", "A" }}) - , m_SER(*this, "SER") - , m_SH_LDQ(*this, "SH_LDQ") - , m_CLK(*this, "CLK") - , m_CLKINH(*this, "CLKINH") + , m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" }, NETLIB_DELEGATE(inputs)) + , m_SER(*this, "SER", NETLIB_DELEGATE_NOOP()) + , m_SH_LDQ(*this, "SH_LDQ", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_CLKINH(*this, "CLKINH", NETLIB_DELEGATE(inputs)) , m_QH(*this, "QH") , m_QHQ(*this, "QHQ") , m_shifter(*this, "m_shifter", 0) - , m_last_CLK(*this, "m_last_CLK", 0) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_shifter = 0; + } + + NETLIB_HANDLERI(clk) + { + unsigned high_bit = m_SER() ? 0x80 : 0; + m_shifter = high_bit | (m_shifter >> 1); + + const auto qh = m_shifter & 1; + + m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing + m_QHQ.push(qh ^ 1, NLTIME_FROM_NS(20)); // FIXME: Timing + } + + NETLIB_HANDLERI(inputs) + { + if (!m_SH_LDQ()) + { + m_shifter = 0; + for (std::size_t i=0; i<8; i++) + m_shifter |= (m_DATA[i]() << i); + const auto qh = m_shifter & 1; + + m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing + m_QHQ.push(qh ^ 1, NLTIME_FROM_NS(20)); // FIXME: Timing + } + if (!m_SH_LDQ() || m_CLKINH()) + m_CLK.inactivate(); + else + m_CLK.activate_lh(); + } - protected: + private: object_array_t<logic_input_t, 8> m_DATA; logic_input_t m_SER; logic_input_t m_SH_LDQ; @@ -42,72 +88,10 @@ namespace netlist logic_output_t m_QHQ; state_var<unsigned> m_shifter; - state_var<unsigned> m_last_CLK; nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74165_dip, 74165) - { - NETLIB_CONSTRUCTOR_DERIVED(74165_dip, 74165) - { - register_subalias("1", m_SH_LDQ); - register_subalias("2", m_CLK); - register_subalias("3", m_DATA[4]); - register_subalias("4", m_DATA[5]); - register_subalias("5", m_DATA[6]); - register_subalias("6", m_DATA[7]); - register_subalias("7", m_QHQ); - register_subalias("8", "GND"); - - register_subalias("9", m_QH); - register_subalias("10", m_SER); - register_subalias("11", m_DATA[0]); - register_subalias("12", m_DATA[1]); - register_subalias("13", m_DATA[2]); - register_subalias("14", m_DATA[3]); - register_subalias("15", m_CLKINH); - register_subalias("16", "VCC"); - } - }; - - NETLIB_RESET(74165) - { - m_shifter = 0; - m_last_CLK = 0; - } - // FIXME: Timing - NETLIB_UPDATE(74165) - { - netlist_sig_t old_qh = m_QH.net().Q(); - netlist_sig_t qh = 0; - - if (!m_SH_LDQ()) - { - m_shifter = 0; - for (std::size_t i=0; i<8; i++) - m_shifter |= (m_DATA[i]() << i); - } - else if (!m_CLK() || m_CLKINH()) - { - // FIXME: qh is overwritten below? - qh = old_qh; - } - else if (!m_last_CLK) - { - unsigned high_bit = m_SER() ? 0x80 : 0; - m_shifter = high_bit | (m_shifter >> 1); - } - - qh = m_shifter & 1; - - m_last_CLK = m_CLK(); - - m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing - } - NETLIB_DEVICE_IMPL(74165, "TTL_74165", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,@VCC,@GND") - NETLIB_DEVICE_IMPL(74165_dip, "TTL_74165_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74165.h b/src/lib/netlist/devices/nld_74165.h deleted file mode 100644 index 51133157dbd..00000000000 --- a/src/lib/netlist/devices/nld_74165.h +++ /dev/null @@ -1,52 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_74165.h - * - * 74165: Parallel-Load 8-Bit Shift Register - * - * +--------------+ - * SH/LDQ |1 ++ 16| VCC - * CLK |2 15| CLKINH - * E |3 14| D - * F |4 74165 13| C - * G |5 12| B - * H |6 11| A - * QHQ |7 10| SER - * GND |8 9| QH - * +--------------+ - * - * SH/LDQ: Shift / !Load - * CLKINH: Clock Inhibit - * SER: Serial In - * - * Naming convention attempts to follow NTE Electronics datasheet - * - */ - -#ifndef NLD_74165_H_ -#define NLD_74165_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74165(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH) \ - NET_REGISTER_DEV(TTL_74165, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, CLKINH, cCLKINH) \ - NET_CONNECT(name, SH_LDQ, cSH_LDQ) \ - NET_CONNECT(name, SER, cSER) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, E, cE) \ - NET_CONNECT(name, F, cF) \ - NET_CONNECT(name, G, cG) \ - NET_CONNECT(name, H, cH) - -#define TTL_74165_DIP(name) \ - NET_REGISTER_DEV(TTL_74165_DIP, name) - -#endif /* NLD_74165_H_ */ diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp index 2b9d6be1a3b..f12101a4737 100644 --- a/src/lib/netlist/devices/nld_74166.cpp +++ b/src/lib/netlist/devices/nld_74166.cpp @@ -3,25 +3,42 @@ /* * nld_74166.cpp * + * 74166: Parallel-Load 8-Bit Shift Register + * + * +--------------+ + * SER |1 ++ 16| VCC + * A |2 15| SH/LDQ + * B |3 14| H + * C |4 74166 13| QH + * D |5 12| G + * CLKINH |6 11| F + * CLK |7 10| E + * GND |8 9| CLRQ + * +--------------+ + * + * SH/LDQ: Shift / !Load + * CLKINH: Clock Inhibit + * SER: Serial In + * + * Naming convention attempts to follow Texas Instruments datasheet + * */ -#include "nld_74166.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +// FIXME: separate handlers for inputs + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(74166) { NETLIB_CONSTRUCTOR(74166) - , m_DATA(*this, {{ "H", "G", "F", "E", "D", "C", "B", "A" }}) - , m_SER(*this, "SER") - , m_CLRQ(*this, "CLRQ") - , m_SH_LDQ(*this, "SH_LDQ") - , m_CLK(*this, "CLK") - , m_CLKINH(*this, "CLKINH") + , m_DATA(*this, { "H", "G", "F", "E", "D", "C", "B", "A" }, NETLIB_DELEGATE(inputs)) + , m_SER(*this, "SER", NETLIB_DELEGATE(inputs)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs)) + , m_SH_LDQ(*this, "SH_LDQ", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs)) + , m_CLKINH(*this, "CLKINH", NETLIB_DELEGATE(inputs)) , m_QH(*this, "QH") , m_shifter(*this, "m_shifter", 0) , m_last_CLRQ(*this, "m_last_CLRQ", 0) @@ -30,103 +47,74 @@ namespace netlist { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 8> m_DATA; - logic_input_t m_SER; - logic_input_t m_CLRQ; - logic_input_t m_SH_LDQ; - logic_input_t m_CLK; - logic_input_t m_CLKINH; - logic_output_t m_QH; - - state_var<unsigned> m_shifter; - state_var<unsigned> m_last_CLRQ; - state_var<unsigned> m_last_CLK; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(74166_dip, 74166) - { - NETLIB_CONSTRUCTOR_DERIVED(74166_dip, 74166) + private: + NETLIB_RESETI() { - register_subalias("1", m_SER); - register_subalias("2", m_DATA[7]); - register_subalias("3", m_DATA[6]); - register_subalias("4", m_DATA[5]); - register_subalias("5", m_DATA[4]); - register_subalias("6", m_CLKINH); - register_subalias("7", m_CLK); - register_subalias("8", "GND"); - - register_subalias("9", m_CLRQ); - register_subalias("10", m_DATA[3]); - register_subalias("11", m_DATA[2]); - register_subalias("12", m_DATA[1]); - register_subalias("13", m_QH); - register_subalias("14", m_DATA[0]); - register_subalias("15", m_SH_LDQ); - register_subalias("16", "VCC"); + m_shifter = 0; + m_last_CLRQ = 0; + m_last_CLK = 0; } - }; - NETLIB_RESET(74166) - { - m_shifter = 0; - m_last_CLRQ = 0; - m_last_CLK = 0; - } - - NETLIB_UPDATE(74166) - { - netlist_sig_t old_qh = m_QH.net().Q(); - netlist_sig_t qh = 0; - - netlist_time delay = NLTIME_FROM_NS(26); - if (m_CLRQ()) + NETLIB_HANDLERI(inputs) { - bool clear_unset = !m_last_CLRQ; - if (clear_unset) - { - delay = NLTIME_FROM_NS(35); - } + netlist_sig_t old_qh = m_QH.net().Q(); + netlist_sig_t qh = 0; - if (!m_CLK() || m_CLKINH()) + netlist_time delay = NLTIME_FROM_NS(26); + if (m_CLRQ()) { - qh = old_qh; - } - else if (!m_last_CLK) - { - if (!m_SH_LDQ()) + bool clear_unset = !m_last_CLRQ; + if (clear_unset) { - m_shifter = 0; - for (std::size_t i=0; i<8; i++) - m_shifter |= (m_DATA[i]() << i); + delay = NLTIME_FROM_NS(35); } - else + + if (!m_CLK() || m_CLKINH()) { - unsigned high_bit = m_SER() ? 0x80 : 0; - m_shifter = high_bit | (m_shifter >> 1); + qh = old_qh; } - - qh = m_shifter & 1; - if (!qh && !clear_unset) + else if (!m_last_CLK) { - delay = NLTIME_FROM_NS(30); + if (!m_SH_LDQ()) + { + m_shifter = 0; + for (std::size_t i=0; i<8; i++) + m_shifter |= (m_DATA[i]() << i); + } + else + { + unsigned high_bit = m_SER() ? 0x80 : 0; + m_shifter = high_bit | (m_shifter >> 1); + } + + qh = m_shifter & 1; + if (!qh && !clear_unset) + { + delay = NLTIME_FROM_NS(30); + } } } + + m_last_CLRQ = m_CLRQ(); + m_last_CLK = m_CLK(); + + m_QH.push(qh, delay); //FIXME } - m_last_CLRQ = m_CLRQ(); - m_last_CLK = m_CLK(); + object_array_t<logic_input_t, 8> m_DATA; + logic_input_t m_SER; + logic_input_t m_CLRQ; + logic_input_t m_SH_LDQ; + logic_input_t m_CLK; + logic_input_t m_CLKINH; + logic_output_t m_QH; - m_QH.push(qh, delay); //FIXME - } + state_var<unsigned> m_shifter; + state_var<unsigned> m_last_CLRQ; + state_var<unsigned> m_last_CLK; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(74166, "TTL_74166", "+CLK,+CLKINH,+SH_LDQ,+SER,+A,+B,+C,+D,+E,+F,+G,+H,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(74166_dip,"TTL_74166_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74166.h b/src/lib/netlist/devices/nld_74166.h deleted file mode 100644 index be9cb7fdc4c..00000000000 --- a/src/lib/netlist/devices/nld_74166.h +++ /dev/null @@ -1,53 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_74166.h - * - * 74166: Parallel-Load 8-Bit Shift Register - * - * +--------------+ - * SER |1 ++ 16| VCC - * A |2 15| SH/LDQ - * B |3 14| H - * C |4 74166 13| QH - * D |5 12| G - * CLKINH |6 11| F - * CLK |7 10| E - * GND |8 9| CLRQ - * +--------------+ - * - * SH/LDQ: Shift / !Load - * CLKINH: Clock Inhibit - * SER: Serial In - * - * Naming convention attempts to follow Texas Instruments datasheet - * - */ - -#ifndef NLD_74166_H_ -#define NLD_74166_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74166(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH, cCLRQ) \ - NET_REGISTER_DEV(TTL_74166, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, CLKINH, cCLKINH) \ - NET_CONNECT(name, SH_LDQ, cSH_LDQ) \ - NET_CONNECT(name, SER, cSER) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, E, cE) \ - NET_CONNECT(name, F, cF) \ - NET_CONNECT(name, G, cG) \ - NET_CONNECT(name, H, cH) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#define TTL_74166_DIP(name) \ - NET_REGISTER_DEV(TTL_74166_DIP, name) - -#endif /* NLD_74166_H_ */ diff --git a/src/lib/netlist/devices/nld_74174.cpp b/src/lib/netlist/devices/nld_74174.cpp index bb6ecc1510b..2789eef0bb5 100644 --- a/src/lib/netlist/devices/nld_74174.cpp +++ b/src/lib/netlist/devices/nld_74174.cpp @@ -1,122 +1,103 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* * nld_74174.cpp * + * DM74174: Hex D Flip-Flops with Clear + * + * +--------------+ + * CLR |1 ++ 16| VCC + * Q1 |2 15| Q6 + * D1 |3 14| D6 + * D2 |4 74174 13| D5 + * Q2 |5 12| Q5 + * D3 |6 11| D4 + * Q3 |7 10| Q4 + * GND |8 9| CLK + * +--------------+ + * + * +-----+-----+---++---+-----+ + * | CLR | CLK | D || Q | QQ | + * +=====+=====+===++===+=====+ + * | 0 | X | X || 0 | 1 | + * | 1 | R | 1 || 1 | 0 | + * | 1 | R | 0 || 0 | 1 | + * | 1 | 0 | X || Q0| Q0Q | + * +-----+-----+---++---+-----+ + * + * Q0 The output logic level of Q before the indicated input conditions were established + * + * R: 0 -> 1 + * + * Naming conventions follow National Semiconductor datasheet + * */ -#include "nld_74174.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ -namespace devices -{ NETLIB_OBJECT(74174) { NETLIB_CONSTRUCTOR(74174) - , m_CLK(*this, "CLK", NETLIB_DELEGATE(74174, sub)) - , m_Q(*this, {{"Q1", "Q2", "Q3", "Q4", "Q5", "Q6"}}) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_Q(*this, 1, "Q{}") , m_clrq(*this, "m_clr", 0) , m_data(*this, "m_data", 0) - , m_D(*this, {{"D1", "D2", "D3", "D4", "D5", "D6"}}) - , m_CLRQ(*this, "CLRQ") + , m_D(*this, 1, "D{}", NETLIB_DELEGATE(other)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(clrq)) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_clrq = 0; + m_data = 0xFF; + } + + private: + NETLIB_HANDLERI(clrq) + { + m_clrq = m_CLRQ(); + if (!m_clrq) + { + m_data = 0; + m_Q.push(m_data, NLTIME_FROM_NS(40)); + m_CLK.inactivate(); + } + else + m_CLK.activate_lh(); + } + + NETLIB_HANDLERI(other) + { + m_data = m_D(); + if (m_clrq) + m_CLK.activate_lh(); + } - NETLIB_HANDLERI(sub) + NETLIB_HANDLERI(clk) { if (m_clrq) { - for (std::size_t i=0; i<6; i++) - { - netlist_sig_t d = (m_data >> i) & 1; - m_Q[i].push(d, NLTIME_FROM_NS(25)); - } + m_Q.push(m_data, NLTIME_FROM_NS(25)); m_CLK.inactivate(); } } - protected: logic_input_t m_CLK; object_array_t<logic_output_t, 6> m_Q; state_var<netlist_sig_t> m_clrq; - state_var<unsigned> m_data; + state_var<netlist_sig_t> m_data; object_array_t<logic_input_t, 6> m_D; logic_input_t m_CLRQ; nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74174_dip, 74174) - { - NETLIB_CONSTRUCTOR_DERIVED(74174_dip, 74174) - { - register_subalias("1", m_CLRQ); - register_subalias("9", m_CLK); - - register_subalias("3", m_D[0]); - register_subalias("2", m_Q[0]); - - register_subalias("4", m_D[1]); - register_subalias("5", m_Q[1]); - - register_subalias("6", m_D[2]); - register_subalias("7", m_Q[2]); - - register_subalias("11", m_D[3]); - register_subalias("10", m_Q[3]); - - register_subalias("13", m_D[4]); - register_subalias("12", m_Q[4]); - - register_subalias("14", m_D[5]); - register_subalias("15", m_Q[5]); - - register_subalias("8", "GND"); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_UPDATE(74174) - { - uint_fast8_t d = 0; - for (std::size_t i=0; i<6; i++) - { - d |= (m_D[i]() << i); - } - m_clrq = m_CLRQ(); - if (!m_clrq) - { - for (std::size_t i=0; i<6; i++) - { - m_Q[i].push(0, NLTIME_FROM_NS(40)); - } - m_data = 0; - } else if (d != m_data) - { - m_data = d; - m_CLK.activate_lh(); - } - } - - - NETLIB_RESET(74174) - { - m_CLK.set_state(logic_t::STATE_INP_LH); - m_clrq = 0; - m_data = 0xFF; - } - - NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(74174_dip,"TTL_74174_DIP", "") + NETLIB_DEVICE_IMPL(74174, "TTL_74174", "+CLK,+D1,+D2,+D3,+D4,+D5,+D6,+CLRQ,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74174.h b/src/lib/netlist/devices/nld_74174.h deleted file mode 100644 index 4fe23739aad..00000000000 --- a/src/lib/netlist/devices/nld_74174.h +++ /dev/null @@ -1,58 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74174.h - * - * DM74174: Hex D Flip-Flops with Clear - * - * +--------------+ - * CLR |1 ++ 16| VCC - * Q1 |2 15| Q6 - * D1 |3 14| D6 - * D2 |4 74174 13| D5 - * Q2 |5 12| Q5 - * D3 |6 11| D4 - * Q3 |7 10| Q4 - * GND |8 9| CLK - * +--------------+ - * - * +-----+-----+---++---+-----+ - * | CLR | CLK | D || Q | QQ | - * +=====+=====+===++===+=====+ - * | 0 | X | X || 0 | 1 | - * | 1 | R | 1 || 1 | 0 | - * | 1 | R | 0 || 0 | 1 | - * | 1 | 0 | X || Q0| Q0Q | - * +-----+-----+---++---+-----+ - * - * Q0 The output logic level of Q before the indicated input conditions were established - * - * R: 0 -> 1 - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74174_H_ -#define NLD_74174_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74174(name, cCLK, cD1, cD2, cD3, cD4, cD5, cD6, cCLRQ) \ - NET_REGISTER_DEV(TTL_74174, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, D2, cD2) \ - NET_CONNECT(name, D3, cD3) \ - NET_CONNECT(name, D4, cD4) \ - NET_CONNECT(name, D5, cD5) \ - NET_CONNECT(name, D6, cD6) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#define TTL_74174_DIP(name) \ - NET_REGISTER_DEV(TTL_74174_DIP, name) - - -#endif /* NLD_74174_H_ */ diff --git a/src/lib/netlist/devices/nld_74175.cpp b/src/lib/netlist/devices/nld_74175.cpp index 145c5887476..064e29cf6da 100644 --- a/src/lib/netlist/devices/nld_74175.cpp +++ b/src/lib/netlist/devices/nld_74175.cpp @@ -1,124 +1,115 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74175.c + * nld_74175.cpp + * + * DM74175: Quad D Flip-Flops with Clear + * + * +--------------+ + * CLR |1 ++ 16| VCC + * Q1 |2 15| Q4 + * Q1Q |3 14| Q4Q + * D1 |4 74175 13| D4 + * D2 |5 12| D3 + * Q2Q |6 11| Q3Q + * Q2 |7 10| Q3 + * GND |8 9| CLK + * +--------------+ + * + * +-----+-----+---++---+-----+ + * | CLR | CLK | D || Q | QQ | + * +=====+=====+===++===+=====+ + * | 0 | X | X || 0 | 1 | + * | 1 | R | 1 || 1 | 0 | + * | 1 | R | 0 || 0 | 1 | + * | 1 | 0 | X || Q0| Q0Q | + * +-----+-----+---++---+-----+ + * + * Q0 The output logic level of Q before the indicated input conditions were established + * + * R: 0 -> 1 + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_74175.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +// FIXME: optimize + +namespace netlist::devices { + + static constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) }; + static constexpr const std::array<netlist_time, 2> delay_clear = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(74175) { NETLIB_CONSTRUCTOR(74175) - , m_D(*this, {{"D1", "D2", "D3", "D4"}}) - , m_CLRQ(*this, "CLRQ") - , m_CLK(*this, "CLK", NETLIB_DELEGATE(74175, clk)) - , m_Q(*this, {{"Q1", "Q2", "Q3", "Q4"}}) - , m_QQ(*this, {{"Q1Q", "Q2Q", "Q3Q", "Q4Q"}}) + , m_D(*this, {"D1", "D2", "D3", "D4"}, NETLIB_DELEGATE(other)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_Q(*this, {"Q1", "Q2", "Q3", "Q4"}) + , m_QQ(*this, {"Q1Q", "Q2Q", "Q3Q", "Q4Q"}) , m_data(*this, "m_data", 0) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_HANDLERI(clk); - - protected: - object_array_t<logic_input_t, 4> m_D; - logic_input_t m_CLRQ; - - logic_input_t m_CLK; - object_array_t<logic_output_t, 4> m_Q; - object_array_t<logic_output_t, 4> m_QQ; - - state_var<unsigned> m_data; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(74175_dip, 74175) - { - NETLIB_CONSTRUCTOR_DERIVED(74175_dip, 74175) + private: + NETLIB_RESETI() { - register_subalias("9", m_CLK); - register_subalias("1", m_CLRQ); - - register_subalias("4", m_D[0]); - register_subalias("2", m_Q[0]); - register_subalias("3", m_QQ[0]); - - register_subalias("5", m_D[1]); - register_subalias("7", m_Q[1]); - register_subalias("6", m_QQ[1]); - - register_subalias("12", m_D[2]); - register_subalias("10", m_Q[2]); - register_subalias("11", m_QQ[2]); - - register_subalias("13", m_D[3]); - register_subalias("15", m_Q[3]); - register_subalias("14", m_QQ[3]); - - register_subalias("8", "GND"); - register_subalias("16", "VCC"); + m_CLK.set_state(logic_t::STATE_INP_LH); + m_data = 0xFF; } - }; - - constexpr const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) }; - constexpr const netlist_time delay_clear[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; - NETLIB_HANDLER(74175, clk) - { - if (m_CLRQ()) + NETLIB_HANDLERI(other) { + uint_fast8_t d = 0; for (std::size_t i=0; i<4; i++) { - netlist_sig_t d = (m_data >> i) & 1; - m_Q[i].push(d, delay[d]); - m_QQ[i].push(d ^ 1, delay[d ^ 1]); + d |= (m_D[i]() << i); + } + if (!m_CLRQ()) + { + for (std::size_t i=0; i<4; i++) + { + m_Q[i].push(0, delay_clear[0]); + m_QQ[i].push(1, delay_clear[1]); + } + m_data = 0; + } else if (d != m_data) + { + m_data = d; + m_CLK.activate_lh(); } - m_CLK.inactivate(); } - } - NETLIB_UPDATE(74175) - { - uint_fast8_t d = 0; - for (std::size_t i=0; i<4; i++) - { - d |= (m_D[i]() << i); - } - if (!m_CLRQ()) + NETLIB_HANDLERI(clk) { - for (std::size_t i=0; i<4; i++) + if (m_CLRQ()) { - m_Q[i].push(0, delay_clear[0]); - m_QQ[i].push(1, delay_clear[1]); + for (std::size_t i=0; i<4; i++) + { + netlist_sig_t d = (m_data >> i) & 1; + m_Q[i].push(d, delay[d]); + m_QQ[i].push(d ^ 1, delay[d ^ 1]); + } + m_CLK.inactivate(); } - m_data = 0; - } else if (d != m_data) - { - m_data = d; - m_CLK.activate_lh(); } - } + object_array_t<logic_input_t, 4> m_D; + logic_input_t m_CLRQ; - NETLIB_RESET(74175) - { - m_CLK.set_state(logic_t::STATE_INP_LH); - m_data = 0xFF; - } + logic_input_t m_CLK; + object_array_t<logic_output_t, 4> m_Q; + object_array_t<logic_output_t, 4> m_QQ; + + state_var<unsigned> m_data; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(74175, "TTL_74175", "+CLK,+D1,+D2,+D3,+D4,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(74175_dip,"TTL_74175_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74175.h b/src/lib/netlist/devices/nld_74175.h deleted file mode 100644 index b29d4680813..00000000000 --- a/src/lib/netlist/devices/nld_74175.h +++ /dev/null @@ -1,56 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74175.h - * - * DM74175: Quad D Flip-Flops with Clear - * - * +--------------+ - * CLR |1 ++ 16| VCC - * Q1 |2 15| Q4 - * Q1Q |3 14| Q4Q - * D1 |4 74175 13| D4 - * D2 |5 12| D3 - * Q2Q |6 11| Q3Q - * Q2 |7 10| Q3 - * GND |8 9| CLK - * +--------------+ - * - * +-----+-----+---++---+-----+ - * | CLR | CLK | D || Q | QQ | - * +=====+=====+===++===+=====+ - * | 0 | X | X || 0 | 1 | - * | 1 | R | 1 || 1 | 0 | - * | 1 | R | 0 || 0 | 1 | - * | 1 | 0 | X || Q0| Q0Q | - * +-----+-----+---++---+-----+ - * - * Q0 The output logic level of Q before the indicated input conditions were established - * - * R: 0 -> 1 - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74175_H_ -#define NLD_74175_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74175(name, cCLK, cD1, cD2, cD3, cD4, cCLRQ) \ - NET_REGISTER_DEV(TTL_74175, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, D2, cD2) \ - NET_CONNECT(name, D3, cD3) \ - NET_CONNECT(name, D4, cD4) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#define TTL_74175_DIP(name) \ - NET_REGISTER_DEV(TTL_74175_DIP, name) - - -#endif /* NLD_74175_H_ */ diff --git a/src/lib/netlist/devices/nld_74192.cpp b/src/lib/netlist/devices/nld_74192.cpp index bedc045164d..bee494a7e54 100644 --- a/src/lib/netlist/devices/nld_74192.cpp +++ b/src/lib/netlist/devices/nld_74192.cpp @@ -1,46 +1,78 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74192.c + * nld_74192.cpp + * + * DM74192: Synchronous 4-Bit Binary Counter with Dual Clock + * Decade counter + * + * FIXME: This should be merged with the 74193 which counts to 16 + * + * +--------------+ + * B |1 ++ 16| VCC + * QB |2 15| A + * QA |3 14| CLEAR + * CD |4 74192 13| BORROWQ + * CU |5 12| CARRYQ + * QC |6 11| LOADQ + * QD |7 10| C + * GND |8 9| D + * +--------------+ + * + * CD: Count up + * CU: Count down + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_74192.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" -namespace netlist -{ - namespace devices - { +#include "nl_base.h" + +namespace netlist::devices { static constexpr const unsigned MAXCNT = 9; + // FIXME: Optimize + + // FIXME: Timing + static constexpr const std::array<netlist_time, 4> delay = + { + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40) + }; + NETLIB_OBJECT(74192) { NETLIB_CONSTRUCTOR(74192) - , m_CLEAR(*this, "CLEAR") - , m_LOADQ(*this, "LOADQ") - , m_CU(*this, "CU") - , m_CD(*this, "CD") + , m_CLEAR(*this, "CLEAR", NETLIB_DELEGATE(inputs)) + , m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(inputs)) + , m_CU(*this, "CU", NETLIB_DELEGATE(inputs)) + , m_CD(*this, "CD", NETLIB_DELEGATE(inputs)) , m_cnt(*this, "m_cnt", 0) , m_last_CU(*this, "m_last_CU", 0) , m_last_CD(*this, "m_last_CD", 0) - , m_Q(*this, {{"QA", "QB", "QC", "QD"}}) + , m_Q(*this, {"QA", "QB", "QC", "QD"}) , m_BORROWQ(*this, "BORROWQ") , m_CARRYQ(*this, "CARRYQ") - , m_A(*this, "A", NETLIB_DELEGATE(74192, sub)) - , m_B(*this, "B", NETLIB_DELEGATE(74192, sub)) - , m_C(*this, "C", NETLIB_DELEGATE(74192, sub)) - , m_D(*this, "D", NETLIB_DELEGATE(74192, sub)) + , m_A(*this, "A", NETLIB_DELEGATE(sub)) + , m_B(*this, "B", NETLIB_DELEGATE(sub)) + , m_C(*this, "C", NETLIB_DELEGATE(sub)) + , m_D(*this, "D", NETLIB_DELEGATE(sub)) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_cnt = 0; + m_last_CU = 0; + m_last_CD = 0; + } - protected: + private: logic_input_t m_CLEAR; logic_input_t m_LOADQ; logic_input_t m_CU; @@ -60,104 +92,62 @@ namespace netlist logic_input_t m_D; nld_power_pins m_power_pins; - NETLIB_HANDLERI(sub) - { - // FIXME: can use more optimization - } - - unsigned read_ABCD() const + NETLIB_HANDLERI(inputs) { - return (m_D() << 3) | (m_C() << 2) | (m_B() << 1) | (m_A() << 0); - } + netlist_sig_t tCarry = 1; + netlist_sig_t tBorrow = 1; + if (m_CLEAR()) + { + m_cnt = 0; + } + else if (!m_LOADQ()) + { + m_cnt = read_ABCD(); + } + else + { + if (m_CD() && !m_last_CU && m_CU()) + { + if (++m_cnt > MAXCNT) + m_cnt = 0; + } + if (m_CU() && !m_last_CD && m_CD()) + { + if (m_cnt > 0) + --m_cnt; + else + m_cnt = MAXCNT; + } + } - }; + if (!m_CU() && (m_cnt == MAXCNT)) + tCarry = 0; - NETLIB_OBJECT_DERIVED(74192_dip, 74192) - { - NETLIB_CONSTRUCTOR_DERIVED(74192_dip, 74192) - { - register_subalias("1", m_B); - register_subalias("2", m_Q[1]); - register_subalias("3", m_Q[0]); - register_subalias("4", m_CD); - register_subalias("5", m_CU); - register_subalias("6", m_Q[2]); - register_subalias("7", m_Q[3]); - register_subalias("8", "GND"); - - register_subalias("9", m_D); - register_subalias("10", m_C); - register_subalias("11", m_LOADQ); - register_subalias("12", m_CARRYQ); - register_subalias("13", m_BORROWQ); - register_subalias("14", m_CLEAR); - register_subalias("15", m_A); - register_subalias("16", "VCC"); - } - }; + if (!m_CD() && (m_cnt == 0)) + tBorrow = 0; - NETLIB_RESET(74192) - { - m_cnt = 0; - m_last_CU = 0; - m_last_CD = 0; - } + m_last_CD = m_CD(); + m_last_CU = m_CU(); - // FIXME: Timing - static constexpr const netlist_time delay[4] = - { - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40) - }; + for (std::size_t i=0; i<4; i++) + m_Q[i].push((m_cnt >> i) & 1, delay[i]); - NETLIB_UPDATE(74192) - { - netlist_sig_t tCarry = 1; - netlist_sig_t tBorrow = 1; - if (m_CLEAR()) - { - m_cnt = 0; + m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME + m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME } - else if (!m_LOADQ()) + + NETLIB_HANDLERI(sub) { - m_cnt = read_ABCD(); + // FIXME: can use more optimization } - else + + unsigned read_ABCD() const { - if (m_CD() && !m_last_CU && m_CU()) - { - if (++m_cnt > MAXCNT) - m_cnt = 0; - } - if (m_CU() && !m_last_CD && m_CD()) - { - if (m_cnt > 0) - --m_cnt; - else - m_cnt = MAXCNT; - } + return (m_D() << 3) | (m_C() << 2) | (m_B() << 1) | (m_A() << 0); } - if (!m_CU() && (m_cnt == MAXCNT)) - tCarry = 0; - - if (!m_CD() && (m_cnt == 0)) - tBorrow = 0; - - m_last_CD = m_CD(); - m_last_CU = m_CU(); - - for (std::size_t i=0; i<4; i++) - m_Q[i].push((m_cnt >> i) & 1, delay[i]); - - m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME - m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME - } + }; NETLIB_DEVICE_IMPL(74192, "TTL_74192", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD,@VCC,@GND") - NETLIB_DEVICE_IMPL(74192_dip,"TTL_74192_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74192.h b/src/lib/netlist/devices/nld_74192.h deleted file mode 100644 index 81397f355ae..00000000000 --- a/src/lib/netlist/devices/nld_74192.h +++ /dev/null @@ -1,50 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74192.h - * - * DM74192: Synchronous 4-Bit Binary Counter with Dual Clock - * Decade counter - * - * FIXME: This should be merged with the 74193 which counts to 16 - * - * +--------------+ - * B |1 ++ 16| VCC - * QB |2 15| A - * QA |3 14| CLEAR - * CD |4 74192 13| BORROWQ - * CU |5 12| CARRYQ - * QC |6 11| LOADQ - * QD |7 10| C - * GND |8 9| D - * +--------------+ - * - * CD: Count up - * CU: Count down - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74192_H_ -#define NLD_74192_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74192(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD) \ - NET_REGISTER_DEV(TTL_74192, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, CLEAR, cCLEAR) \ - NET_CONNECT(name, LOADQ, cLOADQ) \ - NET_CONNECT(name, CU, cCU) \ - NET_CONNECT(name, CD, cCD) - -#define TTL_74192_DIP(name) \ - NET_REGISTER_DEV(TTL_74192_DIP, name) - -#endif /* NLD_74192_H_ */ diff --git a/src/lib/netlist/devices/nld_74193.cpp b/src/lib/netlist/devices/nld_74193.cpp index 5e919a78a9a..fa1a68f56b5 100644 --- a/src/lib/netlist/devices/nld_74193.cpp +++ b/src/lib/netlist/devices/nld_74193.cpp @@ -1,45 +1,118 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_74193.c + * nld_74193.cpp + * + * DM74193: Synchronous 4-Bit Binary Counter with Dual Clock + * + * +--------------+ + * B |1 ++ 16| VCC + * QB |2 15| A + * QA |3 14| CLEAR + * CD |4 74193 13| BORROWQ + * CU |5 12| CARRYQ + * QC |6 11| LOADQ + * QD |7 10| C + * GND |8 9| D + * +--------------+ + * + * CD: Count up + * CU: Count down + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_74193.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { static constexpr const unsigned MAXCNT = 15; + // FIXME: Timing, combine with 74192! + static constexpr const std::array<netlist_time, 4> delay = + { + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40), + NLTIME_FROM_NS(40) + }; + + // FIXME: Optimize! + NETLIB_OBJECT(74193) { NETLIB_CONSTRUCTOR(74193) - , m_A(*this, "A") - , m_B(*this, "B") - , m_C(*this, "C") - , m_D(*this, "D") - , m_CLEAR(*this, "CLEAR") - , m_LOADQ(*this, "LOADQ") - , m_CU(*this, "CU") - , m_CD(*this, "CD") + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_C(*this, "C", NETLIB_DELEGATE(inputs)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_CLEAR(*this, "CLEAR", NETLIB_DELEGATE(inputs)) + , m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(inputs)) + , m_CU(*this, "CU", NETLIB_DELEGATE(inputs)) + , m_CD(*this, "CD", NETLIB_DELEGATE(inputs)) , m_cnt(*this, "m_cnt", 0) , m_last_CU(*this, "m_last_CU", 0) , m_last_CD(*this, "m_last_CD", 0) - , m_Q(*this, {{"QA", "QB", "QC", "QD"}}) + , m_Q(*this, {"QA", "QB", "QC", "QD"}) , m_BORROWQ(*this, "BORROWQ") , m_CARRYQ(*this, "CARRYQ") , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + private: + NETLIB_RESETI() + { + m_cnt = 0; + m_last_CU = 0; + m_last_CD = 0; + } + + NETLIB_HANDLERI(inputs) + { + netlist_sig_t tCarry = 1; + netlist_sig_t tBorrow = 1; + if (m_CLEAR()) + { + m_cnt = 0; + } + else if (!m_LOADQ()) + { + m_cnt = (m_D() << 3) | (m_C() << 2) + | (m_B() << 1) | (m_A() << 0); + } + else + { + if (m_CD() && !m_last_CU && m_CU()) + { + ++m_cnt &= MAXCNT; + } + if (m_CU() && !m_last_CD && m_CD()) + { + if (m_cnt > 0) + --m_cnt; + else + m_cnt = MAXCNT; + } + } + + if (!m_CU() && (m_cnt == MAXCNT)) + tCarry = 0; + + if (!m_CD() && (m_cnt == 0)) + tBorrow = 0; + + m_last_CD = m_CD(); + m_last_CU = m_CU(); + + for (std::size_t i=0; i<4; i++) + m_Q[i].push((m_cnt >> i) & 1, delay[i]); + + m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME timing + m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing + } - protected: logic_input_t m_A; logic_input_t m_B; logic_input_t m_C; @@ -59,92 +132,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74193_dip, 74193) - { - NETLIB_CONSTRUCTOR_DERIVED(74193_dip, 74193) - { - register_subalias("1", m_B); - register_subalias("2", m_Q[1]); - register_subalias("3", m_Q[0]); - register_subalias("4", m_CD); - register_subalias("5", m_CU); - register_subalias("6", m_Q[2]); - register_subalias("7", m_Q[3]); - register_subalias("8", "GND"); - - register_subalias("9", m_D); - register_subalias("10", m_C); - register_subalias("11", m_LOADQ); - register_subalias("12", m_CARRYQ); - register_subalias("13", m_BORROWQ); - register_subalias("14", m_CLEAR); - register_subalias("15", m_A); - register_subalias("16", "VCC"); - } - }; - - NETLIB_RESET(74193) - { - m_cnt = 0; - m_last_CU = 0; - m_last_CD = 0; - } - - // FIXME: Timing - static constexpr const netlist_time delay[4] = - { - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40), - NLTIME_FROM_NS(40) - }; - - NETLIB_UPDATE(74193) - { - netlist_sig_t tCarry = 1; - netlist_sig_t tBorrow = 1; - if (m_CLEAR()) - { - m_cnt = 0; - } - else if (!m_LOADQ()) - { - m_cnt = (m_D() << 3) | (m_C() << 2) - | (m_B() << 1) | (m_A() << 0); - } - else - { - if (m_CD() && !m_last_CU && m_CU()) - { - ++m_cnt &= MAXCNT; - } - if (m_CU() && !m_last_CD && m_CD()) - { - if (m_cnt > 0) - --m_cnt; - else - m_cnt = MAXCNT; - } - } - - if (!m_CU() && (m_cnt == MAXCNT)) - tCarry = 0; - - if (!m_CD() && (m_cnt == 0)) - tBorrow = 0; - - m_last_CD = m_CD(); - m_last_CU = m_CU(); - - for (std::size_t i=0; i<4; i++) - m_Q[i].push((m_cnt >> i) & 1, delay[i]); - - m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME timing - m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing - } - - NETLIB_DEVICE_IMPL(74193, "TTL_74193", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD,@VCC,@GND") - NETLIB_DEVICE_IMPL(74193_dip, "TTL_74193_DIP", "") + NETLIB_DEVICE_IMPL(74193, "TTL_74193", "+A,+B,+C,+D,+CLEAR,+LOADQ,+CU,+CD,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74193.h b/src/lib/netlist/devices/nld_74193.h deleted file mode 100644 index 493e6854266..00000000000 --- a/src/lib/netlist/devices/nld_74193.h +++ /dev/null @@ -1,47 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74193.h - * - * DM74193: Synchronous 4-Bit Binary Counter with Dual Clock - * - * +--------------+ - * B |1 ++ 16| VCC - * QB |2 15| A - * QA |3 14| CLEAR - * CD |4 74193 13| BORROWQ - * CU |5 12| CARRYQ - * QC |6 11| LOADQ - * QD |7 10| C - * GND |8 9| D - * +--------------+ - * - * CD: Count up - * CU: Count down - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_74193_H_ -#define NLD_74193_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74193(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD) \ - NET_REGISTER_DEV(TTL_74193, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, CLEAR, cCLEAR) \ - NET_CONNECT(name, LOADQ, cLOADQ) \ - NET_CONNECT(name, CU, cCU) \ - NET_CONNECT(name, CD, cCD) - -#define TTL_74193_DIP(name) \ - NET_REGISTER_DEV(TTL_74193_DIP, name) - -#endif /* NLD_74193_H_ */ diff --git a/src/lib/netlist/devices/nld_74194.cpp b/src/lib/netlist/devices/nld_74194.cpp index f42032ef91b..4f9fbe69940 100644 --- a/src/lib/netlist/devices/nld_74194.cpp +++ b/src/lib/netlist/devices/nld_74194.cpp @@ -3,37 +3,97 @@ /* * nld_74194.cpp * + * 74194: Parallel-Load 8-Bit Shift Register + * + * +--------------+ + * CLRQ |1 ++ 16| VCC + * SRIN |2 15| QA + * A |3 14| QB + * B |4 74194 13| QC + * C |5 12| QD + * D |6 11| CLK + * SLIN |7 10| S1 + * GND |8 9| S0 + * +--------------+ + * + * CLR: Clear + * SRIN: Shift Right Serial Input + * SLIN: Shift Left Serial Input + * CLK: Clock + * */ -#include "nld_74194.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices - { +namespace netlist::devices { + + // FIXME: Optimize NETLIB_OBJECT(74194) { NETLIB_CONSTRUCTOR(74194) - , m_DATA(*this, {{"D", "C", "B", "A"}}) - , m_SLIN(*this, "SLIN") - , m_SRIN(*this, "SRIN") - , m_CLK(*this, "CLK") - , m_S0(*this, "S0") - , m_S1(*this, "S1") - , m_CLRQ(*this, "CLRQ") - , m_Q(*this, {{"QD", "QC", "QB", "QA"}}) + , m_DATA(*this, {"D", "C", "B", "A"}, NETLIB_DELEGATE(inputs)) + , m_SLIN(*this, "SLIN", NETLIB_DELEGATE(inputs)) + , m_SRIN(*this, "SRIN", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs)) + , m_S0(*this, "S0", NETLIB_DELEGATE(inputs)) + , m_S1(*this, "S1", NETLIB_DELEGATE(inputs)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs)) + , m_Q(*this, {"QD", "QC", "QB", "QA"}) , m_last_CLK(*this, "m_last_CLK", 0) , m_last_Q(*this, "m_last_Q", 0) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + private: + NETLIB_RESETI() + { + m_last_CLK = 0; + m_last_Q = 0; + } + + // FIXME: Timing + NETLIB_HANDLERI(inputs) + { + unsigned q = m_last_Q; + + if (!m_CLRQ()) + { + q = 0; + } + else + { + if (!m_last_CLK && m_CLK()) + { + unsigned s = (m_S1() << 1) | m_S0(); + switch (s) + { + case 0: // LL: Keep old value + break; + case 1: // LH: Shift right + q >>= 1; + q |= m_SRIN() ? 8 : 0; + break; + case 2: + q <<= 1; + q |= m_SLIN() ? 1 : 0; + break; + case 3: + q = 0; + for (std::size_t i=0; i<4; i++) + q |= m_DATA[i]() << i; + break; + } + } + } + + m_last_Q = q; + m_last_CLK = m_CLK(); + + for (std::size_t i=0; i<4; i++) + m_Q[i].push((q >> i) & 1, NLTIME_FROM_NS(26)); // FIXME: Timing + } - protected: object_array_t<logic_input_t, 4> m_DATA; logic_input_t m_SLIN; logic_input_t m_SRIN; @@ -48,81 +108,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74194_dip, 74194) - { - NETLIB_CONSTRUCTOR_DERIVED(74194_dip, 74194) - { - register_subalias("1", m_CLRQ); - register_subalias("2", m_SRIN); - register_subalias("3", m_DATA[3]); - register_subalias("4", m_DATA[2]); - register_subalias("5", m_DATA[1]); - register_subalias("6", m_DATA[0]); - register_subalias("7", m_SLIN); - register_subalias("8", "GND"); - - register_subalias("9", m_S0); - register_subalias("10", m_S1); - register_subalias("11", m_CLK); - register_subalias("12", m_Q[0]); - register_subalias("13", m_Q[1]); - register_subalias("14", m_Q[2]); - register_subalias("15", m_Q[3]); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_RESET(74194) - { - m_last_CLK = 0; - m_last_Q = 0; - } - - // FIXME: Timing - NETLIB_UPDATE(74194) - { - unsigned q = m_last_Q; - - if (!m_CLRQ()) - { - q = 0; - } - else - { - if (!m_last_CLK && m_CLK()) - { - unsigned s = (m_S1() << 1) | m_S0(); - switch (s) - { - case 0: // LL: Keep old value - break; - case 1: // LH: Shift right - q >>= 1; - q |= m_SRIN() ? 8 : 0; - break; - case 2: - q <<= 1; - q |= m_SLIN() ? 1 : 0; - break; - case 3: - q = 0; - for (std::size_t i=0; i<4; i++) - q |= m_DATA[i]() << i; - break; - } - } - } - - m_last_Q = q; - m_last_CLK = m_CLK(); - - for (std::size_t i=0; i<4; i++) - m_Q[i].push((q >> i) & 1, NLTIME_FROM_NS(26)); // FIXME: Timing - } - NETLIB_DEVICE_IMPL(74194, "TTL_74194", "+CLK,+S0,+S1,+SRIN,+A,+B,+C,+D,+SLIN,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(74194_dip, "TTL_74194_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74194.h b/src/lib/netlist/devices/nld_74194.h deleted file mode 100644 index 2432a6ece97..00000000000 --- a/src/lib/netlist/devices/nld_74194.h +++ /dev/null @@ -1,49 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_74194.h - * - * 74194: Parallel-Load 8-Bit Shift Register - * - * +--------------+ - * CLRQ |1 ++ 16| VCC - * SRIN |2 15| QA - * A |3 14| QB - * B |4 74194 13| QC - * C |5 12| QD - * D |6 11| CLK - * SLIN |7 10| S1 - * GND |8 9| S0 - * +--------------+ - * - * CLR: Clear - * SRIN: Shift Right Serial Input - * SLIN: Shift Left Serial Input - * CLK: Clock - * - */ - -#ifndef NLD_74194_H_ -#define NLD_74194_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74194(name, cCLK, cS0, cS1, cSRIN, cA, cB, cC, cD, cSLIN, cCLRQ) \ - NET_REGISTER_DEV(TTL_74194, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, S0, cS0) \ - NET_CONNECT(name, S1, cS1) \ - NET_CONNECT(name, SRIN, cSRIN) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, SLIN, cSLIN) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#define TTL_74194_DIP(name) \ - NET_REGISTER_DEV(TTL_74194_DIP, name) - -#endif /* NLD_74194_H_ */ diff --git a/src/lib/netlist/devices/nld_74365.cpp b/src/lib/netlist/devices/nld_74365.cpp index 85271d7861b..2cc582fbc8a 100644 --- a/src/lib/netlist/devices/nld_74365.cpp +++ b/src/lib/netlist/devices/nld_74365.cpp @@ -3,16 +3,28 @@ /* * nld_74365.cpp * + * SN74365: Hex Bus Driver with 3-State Outputs + * + * +--------------+ + * G1Q |1 ++ 16| VCC + * A1 |2 15| G2Q + * Y1 |3 14| A6 + * A2 |4 74365 13| Y6 + * Y2 |5 12| A5 + * A3 |6 11| Y5 + * Y3 |7 10| A4 + * GND |8 9| Y4 + * +--------------+ + * + * Naming conventions follow Texas Instruments datasheet + * + * Note: Currently the netlist system does not support proper tristate output, so this + * is not a "real" bus driver, it simply outputs 0 if the chip is not enabled. */ -#include "nld_74365.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices - { +namespace netlist::devices { /* FIXME: This should be a single device, i.e. one tristate buffer only. * @@ -24,17 +36,29 @@ namespace netlist NETLIB_OBJECT(74365) { NETLIB_CONSTRUCTOR(74365) - , m_G1Q(*this, "G1Q") - , m_G2Q(*this, "G2Q") - , m_A(*this, {{ "A1", "A2", "A3", "A4", "A5", "A6" }}) - , m_Y(*this, {{ "Y1", "Y2", "Y3", "Y4", "Y5", "Y6" }}) + , m_G1Q(*this, "G1Q", NETLIB_DELEGATE(inputs)) + , m_G2Q(*this, "G2Q", NETLIB_DELEGATE(inputs)) + , m_A(*this, { "A1", "A2", "A3", "A4", "A5", "A6" }, NETLIB_DELEGATE(inputs)) + , m_Y(*this, { "Y1", "Y2", "Y3", "Y4", "Y5", "Y6" }) , m_power_pins(*this) { } - NETLIB_UPDATEI(); + private: + NETLIB_HANDLERI(inputs) + { + if (!m_G1Q() && !m_G2Q()) + { + for (std::size_t i=0; i<6; i++) + m_Y[i].push(m_A[i](), NLTIME_FROM_NS(20)); // FIXME: Correct timing + } + else + { + for (std::size_t i=0; i<6; i++) + m_Y[i].push(0, NLTIME_FROM_NS(20)); // FIXME: Correct timing + } + } - protected: logic_input_t m_G1Q; logic_input_t m_G2Q; object_array_t<logic_input_t, 6> m_A; @@ -42,47 +66,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(74365_dip, 74365) - { - NETLIB_CONSTRUCTOR_DERIVED(74365_dip, 74365) - { - register_subalias("1", m_G1Q); - register_subalias("2", m_A[0]); - register_subalias("3", m_Y[0]); - register_subalias("4", m_A[1]); - register_subalias("5", m_Y[1]); - register_subalias("6", m_A[2]); - register_subalias("7", m_Y[2]); - register_subalias("8", "GND"); - - register_subalias("9", m_A[3]); - register_subalias("10", m_Y[3]); - register_subalias("11", m_A[4]); - register_subalias("12", m_Y[4]); - register_subalias("13", m_A[5]); - register_subalias("14", m_Y[5]); - register_subalias("15", m_G2Q); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_UPDATE(74365) - { - if (!m_G1Q() && !m_G2Q()) - { - for (std::size_t i=0; i<6; i++) - m_Y[i].push(m_A[i](), NLTIME_FROM_NS(20)); // FIXME: Correct timing - } - else - { - for (std::size_t i=0; i<6; i++) - m_Y[i].push(0, NLTIME_FROM_NS(20)); // FIXME: Correct timing - } - } - NETLIB_DEVICE_IMPL(74365, "TTL_74365", "+G1Q,+G2Q,+A1,+A2,+A3,+A4,+A5,+A6,@VCC,@GND") - NETLIB_DEVICE_IMPL(74365_dip, "TTL_74365_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74365.h b/src/lib/netlist/devices/nld_74365.h deleted file mode 100644 index 1aeeddaff8d..00000000000 --- a/src/lib/netlist/devices/nld_74365.h +++ /dev/null @@ -1,46 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_74365.h - * - * SN74365: Hex Bus Driver with 3-State Outputs - * - * +--------------+ - * G1Q |1 ++ 16| VCC - * A1 |2 15| G2Q - * Y1 |3 14| A6 - * A2 |4 74365 13| Y6 - * Y2 |5 12| A5 - * A3 |6 11| Y5 - * Y3 |7 10| A4 - * GND |8 9| Y4 - * +--------------+ - * - * Naming conventions follow Texas Instruments datasheet - * - * Note: Currently the netlist system does not support proper tristate output, so this - * is not a "real" bus driver, it simply outputs 0 if the chip is not enabled. - */ - -#ifndef NLD_74365_H_ -#define NLD_74365_H_ - -#include "netlist/nl_setup.h" - -#define TTL_74365(name, cG1Q, cG2Q, cA1, cA2, cA3, cA4, cA5, cA6) \ - NET_REGISTER_DEV(TTL_74365, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, G1Q, cG1Q) \ - NET_CONNECT(name, G2Q, cG2Q) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) - -#define TTL_74365_DIP(name) \ - NET_REGISTER_DEV(TTL_74365_DIP, name) - -#endif /* NLD_74365_H_ */ diff --git a/src/lib/netlist/devices/nld_74377.cpp b/src/lib/netlist/devices/nld_74377.cpp new file mode 100644 index 00000000000..83da292737f --- /dev/null +++ b/src/lib/netlist/devices/nld_74377.cpp @@ -0,0 +1,101 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_74377.cpp + * + * DM74377: Octal D Flip-Flop With Enable + * + * +--------------+ + * /E |1 ++ 20| VCC + * Q0 |2 19| Q7 + * D0 |3 18| D7 + * D1 |4 74377 17| D6 + * Q1 |5 16| Q6 + * Q2 |6 15| Q5 + * D2 |7 14| D5 + * D3 |8 13| D4 + * Q3 |9 12| Q4 + * GND |10 11| CP + * +--------------+ + * + * DM74378: Hex D Flip-Flop With Enable + * + * +--------------+ + * /E |1 ++ 16| VCC + * Q0 |2 15| Q5 + * D0 |3 14| D5 + * D1 |4 74378 13| D4 + * Q1 |5 12| Q4 + * D2 |6 11| D3 + * Q2 |7 10| Q3 + * GND |8 9| CP + * +--------------+ + * + * DM74379: 4-bit D Flip-Flop With Enable + * + * +--------------+ + * /E |1 ++ 16| VCC + * Q0 |2 15| Q3 + * /Q0 |3 14| /Q3 + * D0 |4 74379 13| D3 + * D1 |5 12| D2 + * /Q1 |6 11| /Q2 + * Q1 |7 10| Q2 + * GND |8 9| CP + * +--------------+ + * + * Naming conventions follow Motorola datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) }; + + NETLIB_OBJECT(74377_GATE) + { + NETLIB_CONSTRUCTOR(74377_GATE) + , m_E(*this, "E", NETLIB_DELEGATE(inputs)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_CP(*this, "CP", NETLIB_DELEGATE(inputs)) + , m_Q(*this, "Q") + , m_QQ(*this, "QQ") + , m_cp(*this, "m_cp", 0) + , m_power_pins(*this) + { + } + + NETLIB_RESETI() + { + } + + private: + NETLIB_HANDLERI(inputs) + { + netlist_sig_t last_cp = m_cp; + + m_cp = m_CP(); + + if (!m_E() && !last_cp && m_cp) + { + netlist_sig_t d = m_D(); + m_Q.push(d, delay[d]); + m_QQ.push(d ^ 1, delay[d ^ 1]); + } + } + + logic_input_t m_E; + logic_input_t m_D; + logic_input_t m_CP; + logic_output_t m_Q; + logic_output_t m_QQ; + + state_var_sig m_cp; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(74377_GATE, "TTL_74377_GATE", "") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74393.cpp b/src/lib/netlist/devices/nld_74393.cpp new file mode 100644 index 00000000000..4f8eac01634 --- /dev/null +++ b/src/lib/netlist/devices/nld_74393.cpp @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_74393.cpp + * + * DM74393: Dual 4-Stage Binary Counter + * + * +--------------+ + * /CP |1 ++ 14| VCC + * MR |2 13| /CP + * Q0 |3 12| MR + * Q1 |4 74393 11| Q0 + * Q2 |5 10| Q1 + * Q3 |6 9| Q2 + * GND |7 8| Q3 + * +--------------+ + * + * Naming conventions follow Motorola datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + static constexpr const unsigned MAXCNT = 15; + + NETLIB_OBJECT(74393) + { + NETLIB_CONSTRUCTOR(74393) + , m_CP(*this, "CP", NETLIB_DELEGATE(cp)) + , m_MR(*this, "MR", NETLIB_DELEGATE(mr)) + , m_Q(*this, {"Q0", "Q1", "Q2", "Q3"}) + , m_cnt(*this, "m_cnt", 0) + , m_cp(*this, "m_cp", 0) + , m_mr(*this, "m_mr", 0) + , m_power_pins(*this) + { + } + + private: + NETLIB_RESETI() + { + m_CP.set_state(logic_t::STATE_INP_HL); + m_cnt = 0; + } + + NETLIB_HANDLERI(mr) + { + if (!m_MR()) + { + m_CP.activate_hl(); + } + else + { + m_CP.inactivate(); + if (m_cnt != 0) + { + m_cnt = 0; + m_Q.push(0, NLTIME_FROM_NS(24)); + } + } + } + + NETLIB_HANDLERI(cp) + { + auto cnt = (m_cnt + 1) & MAXCNT; + m_cnt = cnt; + m_Q[0].push((cnt >> 0) & 1, NLTIME_FROM_NS(13)); + m_Q[1].push((cnt >> 1) & 1, NLTIME_FROM_NS(22)); + m_Q[2].push((cnt >> 2) & 1, NLTIME_FROM_NS(31)); + m_Q[3].push((cnt >> 3) & 1, NLTIME_FROM_NS(40)); + } + + logic_input_t m_CP; + logic_input_t m_MR; + object_array_t<logic_output_t, 4> m_Q; + + state_var<unsigned> m_cnt; + state_var_sig m_cp; + state_var_sig m_mr; + + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(74393, "TTL_74393", "+CP,+MR,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp index 23daf983174..c49038aca8e 100644 --- a/src/lib/netlist/devices/nld_7448.cpp +++ b/src/lib/netlist/devices/nld_7448.cpp @@ -1,42 +1,98 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7448.c + * nld_7448.cpp + * + * DM7448: BCD to 7-Segment decoders/drivers + * + * +--------------+ + * B |1 ++ 16| VCC + * C |2 15| f + * LAMP TEST |3 14| g + * BI/RBQ |4 7448 13| a + * RBI |5 12| b + * D |6 11| c + * A |7 10| d + * GND |8 9| e + * +--------------+ + * + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_7448.h" -#include "nlid_system.h" -#include "nlid_truthtable.h" +#include "nl_base.h" +#include "nl_factory.h" #include <array> -namespace netlist -{ - namespace devices - { - #if !(USE_TRUTHTABLE_7448) +namespace netlist::devices { + NETLIB_OBJECT(7448) { NETLIB_CONSTRUCTOR(7448) - , m_A(*this, "A") - , m_B(*this, "B") - , m_C(*this, "C") - , m_D(*this, "D") - , m_LTQ(*this, "LTQ") - , m_BIQ(*this, "BIQ") - , m_RBIQ(*this, "RBIQ") + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_C(*this, "C", NETLIB_DELEGATE(inputs)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_LTQ(*this, "LTQ", NETLIB_DELEGATE(inputs)) + , m_BIQ(*this, "BIQ", NETLIB_DELEGATE(inputs)) + , m_RBIQ(*this, "RBIQ", NETLIB_DELEGATE(inputs)) , m_state(*this, "m_state", 0) - , m_Q(*this, {{"a", "b", "c", "d", "e", "f", "g"}}) + , m_Q(*this, {"a", "b", "c", "d", "e", "f", "g"}) , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_state = 0; + } - public: - void update_outputs(unsigned v); + private: + void update_outputs(unsigned v) noexcept + { + gsl_Expects(v<16); + if (v != m_state) + { + // max transfer time is 100 NS */ + + uint8_t t = tab7448[v]; + for (std::size_t i = 0; i < 7; i++) + m_Q[i].push((t >> (6-i)) & 1, NLTIME_FROM_NS(100)); + m_state = v; + } + } + + NETLIB_HANDLERI(inputs) + { + if (!m_BIQ() || (m_BIQ() && !m_LTQ())) + { + m_A.inactivate(); + m_B.inactivate(); + m_C.inactivate(); + m_D.inactivate(); + m_RBIQ.inactivate(); + if (m_BIQ() && !m_LTQ()) + { + update_outputs(8); + } + else if (!m_BIQ()) + { + update_outputs(15); + } + } else { + m_RBIQ.activate(); + m_D.activate(); + m_C.activate(); + m_B.activate(); + m_A.activate(); + unsigned v = (m_A() << 0) | (m_B() << 1) | (m_C() << 2) | (m_D() << 3); + if ((!m_RBIQ() && (v==0))) + v = 15; + update_outputs(v); + } + } logic_input_t m_A; logic_input_t m_B; @@ -51,39 +107,12 @@ namespace netlist object_array_t<logic_output_t, 7> m_Q; /* a .. g */ nld_power_pins m_power_pins; + static const std::array<uint8_t, 16> tab7448; }; - NETLIB_OBJECT_DERIVED(7448_dip, 7448) - { - NETLIB_CONSTRUCTOR_DERIVED(7448_dip, 7448) - { - register_subalias("1", m_B); - register_subalias("2", m_C); - register_subalias("3", m_LTQ); - register_subalias("4", m_BIQ); - register_subalias("5", m_RBIQ); - register_subalias("6", m_D); - register_subalias("7", m_A); - register_subalias("8", "GND"); - - register_subalias("9", m_Q[4]); // e - register_subalias("10", m_Q[3]); // d - register_subalias("11", m_Q[2]); // c - register_subalias("12", m_Q[1]); // b - register_subalias("13", m_Q[0]); // a - register_subalias("14", m_Q[6]); // g - register_subalias("15", m_Q[5]); // f - register_subalias("16", "VCC"); - } - }; - #endif - - - #if !(USE_TRUTHTABLE_7448) - #define BITS7(b6,b5,b4,b3,b2,b1,b0) ((b6)<<6) | ((b5)<<5) | ((b4)<<4) | ((b3)<<3) | ((b2)<<2) | ((b1)<<1) | ((b0)<<0) - static constexpr const std::array<uint8_t, 16> tab7448 = + const std::array<uint8_t, 16> NETLIB_NAME(7448)::tab7448 = { BITS7( 1, 1, 1, 1, 1, 1, 0 ), /* 00 - not blanked ! */ BITS7( 0, 1, 1, 0, 0, 0, 0 ), /* 01 */ @@ -103,67 +132,6 @@ namespace netlist BITS7( 0, 0, 0, 0, 0, 0, 0 ), /* 15 */ }; - NETLIB_UPDATE(7448) - { - if (!m_BIQ() || (m_BIQ() && !m_LTQ())) - { - m_A.inactivate(); - m_B.inactivate(); - m_C.inactivate(); - m_D.inactivate(); - m_RBIQ.inactivate(); - if (m_BIQ() && !m_LTQ()) - { - update_outputs(8); - } - else if (!m_BIQ()) - { - update_outputs(15); - } - } else { - m_RBIQ.activate(); - m_D.activate(); - m_C.activate(); - m_B.activate(); - m_A.activate(); - unsigned v = (m_A() << 0) | (m_B() << 1) | (m_C() << 2) | (m_D() << 3); - if ((!m_RBIQ() && (v==0))) - v = 15; - update_outputs(v); - } - } - - NETLIB_RESET(7448) - { - m_state = 0; -#if 0 - m_A.set_state(logic_t::STATE_INP_PASSIVE); - m_B.set_state(logic_t::STATE_INP_PASSIVE); - m_C.set_state(logic_t::STATE_INP_PASSIVE); - m_D.set_state(logic_t::STATE_INP_PASSIVE); - m_RBIQ.set_state(logic_t::STATE_INP_PASSIVE); -#endif - } - - NETLIB_FUNC_VOID(7448, update_outputs, (unsigned v)) - { - nl_assert(v<16); - if (v != m_state) - { - // max transfer time is 100 NS */ - - uint8_t t = tab7448[v]; - for (std::size_t i = 0; i < 7; i++) - m_Q[i].push((t >> (6-i)) & 1, NLTIME_FROM_NS(100)); - m_state = v; - } - } - NETLIB_DEVICE_IMPL(7448, "TTL_7448", "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(7448_dip, "TTL_7448_DIP", "") - - #endif - - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7448.h b/src/lib/netlist/devices/nld_7448.h deleted file mode 100644 index 55ebfd8d6e4..00000000000 --- a/src/lib/netlist/devices/nld_7448.h +++ /dev/null @@ -1,49 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7448.h - * - * DM7448: BCD to 7-Segment decoders/drivers - * - * +--------------+ - * B |1 ++ 16| VCC - * C |2 15| f - * LAMP TEST |3 14| g - * BI/RBQ |4 7448 13| a - * RBI |5 12| b - * D |6 11| c - * A |7 10| d - * GND |8 9| e - * +--------------+ - * - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_7448_H_ -#define NLD_7448_H_ - -#include "netlist/nl_setup.h" - -#ifndef NL_AUTO_DEVICES -#if !(USE_TRUTHTABLE_7448) -#define TTL_7448(name, cA0, cA1, cA2, cA3, cLTQ, cBIQ, cRBIQ) \ - NET_REGISTER_DEV(TTL_7448, name) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, A, cA0) \ - NET_CONNECT(name, B, cA1) \ - NET_CONNECT(name, C, cA2) \ - NET_CONNECT(name, D, cA3) \ - NET_CONNECT(name, LTQ, cLTQ) \ - NET_CONNECT(name, BIQ, cBIQ) \ - NET_CONNECT(name, RBIQ, cRBIQ) - -#define TTL_7448_DIP(name) \ - NET_REGISTER_DEV(TTL_7448_DIP, name) - -#endif -#endif - -#endif /* NLD_7448_H_ */ diff --git a/src/lib/netlist/devices/nld_7450.cpp b/src/lib/netlist/devices/nld_7450.cpp index 818dad40853..df420de69ea 100644 --- a/src/lib/netlist/devices/nld_7450.cpp +++ b/src/lib/netlist/devices/nld_7450.cpp @@ -1,111 +1,90 @@ - // license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7450.c + * nld_7450.cpp + * + * DM7450: DUAL 2-WIDE 2-INPUT AND-OR-INVERT GATES (ONE GATE EXPANDABLE) + * + * +--------------+ + * 1A |1 ++ 14| VCC + * 2A |2 13| 1B + * 2B |3 12| 1XQ + * 2C |4 7450 11| 1X + * 2D |5 10| 1D + * 2Y |6 9| 1C + * GND |7 8| 1Y + * +--------------+ + * _________________ + * Y = (A & B) | (C & D) + * + * Naming conventions follow Texas Instruments datasheet * */ -#include "nld_7450.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { + + static constexpr const std::array<netlist_time, 2> times = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; + + // FIXME: timing, see 74107 for example, use template -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(7450) { NETLIB_CONSTRUCTOR(7450) - , m_A(*this, "A") - , m_B(*this, "B") - , m_C(*this, "C") - , m_D(*this, "D") + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_C(*this, "C", NETLIB_DELEGATE(inputs)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) , m_Q(*this, "Q") , m_power_pins(*this) { } - //NETLIB_RESETI(); - NETLIB_UPDATEI(); - - public: - logic_input_t m_A; - logic_input_t m_B; - logic_input_t m_C; - logic_input_t m_D; - logic_output_t m_Q; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT(7450_dip) - { - NETLIB_CONSTRUCTOR(7450_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", m_A.m_A); - register_subalias("2", m_B.m_A); - register_subalias("3", m_B.m_B); - register_subalias("4", m_B.m_C); - register_subalias("5", m_B.m_D); - register_subalias("6", m_B.m_Q); - register_subalias("7", "A.GND"); - - register_subalias("8", m_A.m_Q); - register_subalias("9", m_A.m_C); - register_subalias("10", m_A.m_D); - //register_subalias("11", m_1.m_X1); - //register_subalias("12", m_1.m_X1Q); - register_subalias("13", m_A.m_B); - register_subalias("14", "A.VCC"); - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - - } //NETLIB_RESETI(); - //NETLIB_UPDATEI(); - - NETLIB_SUB(7450) m_A; - NETLIB_SUB(7450) m_B; - }; - - NETLIB_UPDATE(7450) - { - m_A.activate(); - m_B.activate(); - m_C.activate(); - m_D.activate(); - auto t1 = m_A() & m_B(); - auto t2 = m_C() & m_D(); - - const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; - uint_fast8_t res = 0; - if (t1 ^ 1) + private: + NETLIB_HANDLERI(inputs) { - if (t2 ^ 1) + m_A.activate(); + m_B.activate(); + m_C.activate(); + m_D.activate(); + auto t1 = m_A() & m_B(); + auto t2 = m_C() & m_D(); + + uint_fast8_t res = 0; + if (t1 ^ 1) { - res = 1; + if (t2 ^ 1) + { + res = 1; + } + else + { + m_A.inactivate(); + m_B.inactivate(); + } } else { - m_A.inactivate(); - m_B.inactivate(); - } - } - else - { - if (t2 ^ 1) - { - m_C.inactivate(); - m_D.inactivate(); + if (t2 ^ 1) + { + m_C.inactivate(); + m_D.inactivate(); + } } + m_Q.push(res, times[res]);// ? 22000 : 15000); } - m_Q.push(res, times[res]);// ? 22000 : 15000); - } + + logic_input_t m_A; + logic_input_t m_B; + logic_input_t m_C; + logic_input_t m_D; + logic_output_t m_Q; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(7450, "TTL_7450_ANDORINVERT", "+A,+B,+C,+D,@VCC,@GND") - NETLIB_DEVICE_IMPL(7450_dip, "TTL_7450_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7450.h b/src/lib/netlist/devices/nld_7450.h deleted file mode 100644 index 431eaaaa65d..00000000000 --- a/src/lib/netlist/devices/nld_7450.h +++ /dev/null @@ -1,41 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7450.h - * - * DM7450: DUAL 2-WIDE 2-INPUT AND-OR-INVERT GATES (ONE GATE EXPANDABLE) - * - * +--------------+ - * 1A |1 ++ 14| VCC - * 2A |2 13| 1B - * 2B |3 12| 1XQ - * 2C |4 7450 11| 1X - * 2D |5 10| 1D - * 2Y |6 9| 1C - * GND |7 8| 1Y - * +--------------+ - * _________________ - * Y = (A & B) | (C & D) - * - * Naming conventions follow Texas Instruments datasheet - * - */ - -#ifndef NLD_7450_H_ -#define NLD_7450_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7450_ANDORINVERT(name, cI1, cI2, cI3, cI4) \ - NET_REGISTER_DEV(TTL_7450_ANDORINVERT, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cI1) \ - NET_CONNECT(name, B, cI2) \ - NET_CONNECT(name, C, cI3) \ - NET_CONNECT(name, D, cI4) - -#define TTL_7450_DIP(name) \ - NET_REGISTER_DEV(TTL_7450_DIP, name) - -#endif /* NLD_7450_H_ */ diff --git a/src/lib/netlist/devices/nld_7473.cpp b/src/lib/netlist/devices/nld_7473.cpp index 5c75115c970..d5b859859a4 100644 --- a/src/lib/netlist/devices/nld_7473.cpp +++ b/src/lib/netlist/devices/nld_7473.cpp @@ -1,25 +1,73 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7473.c + * nld_7473.cpp + * + * 7473: Dual Master-Slave J-K Flip-Flops with Clear and Complementary Outputs + * 7473A: Dual Negative-Edge-Triggered Master-Slave J-K Flip-Flops with Clear and Complementary Outputs + * + * +----------+ + * 1CLK |1 ++ 14| 1J + * 1CLRQ |2 13| 1QQ + * 1K |3 12| 1Q + * VCC |4 7473 11| GND + * 2CLK |5 10| 2K + * 2CLRQ |6 9| 2Q + * 2J |7 8| 2QQ + * +----------+ + * + * + * Function table 73 + * + * +-----+-----+-----+---++---+-----+ + * | CLRQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 0 | 1 | + * | 1 | * | 0 | 0 || Q0| Q0Q | + * | 1 | * | 1 | 0 || 1 | 0 | + * | 1 | * | 0 | 1 || 0 | 1 | + * | 1 | * | 1 | 1 || TOGGLE | + * +-----+-----+-----+---++---+-----+ + * _ + * * = _| |_ + * + * This is positive triggered, J and K + * are latched during clock high and + * transferred when CLK falls. + * + * Function table 73A + * + * +-----+-----+-----+---++---+-----+ + * | CLRQ| CLK | J | K || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | X | X | X || 0 | 1 | + * | 1 | F | 0 | 0 || Q0| Q0Q | + * | 1 | F | 1 | 0 || 1 | 0 | + * | 1 | F | 0 | 1 || 0 | 1 | + * | 1 | F | 1 | 1 || TOGGLE | + * | 1 | 1 | X | X || Q0| Q0Q | + * +-----+-----+-----+---++---+-----+ + * + * THe 73A is negative triggered. + * + * Naming conventions follow Texas instruments datasheet + * + * FIXME: Currently, only the 73 is implemented. + * The 73A uses the same model. * */ -#include "nld_7473.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(7473) { NETLIB_CONSTRUCTOR(7473) - , m_CLK(*this, "CLK") - , m_J(*this, "J") - , m_K(*this, "K") - , m_CLRQ(*this, "CLRQ") + , m_CLK(*this, "CLK", NETLIB_DELEGATE(inputs)) + , m_J(*this, "J", NETLIB_DELEGATE(inputs)) + , m_K(*this, "K", NETLIB_DELEGATE(inputs)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs)) , m_last_CLK(*this, "m_last_CLK", 0) , m_q(*this, "m_q", 0) , m_Q(*this, "Q") @@ -28,10 +76,44 @@ namespace netlist { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + private: + NETLIB_RESETI() + { + m_last_CLK = 0; + } + + NETLIB_HANDLERI(inputs) + { + const auto JK = (m_J() << 1) | m_K(); + + if (m_CLRQ()) + { + if (!m_CLK() && m_last_CLK) + { + switch (JK) + { + case 1: // (!m_J) & m_K)) + m_q = 0; + break; + case 2: // (m_J) & !m_K)) + m_q = 1; + break; + case 3: // (m_J) & m_K)) + m_q ^= 1; + break; + default: + case 0: + break; + } + } + } + + m_last_CLK = m_CLK(); + + m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing + m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing + } - public: logic_input_t m_CLK; logic_input_t m_J; logic_input_t m_K; @@ -45,116 +127,9 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(7473A, 7473) - { - public: - NETLIB_CONSTRUCTOR_DERIVED(7473A, 7473) { } - - }; - - NETLIB_OBJECT(7473_dip) - { - NETLIB_CONSTRUCTOR(7473_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", m_A.m_CLK); - register_subalias("2", m_A.m_CLRQ); - register_subalias("3", m_A.m_K); - register_subalias("4", "A.VCC"); - register_subalias("5", m_B.m_CLK); - register_subalias("6", m_B.m_CLRQ); - register_subalias("7", m_B.m_J); - - register_subalias("8", m_B.m_QQ); - register_subalias("9", m_B.m_Q); - register_subalias("10", m_B.m_K); - register_subalias("11", "A.GND"); - register_subalias("12", m_B.m_Q); - register_subalias("13", m_A.m_QQ); - register_subalias("14", m_A.m_J); - - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - } - - private: - NETLIB_SUB(7473) m_A; - NETLIB_SUB(7473) m_B; - }; - - NETLIB_OBJECT(7473A_dip) - { - NETLIB_CONSTRUCTOR(7473A_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", m_A.m_CLK); - register_subalias("2", m_A.m_CLRQ); - register_subalias("3", m_A.m_K); - register_subalias("4", "A.VCC"); - register_subalias("5", m_B.m_CLK); - register_subalias("6", m_B.m_CLRQ); - register_subalias("7", m_B.m_J); - - register_subalias("8", m_B.m_QQ); - register_subalias("9", m_B.m_Q); - register_subalias("10", m_B.m_K); - register_subalias("11", "A.GND"); - register_subalias("12", m_B.m_Q); - register_subalias("13", m_A.m_QQ); - register_subalias("14", m_A.m_J); - - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - } - - private: - NETLIB_SUB(7473A) m_A; - NETLIB_SUB(7473A) m_B; - }; - - NETLIB_RESET(7473) - { - m_last_CLK = 0; - } - - NETLIB_UPDATE(7473) - { - const auto JK = (m_J() << 1) | m_K(); - - if (m_CLRQ()) - { - if (!m_CLK() && m_last_CLK) - { - switch (JK) - { - case 1: // (!m_J) & m_K)) - m_q = 0; - break; - case 2: // (m_J) & !m_K)) - m_q = 1; - break; - case 3: // (m_J) & m_K)) - m_q ^= 1; - break; - default: - case 0: - break; - } - } - } - - m_last_CLK = m_CLK(); - - m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing - m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing - } + using NETLIB_NAME(7473A) = NETLIB_NAME(7473); NETLIB_DEVICE_IMPL(7473, "TTL_7473", "+CLK,+J,+K,+CLRQ,@VCC,@GND") NETLIB_DEVICE_IMPL(7473A, "TTL_7473A", "+CLK,+J,+K,+CLRQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(7473_dip, "TTL_7473_DIP", "") - NETLIB_DEVICE_IMPL(7473A_dip, "TTL_7473A_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7473.h b/src/lib/netlist/devices/nld_7473.h deleted file mode 100644 index e0dc8bdb428..00000000000 --- a/src/lib/netlist/devices/nld_7473.h +++ /dev/null @@ -1,84 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7473.h - * - * 7473: Dual Master-Slave J-K Flip-Flops with Clear and Complementary Outputs - * 7473A: Dual Negative-Edge-Triggered Master-Slave J-K Flip-Flops with Clear and Complementary Outputs - * - * +----------+ - * 1CLK |1 ++ 14| 1J - * 1CLRQ |2 13| 1QQ - * 1K |3 12| 1Q - * VCC |4 7473 11| GND - * 2CLK |5 10| 2K - * 2CLRQ |6 9| 2Q - * 2J |7 8| 2QQ - * +----------+ - * - * - * Function table 73 - * - * +-----+-----+-----+---++---+-----+ - * | CLRQ| CLK | J | K || Q | QQ | - * +=====+=====+=====+===++===+=====+ - * | 0 | X | X | X || 0 | 1 | - * | 1 | * | 0 | 0 || Q0| Q0Q | - * | 1 | * | 1 | 0 || 1 | 0 | - * | 1 | * | 0 | 1 || 0 | 1 | - * | 1 | * | 1 | 1 || TOGGLE | - * +-----+-----+-----+---++---+-----+ - * _ - * * = _| |_ - * - * This is positive triggered, J and K - * are latched during clock high and - * transferred when CLK falls. - * - * Function table 73A - * - * +-----+-----+-----+---++---+-----+ - * | CLRQ| CLK | J | K || Q | QQ | - * +=====+=====+=====+===++===+=====+ - * | 0 | X | X | X || 0 | 1 | - * | 1 | F | 0 | 0 || Q0| Q0Q | - * | 1 | F | 1 | 0 || 1 | 0 | - * | 1 | F | 0 | 1 || 0 | 1 | - * | 1 | F | 1 | 1 || TOGGLE | - * | 1 | 1 | X | X || Q0| Q0Q | - * +-----+-----+-----+---++---+-----+ - * - * THe 73A is negative triggered. - * - * Naming conventions follow Texas instruments datasheet - * - * FIXME: Currently, only the 73 is implemented. - * The 73A uses the same model. - * - */ - -#ifndef NLD_7473_H_ -#define NLD_7473_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7473(name, cCLK, cJ, cK, cCLRQ) \ - NET_REGISTER_DEV(TTL_7473, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, J, cJ) \ - NET_CONNECT(name, K, cK) \ - NET_CONNECT(name, CLRQ, cCLRQ) - -#define TTL_7473A(name, cCLK, cJ, cK, cCLRQ) \ - TTL_7473(name, cCLK, cJ, cK, cCLRQ) - -#define TTL_7473_DIP(name) \ - NET_REGISTER_DEV(TTL_7473_DIP, name) - - -#define TTL_7473A_DIP(name) \ - NET_REGISTER_DEV(TTL_7473A_DIP, name) - -#endif /* NLD_7473_H_ */ diff --git a/src/lib/netlist/devices/nld_7474.cpp b/src/lib/netlist/devices/nld_7474.cpp index 42d4d06b429..f79d38c5e0f 100644 --- a/src/lib/netlist/devices/nld_7474.cpp +++ b/src/lib/netlist/devices/nld_7474.cpp @@ -1,29 +1,58 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7474.c + * nld_7474.cpp * + * DM7474: Dual Positive-Edge-Triggered D Flip-Flops + * with Preset, Clear and Complementary Outputs + * + * +--------------+ + * CLR1 |1 ++ 14| VCC + * D1 |2 13| CLR2 + * CLK1 |3 12| D2 + * PR1 |4 7474 11| CLK2 + * Q1 |5 10| PR2 + * Q1Q |6 9| Q2 + * GND |7 8| Q2Q + * +--------------+ + * + * +-----+-----+-----+---++---+-----+ + * | PR | CLR | CLK | D || Q | QQ | + * +=====+=====+=====+===++===+=====+ + * | 0 | 1 | X | X || 1 | 0 | + * | 1 | 0 | X | X || 0 | 1 | + * | 0 | 0 | X | X || 1 | 1 | (*) + * | 1 | 1 | R | 1 || 1 | 0 | + * | 1 | 1 | R | 0 || 0 | 1 | + * | 1 | 1 | 0 | X || Q0| Q0Q | + * +-----+-----+-----+---++---+-----+ + * + * (*) This configuration is not stable, i.e. it will not persist + * when either the preset and or clear inputs return to their inactive (high) level + * + * Q0 The output logic level of Q before the indicated input conditions were established + * + * R: 0 -. 1 + * + * Naming conventions follow National Semiconductor datasheet + * + * FIXME: Check that (*) is emulated properly */ -#include "nld_7474.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" #include <array> -namespace netlist -{ - namespace devices - { +namespace netlist::devices { NETLIB_OBJECT(7474) { NETLIB_CONSTRUCTOR(7474) - , m_D(*this, "D") - , m_CLRQ(*this, "CLRQ") - , m_PREQ(*this, "PREQ") - , m_CLK(*this, "CLK", NETLIB_DELEGATE(7474, clk)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(inputs)) + , m_PREQ(*this, "PREQ", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) , m_Q(*this, "Q") , m_QQ(*this, "QQ") , m_nextD(*this, "m_nextD", 0) @@ -32,9 +61,36 @@ namespace netlist } private: - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_HANDLERI(clk); + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_D.set_state(logic_t::STATE_INP_ACTIVE); + m_nextD = 0; + } + + NETLIB_HANDLERI(clk) + { + newstate(m_nextD, !m_nextD); + m_CLK.inactivate(); + } + + NETLIB_HANDLERI(inputs) + { + const auto preq(m_PREQ()); + const auto clrq(m_CLRQ()); + if (preq & clrq) + { + m_D.activate(); + m_nextD = m_D(); + m_CLK.activate_lh(); + } + else + { + newstate(preq ^ 1, clrq ^ 1); + m_CLK.inactivate(); + m_D.inactivate(); + } + } logic_input_t m_D; logic_input_t m_CLRQ; @@ -47,7 +103,7 @@ namespace netlist nld_power_pins m_power_pins; - void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) + void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) noexcept { // 0: High-to-low 40 ns, 1: Low-to-high 25 ns static constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; @@ -56,80 +112,6 @@ namespace netlist } }; - NETLIB_OBJECT(7474_dip) - { - NETLIB_CONSTRUCTOR(7474_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", "A.CLRQ"); - register_subalias("2", "A.D"); - register_subalias("3", "A.CLK"); - register_subalias("4", "A.PREQ"); - register_subalias("5", "A.Q"); - register_subalias("6", "A.QQ"); - register_subalias("7", "A.GND"); - - register_subalias("8", "B.QQ"); - register_subalias("9", "B.Q"); - register_subalias("10", "B.PREQ"); - register_subalias("11", "B.CLK"); - register_subalias("12", "B.D"); - register_subalias("13", "B.CLRQ"); - register_subalias("14", "A.VCC"); - - connect("A.GND", "B.GND"); - connect("A.VCC", "B.VCC"); - } - NETLIB_UPDATEI(); - NETLIB_RESETI(); - - private: - NETLIB_SUB(7474) m_A; - NETLIB_SUB(7474) m_B; - }; - - NETLIB_HANDLER(7474, clk) - { - newstate(m_nextD, !m_nextD); - m_CLK.inactivate(); - } - - NETLIB_UPDATE(7474) - { - const auto preq(m_PREQ()); - const auto clrq(m_CLRQ()); - if (preq & clrq) - { - m_D.activate(); - m_nextD = m_D(); - m_CLK.activate_lh(); - } - else - { - newstate(preq ^ 1, clrq ^ 1); - m_CLK.inactivate(); - m_D.inactivate(); - } - } - - NETLIB_RESET(7474) - { - m_CLK.set_state(logic_t::STATE_INP_LH); - m_D.set_state(logic_t::STATE_INP_ACTIVE); - m_nextD = 0; - } - - NETLIB_RESET(7474_dip) - { - } - - NETLIB_UPDATE(7474_dip) - { - } - NETLIB_DEVICE_IMPL(7474, "TTL_7474", "+CLK,+D,+CLRQ,+PREQ,@VCC,@GND") - NETLIB_DEVICE_IMPL(7474_dip, "TTL_7474_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7474.h b/src/lib/netlist/devices/nld_7474.h deleted file mode 100644 index ccf75b42c6b..00000000000 --- a/src/lib/netlist/devices/nld_7474.h +++ /dev/null @@ -1,59 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7474.h - * - * DM7474: Dual Positive-Edge-Triggered D Flip-Flops - * with Preset, Clear and Complementary Outputs - * - * +--------------+ - * CLR1 |1 ++ 14| VCC - * D1 |2 13| CLR2 - * CLK1 |3 12| D2 - * PR1 |4 7474 11| CLK2 - * Q1 |5 10| PR2 - * Q1Q |6 9| Q2 - * GND |7 8| Q2Q - * +--------------+ - * - * +-----+-----+-----+---++---+-----+ - * | PR | CLR | CLK | D || Q | QQ | - * +=====+=====+=====+===++===+=====+ - * | 0 | 1 | X | X || 1 | 0 | - * | 1 | 0 | X | X || 0 | 1 | - * | 0 | 0 | X | X || 1 | 1 | (*) - * | 1 | 1 | R | 1 || 1 | 0 | - * | 1 | 1 | R | 0 || 0 | 1 | - * | 1 | 1 | 0 | X || Q0| Q0Q | - * +-----+-----+-----+---++---+-----+ - * - * (*) This configuration is not stable, i.e. it will not persist - * when either the preset and or clear inputs return to their inactive (high) level - * - * Q0 The output logic level of Q before the indicated input conditions were established - * - * R: 0 -. 1 - * - * Naming conventions follow National Semiconductor datasheet - * - * FIXME: Check that (*) is emulated properly - */ - -#ifndef NLD_7474_H_ -#define NLD_7474_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7474(name, cCLK, cD, cCLRQ, cPREQ) \ - NET_REGISTER_DEV(TTL_7474, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, CLRQ, cCLRQ) \ - NET_CONNECT(name, PREQ, cPREQ) - -#define TTL_7474_DIP(name) \ - NET_REGISTER_DEV(TTL_7474_DIP, name) - -#endif /* NLD_7474_H_ */ diff --git a/src/lib/netlist/devices/nld_7475.cpp b/src/lib/netlist/devices/nld_7475.cpp index 22c99e18952..afe42e84c70 100644 --- a/src/lib/netlist/devices/nld_7475.cpp +++ b/src/lib/netlist/devices/nld_7475.cpp @@ -4,157 +4,95 @@ * nld_7475.cpp * * TODO: Correct timing for clock-induced state changes, rather than assuming timing is always due to data-induced state changes + * + * 7475: 4-Bit Bistable Latches with Complementary Outputs + * 7477: 4-Bit Bistable Latches + * + * +----------+ +----------+ + * 1QQ |1 ++ 16| 1Q 1D |1 ++ 14| 1Q + * 1D |2 15| 2Q 2D |2 13| 2Q + * 2D |3 14| 2QQ 3C4C |3 12| 1C2C + * 3C4C |4 7475 13| 1C2C VCC |4 7477 11| GND + * VCC |5 12| GND 3D |5 10| NC + * 3D |6 11| 3QQ 4D |6 9| 3Q + * 4D |7 10| 3Q NC |7 8| 4Q + * 4QQ |8 9| 4Q +----------+ + * +----------+ + * + * + * Function table + * + * +---+---++---+-----+ + * | D | C || Q | QQ | + * +===+===++===+=====+ + * | 0 | 1 || 0 | 1 | + * | 1 | 1 || 1 | 0 | + * | X | 0 || Q0| Q0Q | + * +---+---++---+-----+ + * + * Naming conventions follow Texas instruments datasheet + * */ -#include "nld_7475.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(7477) +namespace netlist::devices { + + template <bool HasQQ> + NETLIB_OBJECT(7475_GATE_BASE) { - NETLIB_CONSTRUCTOR(7477) - , m_C1C2(*this, "C1C2") - , m_C3C4(*this, "C3C4") - , m_last_Q(*this, "m_last_Q", 0) - , m_D(*this, {{"D1", "D2", "D3", "D4"}}) - , m_Q(*this, {{"Q1", "Q2", "Q3", "Q4"}}) + NETLIB_CONSTRUCTOR(7475_GATE_BASE) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_Q(*this, "Q") + , m_QQ(*this, "QQ") + , m_nextD(*this, "m_nextD", 0) , m_power_pins(*this) { - register_subalias("Q1", m_Q[0]); } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - void update_outputs(std::size_t start, std::size_t end); - - public: - logic_input_t m_C1C2; - logic_input_t m_C3C4; - state_var<unsigned> m_last_Q; - object_array_t<logic_input_t, 4> m_D; - object_array_t<logic_output_t, 4> m_Q; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(7475, 7477) - { - NETLIB_CONSTRUCTOR_DERIVED(7475, 7477) - , m_QQ(*this, {{"QQ1", "QQ2", "QQ3", "QQ4"}}) + NETLIB_RESETI() { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_nextD = 0; } - NETLIB_UPDATEI(); - - public: - object_array_t<logic_output_t, 4> m_QQ; - }; - - NETLIB_OBJECT_DERIVED(7475_dip, 7475) - { - NETLIB_CONSTRUCTOR_DERIVED(7475_dip, 7475) + NETLIB_HANDLERI(clk) { - register_subalias("1", m_QQ[0]); - register_subalias("2", m_D[0]); - register_subalias("3", m_D[1]); - register_subalias("4", m_C3C4); - register_subalias("5", "VCC"); - register_subalias("6", m_D[2]); - register_subalias("7", m_D[3]); - register_subalias("8", m_QQ[3]); - - register_subalias("9", m_Q[3]); - register_subalias("10", m_Q[2]); - register_subalias("11", m_QQ[2]); - register_subalias("12", "GND"); - register_subalias("13", m_C1C2); - register_subalias("14", m_QQ[1]); - register_subalias("15", m_Q[1]); - register_subalias("16", m_Q[0]); + newstate(m_nextD, !m_nextD); + m_CLK.inactivate(); } - }; - NETLIB_OBJECT_DERIVED(7477_dip, 7477) - { - NETLIB_CONSTRUCTOR_DERIVED(7477_dip, 7477) + NETLIB_HANDLERI(inputs) { - register_subalias("1", m_D[0]); - register_subalias("2", m_D[1]); - register_subalias("3", m_C3C4); - //register_subalias("4", ); ==> VCC - register_subalias("5", m_D[2]); - register_subalias("6", m_D[3]); - //register_subalias("7", ); ==> NC - - register_subalias("8", m_Q[3]); - register_subalias("9", m_Q[2]); - //register_subalias("10", ); ==> NC - //register_subalias("11", ); ==> GND - register_subalias("12", m_C1C2); - register_subalias("13", m_Q[1]); - register_subalias("14", m_Q[0]); + m_nextD = m_D(); + m_CLK.activate_lh(); } - }; - - NETLIB_UPDATE(7475) - { - unsigned start_q = m_last_Q; - NETLIB_NAME(7477)::update(); + private: + logic_input_t m_D; + logic_input_t m_CLK; + logic_output_t m_Q; + logic_output_t m_QQ; - for (std::size_t i=0; i<4; i++) - { - unsigned last_bit = (m_last_Q >> i) & 1; - unsigned start_bit = (start_q >> i) & 1; - if (last_bit != start_bit) - m_QQ[i].push(last_bit ^ 1, last_bit != 0 ? NLTIME_FROM_NS(15) : NLTIME_FROM_NS(40)); - } - } - - void NETLIB_NAME(7477)::update_outputs(std::size_t start, std::size_t end) - { - for (std::size_t i=start; i<end; i++) - { - netlist_sig_t d = m_D[i](); - if (d != ((m_last_Q >> i) & 1)) - m_Q[i].push(d, d != 0 ? NLTIME_FROM_NS(30) : NLTIME_FROM_NS(25)); - m_last_Q &= ~(1 << i); - m_last_Q |= d << i; - } - } + state_var<netlist_sig_t> m_nextD; - NETLIB_RESET(7477) - { - m_last_Q = 0; - } + nld_power_pins m_power_pins; - NETLIB_UPDATE(7477) - { - netlist_sig_t c1c2 = m_C1C2(); - netlist_sig_t c3c4 = m_C3C4(); - if (c1c2 && c3c4) + void newstate(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) { - update_outputs(0, 4); - } - else if (c1c2) - { - update_outputs(0, 2); - } - else if (c3c4) - { - update_outputs(2, 4); + // 0: High-to-low 40 ns, 1: Low-to-high 25 ns + static constexpr const std::array<netlist_time, 2> delay = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; + m_Q.push(stateQ, delay[stateQ]); + if (HasQQ) + m_QQ.push(stateQQ, delay[stateQQ]); } + }; - } + using NETLIB_NAME(7475_GATE) = NETLIB_NAME(7475_GATE_BASE)<true>; + using NETLIB_NAME(7477_GATE) = NETLIB_NAME(7475_GATE_BASE)<false>; - NETLIB_DEVICE_IMPL(7475, "TTL_7475", "") - NETLIB_DEVICE_IMPL(7475_dip, "TTL_7475_DIP", "") - NETLIB_DEVICE_IMPL(7477, "TTL_7477", "") - NETLIB_DEVICE_IMPL(7477_dip, "TTL_7477_DIP", "") + NETLIB_DEVICE_IMPL(7475_GATE, "TTL_7475_GATE", "") + NETLIB_DEVICE_IMPL(7477_GATE, "TTL_7477_GATE", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7475.h b/src/lib/netlist/devices/nld_7475.h deleted file mode 100644 index 78ece9ff443..00000000000 --- a/src/lib/netlist/devices/nld_7475.h +++ /dev/null @@ -1,64 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_7475.h - * - * 7475: 4-Bit Bistable Latches with Complementary Outputs - * 7477: 4-Bit Bistable Latches - * - * +----------+ +----------+ - * 1QQ |1 ++ 16| 1Q 1D |1 ++ 14| 1Q - * 1D |2 15| 2Q 2D |2 13| 2Q - * 2D |3 14| 2QQ 3C4C |3 12| 1C2C - * 3C4C |4 7475 13| 1C2C VCC |4 7477 11| GND - * VCC |5 12| GND 3D |5 10| NC - * 3D |6 11| 3QQ 4D |6 9| 3Q - * 4D |7 10| 3Q NC |7 8| 4Q - * 4QQ |8 9| 4Q +----------+ - * +----------+ - * - * - * Function table - * - * +---+---++---+-----+ - * | D | C || Q | QQ | - * +===+===++===+=====+ - * | 0 | 1 || 0 | 1 | - * | 1 | 1 || 1 | 0 | - * | X | 0 || Q0| Q0Q | - * +---+---++---+-----+ - * - * Naming conventions follow Texas instruments datasheet - * - */ - -#ifndef NLD_7475_H_ -#define NLD_7475_H_ - -#include "netlist/nl_setup.h" - -#define PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, C1C2, cC1C2) \ - NET_CONNECT(name, C3C4, cC3C4) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, D2, cD2) \ - NET_CONNECT(name, D3, cD3) \ - NET_CONNECT(name, D4, cD4) - -#define TTL_7475(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) \ - NET_REGISTER_DEV(TTL_7475, name) \ - PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) - -#define TTL_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) \ - NET_REGISTER_DEV(TTL_7477, name) \ - PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4) - -#define TTL_7475_DIP(name) \ - NET_REGISTER_DEV(TTL_7475_DIP, name) - -#define TTL_7477_DIP(name) \ - NET_REGISTER_DEV(TTL_7477_DIP, name) - -#endif /* NLD_7475_H_ */ diff --git a/src/lib/netlist/devices/nld_7483.cpp b/src/lib/netlist/devices/nld_7483.cpp index a2c479a5488..866b8569284 100644 --- a/src/lib/netlist/devices/nld_7483.cpp +++ b/src/lib/netlist/devices/nld_7483.cpp @@ -1,30 +1,45 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7483.c + * nld_7483.cpp + * + * DM7483: 4-Bit Binary Adder with Fast Carry + * + * +--------------+ + * A4 |1 ++ 16| B4 + * S3 |2 15| S4 + * A3 |3 14| C4 + * B3 |4 7483 13| C0 + * VCC |5 12| GND + * S2 |6 11| B1 + * B2 |7 10| A1 + * A2 |8 9| S1 + * +--------------+ + * + * S = (A + B + C0) & 0x0f + * + * C4 = (A + B + C) > 15 ? 1 : 0 + * + * Naming conventions follow Fairchild Semiconductor datasheet * */ -#include "nld_7483.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(7483) { NETLIB_CONSTRUCTOR(7483) - , m_C0(*this, "C0") - , m_A1(*this, "A1", NETLIB_DELEGATE(7483, upd_a)) - , m_A2(*this, "A2", NETLIB_DELEGATE(7483, upd_a)) - , m_A3(*this, "A3", NETLIB_DELEGATE(7483, upd_a)) - , m_A4(*this, "A4", NETLIB_DELEGATE(7483, upd_a)) - , m_B1(*this, "B1", NETLIB_DELEGATE(7483, upd_b)) - , m_B2(*this, "B2", NETLIB_DELEGATE(7483, upd_b)) - , m_B3(*this, "B3", NETLIB_DELEGATE(7483, upd_b)) - , m_B4(*this, "B4", NETLIB_DELEGATE(7483, upd_b)) + , m_C0(*this, "C0", NETLIB_DELEGATE(c0)) + , m_A1(*this, "A1", NETLIB_DELEGATE(upd_a)) + , m_A2(*this, "A2", NETLIB_DELEGATE(upd_a)) + , m_A3(*this, "A3", NETLIB_DELEGATE(upd_a)) + , m_A4(*this, "A4", NETLIB_DELEGATE(upd_a)) + , m_B1(*this, "B1", NETLIB_DELEGATE(upd_b)) + , m_B2(*this, "B2", NETLIB_DELEGATE(upd_b)) + , m_B3(*this, "B3", NETLIB_DELEGATE(upd_b)) + , m_B4(*this, "B4", NETLIB_DELEGATE(upd_b)) , m_a(*this, "m_a", 0) , m_b(*this, "m_b", 0) , m_lastr(*this, "m_lastr", 0) @@ -36,12 +51,40 @@ namespace netlist , m_power_pins(*this) { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_HANDLERI(upd_a); - NETLIB_HANDLERI(upd_b); + NETLIB_RESETI() + { + m_lastr = 0; + } + + private: + NETLIB_HANDLERI(c0) + { + auto r = static_cast<uint8_t>(m_a + m_b + m_C0()); + + if (r != m_lastr) + { + m_lastr = r; + m_S1.push((r >> 0) & 1, NLTIME_FROM_NS(23)); + m_S2.push((r >> 1) & 1, NLTIME_FROM_NS(23)); + m_S3.push((r >> 2) & 1, NLTIME_FROM_NS(23)); + m_S4.push((r >> 3) & 1, NLTIME_FROM_NS(23)); + m_C4.push((r >> 4) & 1, NLTIME_FROM_NS(23)); + } + } + + NETLIB_HANDLERI(upd_a) + { + m_a = static_cast<uint8_t>((m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3)); + c0(); + } + + NETLIB_HANDLERI(upd_b) + { + m_b = static_cast<uint8_t>((m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3)); + c0(); + } + - protected: logic_input_t m_C0; logic_input_t m_A1; logic_input_t m_A2; @@ -64,66 +107,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(7483_dip, 7483) - { - NETLIB_CONSTRUCTOR_DERIVED(7483_dip, 7483) - { - register_subalias("1", m_A4); - register_subalias("2", m_S3); - register_subalias("3", m_A3); - register_subalias("4", m_B3); - register_subalias("5", "VCC"); - register_subalias("6", m_S2); - register_subalias("7", m_B2); - register_subalias("8", m_A2); - - register_subalias("9", m_S1); - register_subalias("10", m_A1); - register_subalias("11", m_B1); - register_subalias("12", "GND"); - register_subalias("13", m_C0); - register_subalias("14", m_C4); - register_subalias("15", m_S4); - register_subalias("16", m_B4); - } - //NETLIB_RESETI(); - //NETLIB_UPDATEI(); - }; - - NETLIB_RESET(7483) - { - m_lastr = 0; - } - - NETLIB_HANDLER(7483, upd_a) - { - m_a = static_cast<uint8_t>((m_A1() << 0) | (m_A2() << 1) | (m_A3() << 2) | (m_A4() << 3)); - NETLIB_NAME(7483)::update(); - } - - NETLIB_HANDLER(7483, upd_b) - { - m_b = static_cast<uint8_t>((m_B1() << 0) | (m_B2() << 1) | (m_B3() << 2) | (m_B4() << 3)); - NETLIB_NAME(7483)::update(); - } - - NETLIB_UPDATE(7483) - { - auto r = static_cast<uint8_t>(m_a + m_b + m_C0()); - - if (r != m_lastr) - { - m_lastr = r; - m_S1.push((r >> 0) & 1, NLTIME_FROM_NS(23)); - m_S2.push((r >> 1) & 1, NLTIME_FROM_NS(23)); - m_S3.push((r >> 2) & 1, NLTIME_FROM_NS(23)); - m_S4.push((r >> 3) & 1, NLTIME_FROM_NS(23)); - m_C4.push((r >> 4) & 1, NLTIME_FROM_NS(23)); - } - } - NETLIB_DEVICE_IMPL(7483, "TTL_7483", "+A1,+A2,+A3,+A4,+B1,+B2,+B3,+B4,+C0,@VCC,@GND") - NETLIB_DEVICE_IMPL(7483_dip, "TTL_7483_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7483.h b/src/lib/netlist/devices/nld_7483.h deleted file mode 100644 index fba46f32457..00000000000 --- a/src/lib/netlist/devices/nld_7483.h +++ /dev/null @@ -1,49 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7483.h - * - * DM7483: 4-Bit Binary Adder with Fast Carry - * - * +--------------+ - * A4 |1 ++ 16| B4 - * S3 |2 15| S4 - * A3 |3 14| C4 - * B3 |4 7483 13| C0 - * VCC |5 12| GND - * S2 |6 11| B1 - * B2 |7 10| A1 - * A2 |8 9| S1 - * +--------------+ - * - * S = (A + B + C0) & 0x0f - * - * C4 = (A + B + C) > 15 ? 1 : 0 - * - * Naming conventions follow Fairchild Semiconductor datasheet - * - */ - -#ifndef NLD_7483_H_ -#define NLD_7483_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7483(name, cA1, cA2, cA3, cA4, cB1, cB2, cB3, cB4, cCI) \ - NET_REGISTER_DEV(TTL_7483, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, B1, cB1) \ - NET_CONNECT(name, B2, cB2) \ - NET_CONNECT(name, B3, cB3) \ - NET_CONNECT(name, B4, cB4) \ - NET_CONNECT(name, C0, cCI) - -#define TTL_7483_DIP(name) \ - NET_REGISTER_DEV(TTL_7483_DIP, name) - -#endif /* NLD_7483_H_ */ diff --git a/src/lib/netlist/devices/nld_7485.cpp b/src/lib/netlist/devices/nld_7485.cpp index 7cf166a807d..6d53854b4be 100644 --- a/src/lib/netlist/devices/nld_7485.cpp +++ b/src/lib/netlist/devices/nld_7485.cpp @@ -3,24 +3,37 @@ /* * nld_7485.cpp * + * FIXME: Truth table candidate + * + * DM7485: 4-bit Magnitude Comparators + * + * +------------+ + * B3 |1 ++ 16| VCC + * LTIN |2 15| A3 + * EQIN |3 14| B2 + * GTIN |4 7485 13| A2 + * GTOUT |5 12| A1 + * EQOUT |6 11| B1 + * LTOUT |7 10| A0 + * GND |8 9| B0 + * +------------+ + * + * Naming convention attempts to follow Texas Instruments datasheet + * */ -#include "nld_7485.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(7485) { NETLIB_CONSTRUCTOR(7485) - , m_A(*this, {{"A0", "A1", "A2", "A3"}}) - , m_B(*this, {{"B0", "B1", "B2", "B3"}}) - , m_LTIN(*this, "LTIN") - , m_EQIN(*this, "EQIN") - , m_GTIN(*this, "GTIN") + , m_A(*this, {"A0", "A1", "A2", "A3"}, NETLIB_DELEGATE(inputs)) + , m_B(*this, {"B0", "B1", "B2", "B3"}, NETLIB_DELEGATE(inputs)) + , m_LTIN(*this, "LTIN", NETLIB_DELEGATE(inputs)) + , m_EQIN(*this, "EQIN", NETLIB_DELEGATE(inputs)) + , m_GTIN(*this, "GTIN", NETLIB_DELEGATE(inputs)) , m_LTOUT(*this, "LTOUT") , m_EQOUT(*this, "EQOUT") , m_GTOUT(*this, "GTOUT") @@ -28,11 +41,45 @@ namespace netlist { } - NETLIB_UPDATEI(); + private: + // FIXME: Timing + NETLIB_HANDLERI(inputs) + { + for (std::size_t i = 4; i-- > 0; ) + { + if (m_A[i]() > m_B[i]()) + { + update_outputs(1, 0, 0); + return; + } + + if (m_A[i]() < m_B[i]()) + { + update_outputs(0, 1, 0); + return; + } + } - void update_outputs(unsigned gt, unsigned lt, unsigned eq); + // must be == if we got here + if (m_EQIN()) + update_outputs(0, 0, 1); + else if (m_GTIN() && m_LTIN()) + update_outputs(0, 0, 0); + else if (m_GTIN()) + update_outputs(1, 0, 0); + else if (m_LTIN()) + update_outputs(0, 1, 0); + else + update_outputs(1, 1, 0); + } + + void update_outputs(unsigned gt, unsigned lt, unsigned eq) + { + m_GTOUT.push(gt, NLTIME_FROM_NS(23)); + m_LTOUT.push(lt, NLTIME_FROM_NS(23)); + m_EQOUT.push(eq, NLTIME_FROM_NS(23)); + } - protected: object_array_t<logic_input_t, 4> m_A; object_array_t<logic_input_t, 4> m_B; logic_input_t m_LTIN; @@ -44,70 +91,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(7485_dip, 7485) - { - NETLIB_CONSTRUCTOR_DERIVED(7485_dip, 7485) - { - register_subalias("1", m_B[3]); - register_subalias("2", m_LTIN); - register_subalias("3", m_EQIN); - register_subalias("4", m_GTIN); - register_subalias("5", m_GTOUT); - register_subalias("6", m_EQOUT); - register_subalias("7", m_LTOUT); - register_subalias("8", "GND"); - - register_subalias("9", m_B[0]); - register_subalias("10", m_A[0]); - register_subalias("11", m_B[1]); - register_subalias("12", m_A[1]); - register_subalias("13", m_A[2]); - register_subalias("14", m_B[2]); - register_subalias("15", m_A[3]); - register_subalias("16", "VCC"); - - } - }; - - void NETLIB_NAME(7485)::update_outputs(unsigned gt, unsigned lt, unsigned eq) - { - m_GTOUT.push(gt, NLTIME_FROM_NS(23)); - m_LTOUT.push(lt, NLTIME_FROM_NS(23)); - m_EQOUT.push(eq, NLTIME_FROM_NS(23)); - } - - // FIXME: Timing - NETLIB_UPDATE(7485) - { - for (std::size_t i = 4; i-- > 0; ) - { - if (m_A[i]() > m_B[i]()) - { - update_outputs(1, 0, 0); - return; - } - else if (m_A[i]() < m_B[i]()) - { - update_outputs(0, 1, 0); - return; - } - } - - // must be == if we got here - if (m_EQIN()) - update_outputs(0, 0, 1); - else if (m_GTIN() && m_LTIN()) - update_outputs(0, 0, 0); - else if (m_GTIN()) - update_outputs(1, 0, 0); - else if (m_LTIN()) - update_outputs(0, 1, 0); - else - update_outputs(1, 1, 0); - } - NETLIB_DEVICE_IMPL(7485, "TTL_7485", "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN,@VCC,@GND") - NETLIB_DEVICE_IMPL(7485_dip, "TTL_7485_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7485.h b/src/lib/netlist/devices/nld_7485.h deleted file mode 100644 index d8fcb5c7701..00000000000 --- a/src/lib/netlist/devices/nld_7485.h +++ /dev/null @@ -1,47 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_7485.h - * - * DM7485: 4-bit Magnitude Comparators - * - * +------------+ - * B3 |1 ++ 16| VCC - * LTIN |2 15| A3 - * EQIN |3 14| B2 - * GTIN |4 7485 13| A2 - * GTOUT |5 12| A1 - * EQOUT |6 11| B1 - * LTOUT |7 10| A0 - * GND |8 9| B0 - * +------------+ - * - * Naming convention attempts to follow Texas Instruments datasheet - * - */ - -#ifndef NLD_7485_H_ -#define NLD_7485_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7485(name, cA0, cA1, cA2, cA3, cB0, cB1, cB2, cB3, cLTIN, cEQIN, cGTIN) \ - NET_REGISTER_DEV(TTL_7485, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, B0, cB0) \ - NET_CONNECT(name, B1, cB1) \ - NET_CONNECT(name, B2, cB2) \ - NET_CONNECT(name, B3, cB3) \ - NET_CONNECT(name, LTIN, cLTIN) \ - NET_CONNECT(name, EQIN, cEQIN) \ - NET_CONNECT(name, GTIN, cGTIN) - -#define TTL_7485_DIP(name) \ - NET_REGISTER_DEV(TTL_7485_DIP, name) - -#endif /* NLD_7485_H_ */ diff --git a/src/lib/netlist/devices/nld_7490.cpp b/src/lib/netlist/devices/nld_7490.cpp index 3bd06a58a3a..7bcf1f7b214 100644 --- a/src/lib/netlist/devices/nld_7490.cpp +++ b/src/lib/netlist/devices/nld_7490.cpp @@ -1,40 +1,127 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_7490.c + * nld_7490.cpp + * + * DM7490: Decade Counters + * + * +--------------+ + * B |1 ++ 14| A + * R01 |2 13| NC + * R02 |3 12| QA + * NC |4 7490 11| QD + * VCC |5 10| GND + * R91 |6 9| QB + * R92 |7 8| QC + * +--------------+ + * + * Counter Sequence + * + * +-------++----+----+----+----+ + * | COUNT || QD | QC | QB | QA | + * +=======++====+====+====+====+ + * | 0 || 0 | 0 | 0 | 0 | + * | 1 || 0 | 0 | 0 | 1 | + * | 2 || 0 | 0 | 1 | 0 | + * | 3 || 0 | 0 | 1 | 1 | + * | 4 || 0 | 1 | 0 | 0 | + * | 5 || 0 | 1 | 0 | 1 | + * | 6 || 0 | 1 | 1 | 0 | + * | 7 || 0 | 1 | 1 | 1 | + * | 8 || 1 | 0 | 0 | 0 | + * | 9 || 1 | 0 | 0 | 1 | + * +-------++----+----+----+----+ + * + * Note A Output QA is connected to input B for BCD count + * + * Reset Count Function table + * + * +-----+-----+-----+-----++----+----+----+----+ + * | R01 | R02 | R91 | R92 || QD | QC | QB | QA | + * +=====+=====+=====+=====++====+====+====+====+ + * | 1 | 1 | 0 | X || 0 | 0 | 0 | 0 | + * | 1 | 1 | X | 0 || 0 | 0 | 0 | 0 | + * | X | X | 1 | 1 || 1 | 0 | 0 | 1 | + * | X | 0 | X | 0 || COUNT | + * | 0 | X | 0 | X || COUNT | + * | 0 | X | X | 0 || COUNT | + * | X | 0 | 0 | X || COUNT | + * +-----+-----+-----+-----++----+----+----+----+ + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_7490.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices +namespace netlist::devices { + + static constexpr const std::array<const netlist_time, 4> delay = { + NLTIME_FROM_NS(18), + NLTIME_FROM_NS(36) - NLTIME_FROM_NS(18), + NLTIME_FROM_NS(54) - NLTIME_FROM_NS(18), + NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18) + }; + NETLIB_OBJECT(7490) { NETLIB_CONSTRUCTOR(7490) - , m_A(*this, "A") - , m_B(*this, "B") - , m_R1(*this, "R1") - , m_R2(*this, "R2") - , m_R91(*this, "R91") - , m_R92(*this, "R92") + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_R1(*this, "R1", NETLIB_DELEGATE(inputs)) + , m_R2(*this, "R2", NETLIB_DELEGATE(inputs)) + , m_R91(*this, "R91", NETLIB_DELEGATE(inputs)) + , m_R92(*this, "R92", NETLIB_DELEGATE(inputs)) , m_cnt(*this, "m_cnt", 0) , m_last_A(*this, "m_last_A", 0) , m_last_B(*this, "m_last_B", 0) - , m_Q(*this, {{"QA", "QB", "QC", "QD"}}) + , m_Q(*this, {"QA", "QB", "QC", "QD"}) , m_power_pins(*this) { } private: - NETLIB_UPDATEI(); - NETLIB_RESETI(); + NETLIB_HANDLERI(inputs) + { + const netlist_sig_t new_A = m_A(); + const netlist_sig_t new_B = m_B(); - void update_outputs(); + if (m_R91() & m_R92()) + { + m_cnt = 9; + m_Q.push(9, delay); + } + else if (m_R1() & m_R2()) + { + m_cnt = 0; + m_Q.push(0, delay); + } + else + { + if (m_last_A && !new_A) // High - Low + { + m_cnt ^= 1; + m_Q[0].push(m_cnt & 1, delay[0]); + } + if (m_last_B && !new_B) // High - Low + { + m_cnt += 2; + if (m_cnt >= 10) + m_cnt &= 1; /* Output A is not reset! */ + m_Q.push(m_cnt, delay); + } + } + m_last_A = new_A; + m_last_B = new_B; + } + + NETLIB_RESETI() + { + m_cnt = 0; + m_last_A = 0; + m_last_B = 0; + } logic_input_t m_A; logic_input_t m_B; @@ -51,86 +138,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(7490_dip, 7490) - { - NETLIB_CONSTRUCTOR_DERIVED(7490_dip, 7490) - { - register_subalias("1", "B"); - register_subalias("2", "R1"); - register_subalias("3", "R2"); - - // register_subalias("4", ); --> NC - register_subalias("5", "VCC"); - register_subalias("6", "R91"); - register_subalias("7", "R92"); - - register_subalias("8", "QC"); - register_subalias("9", "QB"); - register_subalias("10", "GND"); - register_subalias("11", "QD"); - register_subalias("12", "QA"); - // register_subalias("13", ); --> NC - register_subalias("14", "A"); - } - }; - - NETLIB_RESET(7490) - { - m_cnt = 0; - m_last_A = 0; - m_last_B = 0; - } - - static constexpr const netlist_time delay[4] = - { - NLTIME_FROM_NS(18), - NLTIME_FROM_NS(36) - NLTIME_FROM_NS(18), - NLTIME_FROM_NS(54) - NLTIME_FROM_NS(18), - NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18) - }; - - NETLIB_UPDATE(7490) - { - const netlist_sig_t new_A = m_A(); - const netlist_sig_t new_B = m_B(); - - if (m_R91() & m_R92()) - { - m_cnt = 9; - update_outputs(); - } - else if (m_R1() & m_R2()) - { - m_cnt = 0; - update_outputs(); - } - else - { - if (m_last_A && !new_A) // High - Low - { - m_cnt ^= 1; - m_Q[0].push(m_cnt & 1, delay[0]); - } - if (m_last_B && !new_B) // High - Low - { - m_cnt += 2; - if (m_cnt >= 10) - m_cnt &= 1; /* Output A is not reset! */ - update_outputs(); - } - } - m_last_A = new_A; - m_last_B = new_B; - } - - NETLIB_FUNC_VOID(7490, update_outputs, ()) - { - for (std::size_t i=0; i<4; i++) - m_Q[i].push((m_cnt >> i) & 1, delay[i]); - } - NETLIB_DEVICE_IMPL(7490, "TTL_7490", "+A,+B,+R1,+R2,+R91,+R92,@VCC,@GND") - NETLIB_DEVICE_IMPL(7490_dip, "TTL_7490_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7490.h b/src/lib/netlist/devices/nld_7490.h deleted file mode 100644 index e0479ba14b0..00000000000 --- a/src/lib/netlist/devices/nld_7490.h +++ /dev/null @@ -1,74 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7490.h - * - * DM7490: Decade Counters - * - * +--------------+ - * B |1 ++ 14| A - * R01 |2 13| NC - * R02 |3 12| QA - * NC |4 7490 11| QD - * VCC |5 10| GND - * R91 |6 9| QB - * R92 |7 8| QC - * +--------------+ - * - * Counter Sequence - * - * +-------++----+----+----+----+ - * | COUNT || QD | QC | QB | QA | - * +=======++====+====+====+====+ - * | 0 || 0 | 0 | 0 | 0 | - * | 1 || 0 | 0 | 0 | 1 | - * | 2 || 0 | 0 | 1 | 0 | - * | 3 || 0 | 0 | 1 | 1 | - * | 4 || 0 | 1 | 0 | 0 | - * | 5 || 0 | 1 | 0 | 1 | - * | 6 || 0 | 1 | 1 | 0 | - * | 7 || 0 | 1 | 1 | 1 | - * | 8 || 1 | 0 | 0 | 0 | - * | 9 || 1 | 0 | 0 | 1 | - * +-------++----+----+----+----+ - * - * Note A Output QA is connected to input B for BCD count - * - * Reset Count Function table - * - * +-----+-----+-----+-----++----+----+----+----+ - * | R01 | R02 | R91 | R92 || QD | QC | QB | QA | - * +=====+=====+=====+=====++====+====+====+====+ - * | 1 | 1 | 0 | X || 0 | 0 | 0 | 0 | - * | 1 | 1 | X | 0 || 0 | 0 | 0 | 0 | - * | X | X | 1 | 1 || 1 | 0 | 0 | 1 | - * | X | 0 | X | 0 || COUNT | - * | 0 | X | 0 | X || COUNT | - * | 0 | X | X | 0 || COUNT | - * | X | 0 | 0 | X || COUNT | - * +-----+-----+-----+-----++----+----+----+----+ - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_7490_H_ -#define NLD_7490_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7490(name, cA, cB, cR1, cR2, cR91, cR92) \ - NET_REGISTER_DEV(TTL_7490, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, R1, cR1) \ - NET_CONNECT(name, R2, cR2) \ - NET_CONNECT(name, R91, cR91) \ - NET_CONNECT(name, R92, cR92) - -#define TTL_7490_DIP(name) \ - NET_REGISTER_DEV(TTL_7490_DIP, name) - -#endif /* NLD_7490_H_ */ diff --git a/src/lib/netlist/devices/nld_7492.cpp b/src/lib/netlist/devices/nld_7492.cpp new file mode 100644 index 00000000000..1689ff0dd9d --- /dev/null +++ b/src/lib/netlist/devices/nld_7492.cpp @@ -0,0 +1,135 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_7492.cpp + * + * SN7492: Divide-by-12 Counter + * + * +--------------+ + * B |1 ++ 14| A + * NC |2 13| NC + * NC |3 12| QA + * NC |4 7492 11| QD + * VCC |5 10| GND + * R01 |6 9| QB + * R02 |7 8| QC + * +--------------+ + * + * Counter Sequence + * + * +-------++----+----+----+----+ + * | COUNT || QD | QC | QB | QA | + * +=======++====+====+====+====+ + * | 0 || 0 | 0 | 0 | 0 | + * | 1 || 0 | 0 | 0 | 1 | + * | 2 || 0 | 0 | 1 | 0 | + * | 3 || 0 | 0 | 1 | 1 | + * | 4 || 0 | 1 | 0 | 0 | + * | 5 || 0 | 1 | 0 | 1 | + * | 6 || 1 | 0 | 0 | 0 | + * | 7 || 1 | 0 | 0 | 1 | + * | 8 || 1 | 0 | 1 | 0 | + * | 9 || 1 | 0 | 1 | 1 | + * | 10 || 1 | 1 | 0 | 0 | + * | 11 || 1 | 1 | 0 | 1 | + * +-------++----+----+----+----+ + * + * Note A Output QA is connected to input B + * + * Reset Count Function table + * + * +-----+-----++----+----+----+----+ + * | R01 | R02 || QD | QC | QB | QA | + * +=====+=====++====+====+====+====+ + * | 1 | 1 || 0 | 0 | 0 | 0 | + * | 0 | X || COUNT | + * | X | 0 || COUNT | + * +-----+-----++----+----+----+----+ + * + * Naming conventions follow Texas Instruments datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + static constexpr const std::array<const netlist_time, 4> delay = + { + NLTIME_FROM_NS(18), + NLTIME_FROM_NS(36) - NLTIME_FROM_NS(18), + NLTIME_FROM_NS(54) - NLTIME_FROM_NS(18), + NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18) + }; + + NETLIB_OBJECT(7492) + { + NETLIB_CONSTRUCTOR(7492) + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_R1(*this, "R1", NETLIB_DELEGATE(inputs)) + , m_R2(*this, "R2", NETLIB_DELEGATE(inputs)) + , m_cnt(*this, "m_cnt", 0) + , m_last_A(*this, "m_last_A", 0) + , m_last_B(*this, "m_last_B", 0) + , m_Q(*this, {"QA", "QB", "QC", "QD"}) + , m_power_pins(*this) + { + } + + private: + + NETLIB_HANDLERI(inputs) + { + const netlist_sig_t new_A = m_A(); + const netlist_sig_t new_B = m_B(); + + if (m_R1() & m_R2()) + { + m_cnt = 0; + m_Q.push(0, delay); + } + else + { + if (m_last_A && !new_A) // High - Low + { + m_cnt ^= 1; + m_Q[0].push(m_cnt & 1, delay[0]); + } + if (m_last_B && !new_B) // High - Low + { + m_cnt += 2; + if (m_cnt == 6) + m_cnt = 8; + if (m_cnt == 14) + m_cnt = 0; + m_Q.push(m_cnt, delay); + } + } + m_last_A = new_A; + m_last_B = new_B; + } + + NETLIB_RESETI() + { + m_cnt = 0; + m_last_A = 0; + m_last_B = 0; + } + + logic_input_t m_A; + logic_input_t m_B; + logic_input_t m_R1; + logic_input_t m_R2; + + state_var_u8 m_cnt; + state_var<netlist_sig_t> m_last_A; + state_var<netlist_sig_t> m_last_B; + + object_array_t<logic_output_t, 4> m_Q; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(7492, "TTL_7492", "+A,+B,+R1,+R2,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp index 003c3291096..a6d80fd551b 100644 --- a/src/lib/netlist/devices/nld_7493.cpp +++ b/src/lib/netlist/devices/nld_7493.cpp @@ -1,36 +1,77 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* * nld_7493.cpp * + * DM7493: Binary Counters + * + * +--------------+ + * B |1 ++ 14| A + * R01 |2 13| NC + * R02 |3 12| QA + * NC |4 7493 11| QD + * VCC |5 10| GND + * NC |6 9| QB + * NC |7 8| QC + * +--------------+ + * + * Counter Sequence + * + * +-------++----+----+----+----+ + * | COUNT || QD | QC | QB | QA | + * +=======++====+====+====+====+ + * | 0 || 0 | 0 | 0 | 0 | + * | 1 || 0 | 0 | 0 | 1 | + * | 2 || 0 | 0 | 1 | 0 | + * | 3 || 0 | 0 | 1 | 1 | + * | 4 || 0 | 1 | 0 | 0 | + * | 5 || 0 | 1 | 0 | 1 | + * | 6 || 0 | 1 | 1 | 0 | + * | 7 || 0 | 1 | 1 | 1 | + * | 8 || 1 | 0 | 0 | 0 | + * | 9 || 1 | 0 | 0 | 1 | + * | 10 || 1 | 0 | 1 | 0 | + * | 11 || 1 | 0 | 1 | 1 | + * | 12 || 1 | 1 | 0 | 0 | + * | 13 || 1 | 1 | 0 | 1 | + * | 14 || 1 | 1 | 1 | 0 | + * | 15 || 1 | 1 | 1 | 1 | + * +-------++----+----+----+----+ + * + * Note C Output QA is connected to input B + * + * Reset Count Function table + * + * +-----+-----++----+----+----+----+ + * | R01 | R02 || QD | QC | QB | QA | + * +=====+=====++====+====+====+====+ + * | 1 | 1 || 0 | 0 | 0 | 0 | + * | 0 | X || COUNT | + * | X | 0 || COUNT | + * +-----+-----++----+----+----+----+ + * + * Naming conventions follow National Semiconductor datasheet + * */ -#include "nld_7493.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices - { - static constexpr const netlist_time out_delay = NLTIME_FROM_NS(18); - static constexpr const netlist_time out_delay2 = NLTIME_FROM_NS(36); - static constexpr const netlist_time out_delay3 = NLTIME_FROM_NS(54); +namespace netlist::devices { + + static constexpr const std::array<const netlist_time, 3> out_delay { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54) }; NETLIB_OBJECT(7493) { NETLIB_CONSTRUCTOR(7493) - , m_R1(*this, "R1") - , m_R2(*this, "R2") - , m_a(*this, "_m_a", 0) - , m_bcd(*this, "_m_b", 0) - , m_CLKA(*this, "CLKA", NETLIB_DELEGATE(7493, updA)) - , m_CLKB(*this, "CLKB", NETLIB_DELEGATE(7493, updB)) + , m_CLKA(*this, "CLKA", NETLIB_DELEGATE(updA)) + , m_CLKB(*this, "CLKB", NETLIB_DELEGATE(updB)) , m_QA(*this, "QA") - , m_QB(*this, "QB") - , m_QC(*this, "QC") - , m_QD(*this, "QD") + , m_QBCD(*this, {"QB", "QC", "QD"}) + , m_a(*this, "m_a", 0) + , m_bcd(*this, "m_b", 0) + , m_R1(*this, "R1", NETLIB_DELEGATE(inputs)) + , m_R2(*this, "R2", NETLIB_DELEGATE(inputs)) , m_power_pins(*this) { } @@ -43,9 +84,9 @@ namespace netlist m_CLKB.set_state(logic_t::STATE_INP_HL); } - NETLIB_UPDATEI() + NETLIB_HANDLERI(inputs) { - if (!(m_R1() & m_R2())) + if (!(m_R1() && m_R2())) { m_CLKA.activate_hl(); m_CLKB.activate_hl(); @@ -55,9 +96,7 @@ namespace netlist m_CLKA.inactivate(); m_CLKB.inactivate(); m_QA.push(0, NLTIME_FROM_NS(40)); - m_QB.push(0, NLTIME_FROM_NS(40)); - m_QC.push(0, NLTIME_FROM_NS(40)); - m_QD.push(0, NLTIME_FROM_NS(40)); + m_QBCD.push(0, NLTIME_FROM_NS(40)); m_a = m_bcd = 0; } } @@ -65,59 +104,30 @@ namespace netlist NETLIB_HANDLERI(updA) { m_a ^= 1; - m_QA.push(m_a, out_delay); + m_QA.push(m_a, out_delay[0]); } NETLIB_HANDLERI(updB) { - auto cnt = (++m_bcd &= 0x07); - m_QD.push((cnt >> 2) & 1, out_delay3); - m_QC.push((cnt >> 1) & 1, out_delay2); - m_QB.push(cnt & 1, out_delay); + const auto cnt(++m_bcd &= 0x07); + m_QBCD.push(cnt, out_delay); } - logic_input_t m_R1; - logic_input_t m_R2; - - state_var_sig m_a; - state_var_u8 m_bcd; - logic_input_t m_CLKA; logic_input_t m_CLKB; logic_output_t m_QA; - logic_output_t m_QB; - logic_output_t m_QC; - logic_output_t m_QD; - nld_power_pins m_power_pins; - }; + object_array_t<logic_output_t, 3> m_QBCD; - NETLIB_OBJECT_DERIVED(7493_dip, 7493) - { - NETLIB_CONSTRUCTOR_DERIVED(7493_dip, 7493) - { - register_subalias("1", "CLKB"); - register_subalias("2", "R1"); - register_subalias("3", "R2"); - - // register_subalias("4", ); --> NC - register_subalias("5", "VCC"); - // register_subalias("6", ); --> NC - // register_subalias("7", ); --> NC - - register_subalias("8", "QC"); - register_subalias("9", "QB"); - register_subalias("10", "GND"); - register_subalias("11", "QD"); - register_subalias("12", "QA"); - // register_subalias("13", ); -. NC - register_subalias("14", "CLKA"); - } - }; + state_var<unsigned> m_a; + state_var<unsigned> m_bcd; + + logic_input_t m_R1; + logic_input_t m_R2; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(7493, "TTL_7493", "+CLKA,+CLKB,+R1,+R2,@VCC,@GND") - NETLIB_DEVICE_IMPL(7493_dip, "TTL_7493_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7493.h b/src/lib/netlist/devices/nld_7493.h deleted file mode 100644 index 3498d216b08..00000000000 --- a/src/lib/netlist/devices/nld_7493.h +++ /dev/null @@ -1,74 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_7493.h - * - * DM7493: Binary Counters - * - * +--------------+ - * B |1 ++ 14| A - * R01 |2 13| NC - * R02 |3 12| QA - * NC |4 7493 11| QD - * VCC |5 10| GND - * NC |6 9| QB - * NC |7 8| QC - * +--------------+ - * - * Counter Sequence - * - * +-------++----+----+----+----+ - * | COUNT || QD | QC | QB | QA | - * +=======++====+====+====+====+ - * | 0 || 0 | 0 | 0 | 0 | - * | 1 || 0 | 0 | 0 | 1 | - * | 2 || 0 | 0 | 1 | 0 | - * | 3 || 0 | 0 | 1 | 1 | - * | 4 || 0 | 1 | 0 | 0 | - * | 5 || 0 | 1 | 0 | 1 | - * | 6 || 0 | 1 | 1 | 0 | - * | 7 || 0 | 1 | 1 | 1 | - * | 8 || 1 | 0 | 0 | 0 | - * | 9 || 1 | 0 | 0 | 1 | - * | 10 || 1 | 0 | 1 | 0 | - * | 11 || 1 | 0 | 1 | 1 | - * | 12 || 1 | 1 | 0 | 0 | - * | 13 || 1 | 1 | 0 | 1 | - * | 14 || 1 | 1 | 1 | 0 | - * | 15 || 1 | 1 | 1 | 1 | - * +-------++----+----+----+----+ - * - * Note C Output QA is connected to input B - * - * Reset Count Function table - * - * +-----+-----++----+----+----+----+ - * | R01 | R02 || QD | QC | QB | QA | - * +=====+=====++====+====+====+====+ - * | 1 | 1 || 0 | 0 | 0 | 0 | - * | 0 | X || COUNT | - * | X | 0 || COUNT | - * +-----+-----++----+----+----+----+ - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_7493_H_ -#define NLD_7493_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7493(name, cCLKA, cCLKB, cR1, cR2) \ - NET_REGISTER_DEV(TTL_7493, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLKA, cCLKA) \ - NET_CONNECT(name, CLKB, cCLKB) \ - NET_CONNECT(name, R1, cR1) \ - NET_CONNECT(name, R2, cR2) - -#define TTL_7493_DIP(name) \ - NET_REGISTER_DEV(TTL_7493_DIP, name) - -#endif /* NLD_7493_H_ */ diff --git a/src/lib/netlist/devices/nld_7497.cpp b/src/lib/netlist/devices/nld_7497.cpp index e9ac7833191..7d80c580d14 100644 --- a/src/lib/netlist/devices/nld_7497.cpp +++ b/src/lib/netlist/devices/nld_7497.cpp @@ -1,4 +1,4 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Sergey Svishchev /* * nld_7497.cpp @@ -7,50 +7,125 @@ * * - STRB and EN * - Timing + * + * SN7497: Synchronous 6-Bit Binary Rate Multiplier + * + * +--------------+ + * B1 |1 16| VCC + * B4 |2 15| B3 + * B5 |3 14| B2 + * B0 |4 7497 13| CLR + * Z |5 12| UNITY/CAS + * Y |6 11| ENin (EN) + * ENout |7 10| STRB + * GND |8 9| CLK + * +--------------+ + * + * Naming conventions follow TI datasheet + * + * The counter is enabled when the clear, strobe, and enable inputs are low. + * + * When the rate input is binary 0 (all rate inputs low), Z remains high [and Y low]. + * + * The unity/cascade input, when connected to the clock input, passes + * clock frequency (inverted) to the Y output when the rate input/decoding + * gates are inhibited by the strobe. + * + * When CLR is H, states of CLK and STRB can affect Y and Z. Default are + * Y L, Z H, ENout H. + * + * Unity/cascade is used to inhibit output Y (UNITY L -> Y H) */ -#include "nld_7497.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" -namespace netlist -{ - namespace devices - { +namespace netlist::devices { + + static constexpr const std::array<netlist_time, 2> out_delay_CLK_Y = { NLTIME_FROM_NS(20), NLTIME_FROM_NS(26) }; // tPHL, tPLH + static constexpr const std::array<netlist_time, 2> out_delay_CLK_Z = { NLTIME_FROM_NS(17), NLTIME_FROM_NS(12) }; - static constexpr const netlist_time out_delay_CLK_Y[2] = { NLTIME_FROM_NS(20), NLTIME_FROM_NS(26) }; // tPHL, tPLH - static constexpr const netlist_time out_delay_CLK_Z[2] = { NLTIME_FROM_NS(17), NLTIME_FROM_NS(12) }; + // FIXME: room for improvement -> clock handling NETLIB_OBJECT(7497) { NETLIB_CONSTRUCTOR(7497) - , m_B(*this, {{"B5", "B4", "B3", "B2", "B1", "B0"}}) - , m_CLK(*this, "CLK", NETLIB_DELEGATE(7497, clk_strb)) - , m_STRBQ(*this, "STRBQ", NETLIB_DELEGATE(7497, clk_strb)) - , m_ENQ(*this, "ENQ") - , m_UNITYQ(*this, "UNITYQ", NETLIB_DELEGATE(7497, unity)) - , m_CLR(*this, "CLR", NETLIB_DELEGATE(7497, clr)) + , m_B(*this, {"B5", "B4", "B3", "B2", "B1", "B0"}, NETLIB_DELEGATE(inputs)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk_strb)) + , m_STRBQ(*this, "STRBQ", NETLIB_DELEGATE(clk_strb)) + , m_ENQ(*this, "ENQ", NETLIB_DELEGATE(inputs)) + , m_UNITYQ(*this, "UNITYQ", NETLIB_DELEGATE(unity)) + , m_CLR(*this, "CLR", NETLIB_DELEGATE(clr)) , m_Y(*this, "Y") , m_ZQ(*this, "ZQ") , m_ENOUTQ(*this, "ENOUTQ") , m_cnt(*this, "_m_cnt", 0) , m_rate(*this, "_m_rate", 0) , m_state(*this, "_m_state", 0) - , m_lastclock(*this, "_m_lastclock", 0) + , m_last_clock(*this, "_m_lastclock", 0) , m_power_pins(*this) { } private: - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_cnt = 0; + m_rate = 0; + m_last_clock = 0; + } - NETLIB_HANDLERI(noop) { } - NETLIB_HANDLERI(unity); - NETLIB_HANDLERI(clr); - NETLIB_HANDLERI(clk_strb); + NETLIB_HANDLERI(unity) + { + newstate (m_state); + } + + NETLIB_HANDLERI(clr) + { + m_cnt = 0; + clk_strb(); + } + + NETLIB_HANDLERI(clk_strb) + { + netlist_sig_t clk = m_CLK(); + + if (!m_last_clock && clk && !m_ENQ() && !m_CLR()) + { + m_cnt++; + m_cnt &= 63; + } + m_last_clock = clk; + + const netlist_sig_t clk_strb = (clk ^ 1) & (m_STRBQ() ^ 1); + + const netlist_sig_t cntQ = m_cnt; + + // NOR GATE + netlist_sig_t p1 = ((cntQ & 63) == 31 && (m_rate & 32)) || + ((cntQ & 31) == 15 && (m_rate & 16)) || + ((cntQ & 15) == 7 && (m_rate & 8)) || + ((cntQ & 7) == 3 && (m_rate & 4)) || + ((cntQ & 3) == 1 && (m_rate & 2)) || + ((cntQ & 1) == 0 && (m_rate & 1)); + + p1 = (p1 & clk_strb) ^ 1; + + newstate(p1); + + // NAND gate + if ((m_cnt == 63) && !m_ENQ()) + m_ENOUTQ.push(0, out_delay_CLK_Y[0]); // XXX timing + else + m_ENOUTQ.push(1, out_delay_CLK_Y[1]); + + } + + NETLIB_HANDLERI(inputs) + { + m_rate = rate(); + clk_strb(); + } - protected: object_array_t<logic_input_t, 6> m_B; logic_input_t m_CLK; logic_input_t m_STRBQ; @@ -65,7 +140,7 @@ namespace netlist state_var_u8 m_cnt; state_var_u8 m_rate; state_var_sig m_state; - state_var_sig m_lastclock; + state_var_sig m_last_clock; nld_power_pins m_power_pins; void newstate(const netlist_sig_t state) @@ -88,92 +163,6 @@ namespace netlist } }; - NETLIB_RESET(7497) - { - m_cnt = 0; - m_rate = 0; - m_lastclock = 0; - } - - NETLIB_UPDATE(7497) - { - m_rate = rate(); - clk_strb(); - } - - NETLIB_HANDLER(7497, unity) - { - newstate (m_state); - } - - NETLIB_HANDLER(7497, clr) - { - m_cnt = 0; - clk_strb(); - } - - NETLIB_HANDLER(7497, clk_strb) - { - netlist_sig_t clk = m_CLK(); - - if (!m_lastclock && clk && !m_ENQ() && !m_CLR()) - { - m_cnt++; - m_cnt &= 63; - } - m_lastclock = clk; - - const netlist_sig_t clk_strb = (clk ^ 1) & (m_STRBQ() ^ 1); - - const netlist_sig_t cntQ = m_cnt; - - // NOR GATE - netlist_sig_t p1 = ((cntQ & 63) == 31 && (m_rate & 32)) || - ((cntQ & 31) == 15 && (m_rate & 16)) || - ((cntQ & 15) == 7 && (m_rate & 8)) || - ((cntQ & 7) == 3 && (m_rate & 4)) || - ((cntQ & 3) == 1 && (m_rate & 2)) || - ((cntQ & 1) == 0 && (m_rate & 1)); - - p1 = (p1 & clk_strb) ^ 1; - - newstate(p1); - - // NAND gate - if ((m_cnt == 63) && !m_ENQ()) - m_ENOUTQ.push(0, out_delay_CLK_Y[0]); // XXX timing - else - m_ENOUTQ.push(1, out_delay_CLK_Y[1]); - - } - - NETLIB_OBJECT_DERIVED(7497_dip, 7497) - { - NETLIB_CONSTRUCTOR_DERIVED(7497_dip, 7497) - { - register_subalias("1", m_B[4]); // B0 - register_subalias("2", m_B[1]); // B4 - register_subalias("3", m_B[0]); // B5 - register_subalias("4", m_B[5]); // B0 - register_subalias("5", m_ZQ); - register_subalias("6", m_Y); - register_subalias("7", m_ENOUTQ); - register_subalias("8", "GND"); - - register_subalias("9", m_CLK); - register_subalias("10", m_STRBQ); - register_subalias("11", m_UNITYQ); - register_subalias("12", m_ENQ); - register_subalias("13", m_CLR); - register_subalias("14", m_B[3]); // B2 - register_subalias("15", m_B[2]); // B3 - register_subalias("16", "VCC"); - } - }; - - - NETLIB_DEVICE_IMPL(7497, "TTL_7497", "+CLK,+STRBQ,+ENQ,+UNITYQ,+CLR,+B0,+B1,+B2,+B3,+B4,+B5, @VCC, @GND") - NETLIB_DEVICE_IMPL(7497_dip, "TTL_7497_DIP", "") + NETLIB_DEVICE_IMPL(7497, "TTL_7497", "+CLK,+STRBQ,+ENQ,+UNITYQ,+CLR,+B0,+B1,+B2,+B3,+B4,+B5,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_7497.h b/src/lib/netlist/devices/nld_7497.h deleted file mode 100644 index 3e3e2e89e40..00000000000 --- a/src/lib/netlist/devices/nld_7497.h +++ /dev/null @@ -1,59 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Sergey Svishchev -/* - * nld_7497.h - * - * SN7497: Synchronous 6-Bit Binary Rate Multiplier - * - * +--------------+ - * B1 |1 16| VCC - * B4 |2 15| B3 - * B5 |3 14| B2 - * B0 |4 7497 13| CLR - * Z |5 12| UNITY/CAS - * Y |6 11| ENin (EN) - * ENout |7 10| STRB - * GND |8 9| CLK - * +--------------+ - * - * Naming conventions follow TI datasheet - * - * The counter is enabled when the clear, strobe, and enable inputs are low. - * - * When the rate input is binary 0 (all rate inputs low), Z remains high [and Y low]. - * - * The unity/cascade input, when connected to the clock input, passes - * clock frequency (inverted) to the Y output when the rate input/decoding - * gates are inhibited by the strobe. - * - * When CLR is H, states of CLK and STRB can affect Y and Z. Default are - * Y L, Z H, ENout H. - * - * Unity/cascade is used to inhibit output Y (UNITY L -> Y H) - */ - -#ifndef NLD_7497_H_ -#define NLD_7497_H_ - -#include "netlist/nl_setup.h" - -#define TTL_7497(name, cCLK, cSTRB, cEN, cUNITY, cCLR, cB0, cB1, cB2, cB3, cB4, cB5) \ - NET_REGISTER_DEV(TTL_7497, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, STRBQ, cSTRB) \ - NET_CONNECT(name, ENQ, cEN) \ - NET_CONNECT(name, UNITYQ,cUNITY) \ - NET_CONNECT(name, CLR, cCLR) \ - NET_CONNECT(name, B0, cB0) \ - NET_CONNECT(name, B1, cB1) \ - NET_CONNECT(name, B2, cB2) \ - NET_CONNECT(name, B3, cB3) \ - NET_CONNECT(name, B4, cB4) \ - NET_CONNECT(name, B5, cB5) - -#define TTL_7497_DIP(name) \ - NET_REGISTER_DEV(TTL_7497_DIP, name) - -#endif /* NLD_7497_H_ */ diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp index 20798f7da69..11cbc8aeb0d 100644 --- a/src/lib/netlist/devices/nld_74ls629.cpp +++ b/src/lib/netlist/devices/nld_74ls629.cpp @@ -1,7 +1,27 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_SN74LS629.c + * nld_SN74LS629.cpp + * + * SN74LS629: VOLTAGE-CONTROLLED OSCILLATORS + * + * +--------------+ + * 2FC |1 ++ 16| VCC + * 1FC |2 15| QSC VCC + * 1RNG |3 14| 2RNG + * 1CX1 |4 74LS629 13| 2CX1 + * 1CX2 |5 12| 2CX2 + * 1ENQ |6 11| 2ENQ + * 1Y |7 10| 2Y + * OSC GND |8 9| GND + * +--------------+ + * + * Naming conventions follow Texas Instruments datasheet + * + * NOTE: The CX1 and CX2 pins are not connected! + * The capacitor value has to be specified as a parameter. + * There are more comments on the challenges of emulating this + * chip in the *.c file * */ @@ -38,35 +58,22 @@ * Then just use that to toggle a waveform. */ +#include "analog/nlid_twoterm.h" -#include "nld_74ls629.h" -#include "netlist/analog/nlid_twoterm.h" +namespace netlist::devices { -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(SN74LS629clk) + struct SN74LS629clk { - NETLIB_CONSTRUCTOR(SN74LS629clk) - , m_FB(*this, "FB") - , m_Y(*this, "Y") - , m_enableq(*this, "m_enableq", 1) - , m_out(*this, "m_out", 0) - , m_inc(*this, "m_inc", netlist_time::zero()) - { - connect(m_FB, m_Y); - } - - NETLIB_RESETI() + SN74LS629clk(device_t &owner) + : m_FB(owner, "FB", nl_delegate(&SN74LS629clk::fb, this)) + , m_Y(owner, "Y") + , m_enableq(owner, "m_enableq", 0) + , m_out(owner, "m_out", 0) + , m_inc(owner, "m_inc", netlist_time::zero()) { - m_enableq = 0; - m_out = 0; - m_inc = netlist_time::zero(); + owner.connect("FB", "Y"); } - NETLIB_UPDATEI(); - public: logic_input_t m_FB; logic_output_t m_Y; @@ -74,168 +81,127 @@ namespace netlist state_var<netlist_sig_t> m_enableq; state_var<netlist_sig_t> m_out; state_var<netlist_time> m_inc; + + private: + NETLIB_HANDLERI(fb) + { + if (!m_enableq) + { + m_out = m_out ^ 1; + m_Y.push(m_out, m_inc); + } + else + { + m_Y.push(1, m_inc); + } + } + }; NETLIB_OBJECT(SN74LS629) { NETLIB_CONSTRUCTOR(SN74LS629) - , m_clock(*this, "OSC") + , m_clock(*this) , m_R_FC(*this, "R_FC") , m_R_RNG(*this, "R_RNG") - , m_ENQ(*this, "ENQ") - , m_RNG(*this, "RNG") - , m_FC(*this, "FC") - , m_CAP(*this, "CAP", 1e-6) + , m_ENQ(*this, "ENQ", NETLIB_DELEGATE(inputs)) + , m_RNG(*this, "RNG", NETLIB_DELEGATE(inputs)) + , m_FC(*this, "FC", NETLIB_DELEGATE(inputs)) + , m_CAP(*this, "CAP", nlconst::magic(1e-6)) + , m_power_pins(*this) + , m_power_pins_osc(*this, "OSCVCC", "OSCGND") { - register_subalias("GND", m_R_FC.m_N); + connect("OSCGND", "R_FC.2"); - connect(m_FC, m_R_FC.m_P); - connect(m_RNG, m_R_RNG.m_P); - connect(m_R_FC.m_N, m_R_RNG.m_N); - - register_subalias("Y", m_clock.m_Y); + connect("FC", "R_FC.1"); + connect("RNG", "R_RNG.1"); + connect("R_FC.2", "R_RNG.2"); } + private: NETLIB_RESETI() { - m_R_FC.set_R(90000.0); - m_R_RNG.set_R(90000.0); - m_clock.reset(); + m_R_FC().set_R( nlconst::magic(90000.0)); + m_R_RNG().set_R(nlconst::magic(90000.0)); } - NETLIB_UPDATEI(); NETLIB_UPDATE_PARAMI() { /* update param may be called from anywhere, update_dev(time) is not a good idea */ } - public: - NETLIB_SUB(SN74LS629clk) m_clock; - analog::NETLIB_SUB(R_base) m_R_FC; - analog::NETLIB_SUB(R_base) m_R_RNG; + SN74LS629clk m_clock; + NETLIB_SUB_NS(analog, R_base) m_R_FC; + NETLIB_SUB_NS(analog, R_base) m_R_RNG; logic_input_t m_ENQ; analog_input_t m_RNG; analog_input_t m_FC; - param_double_t m_CAP; - }; - - NETLIB_OBJECT(SN74LS629_dip) - { - NETLIB_CONSTRUCTOR(SN74LS629_dip) - , m_A(*this, "A") - , m_B(*this, "B") - { - register_subalias("1", m_B.m_FC); - register_subalias("2", m_A.m_FC); - register_subalias("3", m_A.m_RNG); - - register_subalias("6", m_A.m_ENQ); - register_subalias("7", m_A.m_clock.m_Y); + param_fp_t m_CAP; + nld_power_pins m_power_pins; + nld_power_pins m_power_pins_osc; - register_subalias("8", m_A.m_R_FC.m_N); - register_subalias("9", m_A.m_R_FC.m_N); - connect(m_A.m_R_FC.m_N, m_B.m_R_FC.m_N); - - register_subalias("10", m_B.m_clock.m_Y); - - register_subalias("11", m_B.m_ENQ); - register_subalias("14", m_B.m_RNG); - } - - NETLIB_UPDATEI() { } - - NETLIB_RESETI() + NETLIB_HANDLERI(inputs) { - m_A.reset(); - m_B.reset(); + { + // recompute + nl_fptype v_freq = m_FC(); + nl_fptype v_rng = m_RNG(); + + /* coefficients */ + const nl_fptype k1 = nlconst::magic( 1.9904769024796283E+03); + const nl_fptype k2 = nlconst::magic( 1.2070059213983407E+03); + const nl_fptype k3 = nlconst::magic( 1.3266985579561108E+03); + const nl_fptype k4 = nlconst::magic(-1.5500979825922698E+02); + const nl_fptype k5 = nlconst::magic( 2.8184536266938172E+00); + const nl_fptype k6 = nlconst::magic(-2.3503421582744556E+02); + const nl_fptype k7 = nlconst::magic(-3.3836786704527788E+02); + const nl_fptype k8 = nlconst::magic(-1.3569136703258670E+02); + const nl_fptype k9 = nlconst::magic( 2.9914575453819188E+00); + const nl_fptype k10 = nlconst::magic( 1.6855569086173170E+00); + + /* scale due to input resistance */ + + /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */ + + nl_fptype v_freq_2 = v_freq * v_freq; + nl_fptype v_freq_3 = v_freq_2 * v_freq; + nl_fptype v_freq_4 = v_freq_3 * v_freq; + nl_fptype freq = k1; + freq += k2 * v_freq; + freq += k3 * v_freq_2; + freq += k4 * v_freq_3; + freq += k5 * v_freq_4; + freq += k6 * v_rng; + freq += k7 * v_rng * v_freq; + freq += k8 * v_rng * v_freq_2; + freq += k9 * v_rng * v_freq_3; + freq += k10 * v_rng * v_freq_4; + + freq *= nlconst::magic(0.1e-6) / m_CAP(); + + // FIXME: we need a possibility to remove entries from queue ... + // or an exact model ... + m_clock.m_inc = netlist_time::from_fp(nlconst::half() / freq); + } + + if (!m_clock.m_enableq && m_ENQ()) + { + m_clock.m_enableq = 1; + m_clock.m_out = m_clock.m_out ^ 1; + m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1)); + } + else if (m_clock.m_enableq && !m_ENQ()) + { + m_clock.m_enableq = 0; + m_clock.m_out = m_clock.m_out ^ 1; + m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1)); + } } - private: - NETLIB_SUB(SN74LS629) m_A; - NETLIB_SUB(SN74LS629) m_B; }; + NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP,@VCC,@GND") - NETLIB_UPDATE(SN74LS629clk) - { - if (!m_enableq) - { - m_out = m_out ^ 1; - m_Y.push(m_out, m_inc); - } - else - { - m_Y.push(1, m_inc); - } - } - - NETLIB_UPDATE(SN74LS629) - { - { - // recompute - nl_double freq; - nl_double v_freq_2, v_freq_3, v_freq_4; - nl_double v_freq = m_FC(); - nl_double v_rng = m_RNG(); - - /* coefficients */ - const nl_double k1 = 1.9904769024796283E+03; - const nl_double k2 = 1.2070059213983407E+03; - const nl_double k3 = 1.3266985579561108E+03; - const nl_double k4 = -1.5500979825922698E+02; - const nl_double k5 = 2.8184536266938172E+00; - const nl_double k6 = -2.3503421582744556E+02; - const nl_double k7 = -3.3836786704527788E+02; - const nl_double k8 = -1.3569136703258670E+02; - const nl_double k9 = 2.9914575453819188E+00; - const nl_double k10 = 1.6855569086173170E+00; - - /* scale due to input resistance */ - - /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */ - - v_freq_2 = v_freq * v_freq; - v_freq_3 = v_freq_2 * v_freq; - v_freq_4 = v_freq_3 * v_freq; - freq = k1; - freq += k2 * v_freq; - freq += k3 * v_freq_2; - freq += k4 * v_freq_3; - freq += k5 * v_freq_4; - freq += k6 * v_rng; - freq += k7 * v_rng * v_freq; - freq += k8 * v_rng * v_freq_2; - freq += k9 * v_rng * v_freq_3; - freq += k10 * v_rng * v_freq_4; - - freq *= plib::constants<nl_double>::cast(0.1e-6) / m_CAP(); - - // FIXME: we need a possibility to remove entries from queue ... - // or an exact model ... - m_clock.m_inc = netlist_time::from_double(0.5 / freq); - //m_clock.update(); - - //NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq)); - } - - if (!m_clock.m_enableq && m_ENQ()) - { - m_clock.m_enableq = 1; - m_clock.m_out = m_clock.m_out ^ 1; - m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1)); - } - else if (m_clock.m_enableq && !m_ENQ()) - { - m_clock.m_enableq = 0; - m_clock.m_out = m_clock.m_out ^ 1; - m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1)); - } - } - - NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP") - NETLIB_DEVICE_IMPL(SN74LS629_dip, "SN74LS629_DIP", "1.CAP1,2.CAP2") - - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_74ls629.h b/src/lib/netlist/devices/nld_74ls629.h deleted file mode 100644 index 30d15d70865..00000000000 --- a/src/lib/netlist/devices/nld_74ls629.h +++ /dev/null @@ -1,42 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_74LS629.h - * - * SN74LS629: VOLTAGE-CONTROLLED OSCILLATORS - * - * +--------------+ - * 2FC |1 ++ 16| VCC - * 1FC |2 15| QSC VCC - * 1RNG |3 14| 2RNG - * 1CX1 |4 74LS629 13| 2CX1 - * 1CX2 |5 12| 2CX2 - * 1ENQ |6 11| 2ENQ - * 1Y |7 10| 2Y - * OSC GND |8 9| GND - * +--------------+ - * - * Naming conventions follow Texas Instruments datasheet - * - * NOTE: The CX1 and CX2 pins are not connected! - * The capacitor value has to be specified as a parameter. - * There are more comments on the challenges of emulating this - * chip in the *.c file - * - */ - -#ifndef NLD_74LS629_H_ -#define NLD_74LS629_H_ - -#include "netlist/nl_setup.h" - -#define SN74LS629(name, p_cap) \ - NET_REGISTER_DEV(SN74LS629, name) \ - NETDEV_PARAMI(name, CAP, p_cap) - -#define SN74LS629_DIP(name, p_cap1, p_cap2) \ - NET_REGISTER_DEV(SN74LS629_DIP, name) \ - NETDEV_PARAMI(name, 1.CAP, p_cap1) \ - NETDEV_PARAMI(name, 2.CAP, p_cap2) - -#endif /* NLD_74LS629_H_ */ diff --git a/src/lib/netlist/devices/nld_8277.cpp b/src/lib/netlist/devices/nld_8277.cpp new file mode 100644 index 00000000000..c1c59e360fd --- /dev/null +++ b/src/lib/netlist/devices/nld_8277.cpp @@ -0,0 +1,166 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/* + * nld_8277.cpp + * + * 8277: Dual 8-Bit Shift Register + * + * +--------------+ + * RESET |1 ++ 16| VCC + * /Q7A |2 15| /Q7B + * Q7A |3 14| Q7B + * DSA |4 8277 13| DSB + * D1A |5 12| D1B + * D0A |6 11| D0B + * CLKA |7 10| CLKB + * GND |8 9| CLK + * +--------------+ + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + NETLIB_OBJECT(8277_shifter) + { + NETLIB_CONSTRUCTOR(8277_shifter) + , m_D0(*this, "D0", NETLIB_DELEGATE(inputs)) + , m_D1(*this, "D1", NETLIB_DELEGATE(inputs)) + , m_DS(*this, "DS", NETLIB_DELEGATE(inputs)) + , m_buffer(*this, "m_buffer", 0) + , m_Q7(*this, "Q7") + , m_Q7Q(*this, "Q7Q") + , m_power_pins(*this) + { + } + + public: + void reset_shifter() noexcept + { + m_buffer = 0; + m_Q7.push(0, NLTIME_FROM_NS(40)); + m_Q7Q.push(1, NLTIME_FROM_NS(40)); + } + + void shift() noexcept + { + uint32_t in = (m_DS() ? m_D1() : m_D0()); + m_buffer <<= 1; + m_buffer |= in; + uint32_t out = (m_buffer >> 7) & 1; + uint32_t outq = (~m_buffer >> 7) & 1; + m_Q7.push(out, NLTIME_FROM_NS(40)); + m_Q7Q.push(outq, NLTIME_FROM_NS(40)); + } + + logic_input_t m_D0; + logic_input_t m_D1; + logic_input_t m_DS; + + state_var<uint8_t> m_buffer; + + logic_output_t m_Q7; + logic_output_t m_Q7Q; + nld_power_pins m_power_pins; + private: + NETLIB_HANDLERI(inputs) + { + /* do nothing */ + } + }; + + NETLIB_OBJECT(8277) + { + NETLIB_CONSTRUCTOR(8277) + , m_A(*this, "A") + , m_B(*this, "B") + , m_RESET(*this, "RESET", NETLIB_DELEGATE(shifter_reset)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_CLKA(*this, "CLKA", NETLIB_DELEGATE(clka)) + , m_CLKB(*this, "CLKB", NETLIB_DELEGATE(clkb)) + , m_last_CLK(*this, "m_last_CLK", 0) + , m_last_CLKA(*this, "m_last_CLKA", 0) + , m_last_CLKB(*this, "m_last_CLKB", 0) + // FIXME: needs family! + { + register_sub_alias("D0A", "A.D0"); + register_sub_alias("D1A", "A.D1"); + register_sub_alias("DSA", "A.DS"); + register_sub_alias("Q7A", "A.Q7"); + register_sub_alias("Q7QA", "A.Q7Q"); + register_sub_alias("D0B", "B.D0"); + register_sub_alias("D1B", "B.D1"); + register_sub_alias("DSB", "B.DS"); + register_sub_alias("Q7B", "B.Q7"); + register_sub_alias("Q7QB", "B.Q7Q"); + + connect("A.VCC", "B.VCC"); + connect("A.GND", "B.GND"); + + register_sub_alias("VCC", "A.VCC"); + register_sub_alias("GND", "A.GND"); + } + + NETLIB_RESETI() + { + m_last_CLK = 0; + m_last_CLKA = 0; + m_last_CLKB = 0; + } + + private: + NETLIB_HANDLERI(shifter_reset) + { + if (!m_RESET()) + { + m_A().reset_shifter(); + m_B().reset_shifter(); + } + } + + NETLIB_HANDLERI(clk) + { + if (!m_last_CLK && m_CLK()) + { + m_A().shift(); + m_B().shift(); + } + m_last_CLK = m_CLK(); + m_last_CLKA = m_CLKA(); + m_last_CLKB = m_CLKB(); + } + + NETLIB_HANDLERI(clka) + { + if (!m_last_CLKA && m_CLKA()) + { + m_A().shift(); + } + m_last_CLKA = m_CLKA(); + } + + NETLIB_HANDLERI(clkb) + { + if (!m_last_CLKB && m_CLKB()) + { + m_B().shift(); + } + m_last_CLKB = m_CLKB(); + } + + NETLIB_SUB(8277_shifter) m_A; + NETLIB_SUB(8277_shifter) m_B; + logic_input_t m_RESET; + logic_input_t m_CLK; + logic_input_t m_CLKA; + logic_input_t m_CLKB; + + state_var<uint32_t> m_last_CLK; + state_var<uint32_t> m_last_CLKA; + state_var<uint32_t> m_last_CLKB; + }; + + NETLIB_DEVICE_IMPL(8277, "TTL_8277", "+RESET,+CLK,+CLKA,+D0A,+D1A,+DSA,+CLKB,+D0B,+D1B,+DSB,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_82S115.cpp b/src/lib/netlist/devices/nld_82S115.cpp deleted file mode 100644 index 85ba43fa1e6..00000000000 --- a/src/lib/netlist/devices/nld_82S115.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S115.cpp - * - */ - -#include "nld_82S115.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(82S115) - { - NETLIB_CONSTRUCTOR(82S115) - , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"}}) - , m_CE1Q(*this, "CE1Q") - , m_CE2(*this, "CE2") - , m_STROBE(*this, "STROBE") - , m_O(*this, {{"O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8"}}) - , m_last_O(*this, "m_last_O", 0) - , m_ROM(*this, "ROM") - , m_power_pins(*this) - { - } - - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 9> m_A; - logic_input_t m_CE1Q; - logic_input_t m_CE2; - logic_input_t m_STROBE; - object_array_t<logic_output_t, 8> m_O; - - state_var<unsigned> m_last_O; - - param_rom_t<uint8_t, 9, 8> m_ROM; // 4096 bits, 512x8 - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(82S115_dip, 82S115) - { - NETLIB_CONSTRUCTOR_DERIVED(82S115_dip, 82S115) - { - register_subalias("21", m_A[0]); - register_subalias("22", m_A[1]); - register_subalias("23", m_A[2]); - register_subalias("1", m_A[3]); - register_subalias("2", m_A[4]); - register_subalias("3", m_A[5]); - register_subalias("4", m_A[6]); - register_subalias("5", m_A[7]); - register_subalias("6", m_A[8]); - - register_subalias("20", m_CE1Q); - register_subalias("19", m_CE2); - - // register_subalias("13", m_FE1); - // register_subalias("11", m_FE2); - - register_subalias("18", m_STROBE); - - register_subalias("7", m_O[0]); - register_subalias("8", m_O[1]); - register_subalias("9", m_O[2]); - register_subalias("10", m_O[3]); - register_subalias("14", m_O[4]); - register_subalias("15", m_O[5]); - register_subalias("16", m_O[6]); - register_subalias("17", m_O[7]); - - register_subalias("12", "GND"); - register_subalias("24", "VCC"); - } - }; - - NETLIB_RESET(82S115) - { - m_last_O = 0; - } - - // FIXME: timing! - NETLIB_UPDATE(82S115) - { - unsigned o = 0; - - if (!m_CE1Q() && m_CE2()) - { - if (m_STROBE()) - { - unsigned a = 0; - for (std::size_t i=0; i<9; i++) - a |= (m_A[i]() << i); - - o = m_ROM[a]; - } - else - { - o = m_last_O; - } - } - - m_last_O = o; - - // FIXME: Outputs are tristate. This needs to be properly implemented - for (std::size_t i=0; i<8; i++) - m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(40)); // FIXME: Timing - } - - NETLIB_DEVICE_IMPL(82S115, "PROM_82S115", "+CE1Q,+CE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+STROBE,@VCC,@GND") - NETLIB_DEVICE_IMPL(82S115_dip, "PROM_82S115_DIP", "") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_82S115.h b/src/lib/netlist/devices/nld_82S115.h deleted file mode 100644 index da4c1209e81..00000000000 --- a/src/lib/netlist/devices/nld_82S115.h +++ /dev/null @@ -1,53 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S115.h - * - * 82S115: 4K-bit TTL bipolar PROM (512 x 8) - * - * +--------------+ - * A3 |1 ++ 24| VCC - * A4 |2 23| A2 - * A5 |3 22| A1 - * A6 |4 82S115 21| A0 - * A7 |5 20| CE1Q - * A8 |6 19| CE2 - * O1 |7 18| STROBE - * O2 |8 17| O8 - * O3 |9 16| O7 - * O4 |10 15| O6 - * FE2 |11 14| O5 - * GND |12 13| FE1 - * +--------------+ - * - * - * Naming conventions follow Signetics datasheet - * - */ - -#ifndef NLD_82S115_H_ -#define NLD_82S115_H_ - -#include "netlist/nl_setup.h" - -#define PROM_82S115(name, cCE1Q, cCE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cSTROBE) \ - NET_REGISTER_DEV(PROM_82S115, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CE1Q, cCE1Q) \ - NET_CONNECT(name, CE2, cCE2) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) \ - NET_CONNECT(name, A7, cA7) \ - NET_CONNECT(name, A8, cA8) \ - NET_CONNECT(name, STROBE, cSTROBE) - -#define PROM_82S115_DIP(name) \ - NET_REGISTER_DEV(PROM_82S115_DIP, name) - -#endif /* NLD_82S115_H_ */ diff --git a/src/lib/netlist/devices/nld_82S123.cpp b/src/lib/netlist/devices/nld_82S123.cpp deleted file mode 100644 index d20b3a7147d..00000000000 --- a/src/lib/netlist/devices/nld_82S123.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S123.cpp - * - */ - -#include "nld_82S123.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(82S123) - { - NETLIB_CONSTRUCTOR(82S123) - , m_A(*this, {{"A0", "A1", "A2", "A3", "A4"}}) - , m_CEQ(*this, "CEQ") - , m_O(*this, {{"O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8"}}) - , m_ROM(*this, "ROM") - , m_power_pins(*this) - { - } - - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 5> m_A; - logic_input_t m_CEQ; - object_array_t<logic_output_t, 8> m_O; - - param_rom_t<uint8_t, 5, 8> m_ROM; // 256 bits, 32x8 - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(82S123_dip, 82S123) - { - NETLIB_CONSTRUCTOR_DERIVED(82S123_dip, 82S123) - { - register_subalias("1", m_O[0]); - register_subalias("2", m_O[1]); - register_subalias("3", m_O[2]); - register_subalias("4", m_O[3]); - register_subalias("5", m_O[4]); - register_subalias("6", m_O[5]); - register_subalias("7", m_O[6]); - register_subalias("8", "GND"); - - register_subalias("9", m_O[7]); - register_subalias("10", m_A[0]); - register_subalias("11", m_A[1]); - register_subalias("12", m_A[2]); - register_subalias("13", m_A[3]); - register_subalias("14", m_A[4]); - register_subalias("15", m_CEQ); - register_subalias("16", "VCC"); - } - }; - - // FIXME: timing! - NETLIB_UPDATE(82S123) - { - unsigned o = 0xff; - - netlist_time delay = NLTIME_FROM_NS(35); - if (!m_CEQ()) - { - unsigned a = 0; - for (std::size_t i=0; i<5; i++) - a |= (m_A[i]() << i); - - o = m_ROM[a]; - - delay = NLTIME_FROM_NS(50); - } - - // FIXME: Outputs are tristate. This needs to be properly implemented - for (std::size_t i=0; i<8; i++) - m_O[i].push((o >> i) & 1, delay); - } - - NETLIB_DEVICE_IMPL(82S123, "PROM_82S123", "+CEQ,+A0,+A1,+A2,+A3,+A4,@VCC,@GND") - NETLIB_DEVICE_IMPL(82S123_dip, "PROM_82S123_DIP", "") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_82S123.h b/src/lib/netlist/devices/nld_82S123.h deleted file mode 100644 index 69088b03f6b..00000000000 --- a/src/lib/netlist/devices/nld_82S123.h +++ /dev/null @@ -1,44 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S123.h - * - * 82S23: 256-bit (32x8) TTL bipolar PROM with open-collector outputs - * 82S123: 256-bit (32x8) TTL bipolar PROM with tri-state outputs - * - * +--------------+ - * O1 |1 ++ 16| VCC - * O2 |2 15| CEQ - * O3 |3 14| A4 - * O4 |4 82S123 13| A3 - * O5 |5 12| A2 - * O6 |6 11| A1 - * O7 |7 10| A0 - * GND |8 9| O8 - * +--------------+ - * - * - * Naming conventions follow Philips datasheet - * - */ - -#ifndef NLD_82S123_H_ -#define NLD_82S123_H_ - -#include "netlist/nl_setup.h" - -#define PROM_82S123(name, cCEQ, cA0, cA1, cA2, cA3, cA4) \ - NET_REGISTER_DEV(PROM_82S123, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CEQ, cCEQ) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) - -#define PROM_82S123_DIP(name) \ - NET_REGISTER_DEV(PROM_82S123_DIP, name) - -#endif /* NLD_82S123_H_ */ diff --git a/src/lib/netlist/devices/nld_82S126.cpp b/src/lib/netlist/devices/nld_82S126.cpp deleted file mode 100644 index 9ce6697c82e..00000000000 --- a/src/lib/netlist/devices/nld_82S126.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S126.cpp - * - */ - -#include "nld_82S126.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(82S126) - { - NETLIB_CONSTRUCTOR(82S126) - , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }}) - , m_CE1Q(*this, "CE1Q") - , m_CE2Q(*this, "CE2Q") - , m_O(*this, {{"O1", "O2", "O3", "O4" }}) - , m_ROM(*this, "ROM") - , m_power_pins(*this) - { - } - - NETLIB_UPDATEI(); - - protected: - object_array_t<logic_input_t, 8> m_A; - logic_input_t m_CE1Q; - logic_input_t m_CE2Q; - object_array_t<logic_output_t, 4> m_O; - - param_rom_t<uint8_t, 8, 4> m_ROM; // 1024 bits, 32x32, used as 256x4 - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(82S126_dip, 82S126) - { - NETLIB_CONSTRUCTOR_DERIVED(82S126_dip, 82S126) - { - register_subalias("5", m_A[0]); - register_subalias("6", m_A[1]); - register_subalias("7", m_A[2]); - register_subalias("4", m_A[3]); - register_subalias("3", m_A[4]); - register_subalias("2", m_A[5]); - register_subalias("1", m_A[6]); - register_subalias("15", m_A[7]); - - register_subalias("13", m_CE1Q); - register_subalias("14", m_CE2Q); - - register_subalias("12", m_O[0]); - register_subalias("11", m_O[1]); - register_subalias("10", m_O[2]); - register_subalias("9", m_O[3]); - - register_subalias("8", "GND"); - register_subalias("16", "VCC"); - } - }; - - // FIXME: timing! - NETLIB_UPDATE(82S126) - { - unsigned o = 0xf; - - netlist_time delay = NLTIME_FROM_NS(25); - if (!m_CE1Q() && !m_CE2Q()) - { - unsigned a = 0; - for (std::size_t i=0; i<8; i++) - a |= (m_A[i]() << i); - - o = m_ROM[a]; - - delay = NLTIME_FROM_NS(50); - } - - // FIXME: Outputs are tristate. This needs to be properly implemented - for (std::size_t i=0; i<4; i++) - m_O[i].push((o >> i) & 1, delay); - } - - NETLIB_DEVICE_IMPL(82S126, "PROM_82S126", "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,@VCC,@GND") - NETLIB_DEVICE_IMPL(82S126_dip, "PROM_82S126_DIP", "") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_82S126.h b/src/lib/netlist/devices/nld_82S126.h deleted file mode 100644 index 35f2c0dd725..00000000000 --- a/src/lib/netlist/devices/nld_82S126.h +++ /dev/null @@ -1,47 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_82S126.h - * - * 82S126: 1K-bit TTL bipolar PROM - * - * +--------------+ - * A6 |1 ++ 16| VCC - * A5 |2 15| Q7 - * A4 |3 14| CE2Q - * A3 |4 82S126 13| CE1Q - * A0 |5 12| O1 - * A1 |6 11| O2 - * A2 |7 10| O3 - * GND |8 9| O4 - * +--------------+ - * - * - * Naming conventions follow Signetics datasheet - * - */ - -#ifndef NLD_82S126_H_ -#define NLD_82S126_H_ - -#include "netlist/nl_setup.h" - -#define PROM_82S126(name, cCE1Q, cCE2Q, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7) \ - NET_REGISTER_DEV(PROM_82S126, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CE1Q, cCE1Q) \ - NET_CONNECT(name, CE2Q, cCE2Q) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) \ - NET_CONNECT(name, A7, cA7) - -#define PROM_82S126_DIP(name) \ - NET_REGISTER_DEV(PROM_82S126_DIP, name) - -#endif /* NLD_82S126_H_ */ diff --git a/src/lib/netlist/devices/nld_82S16.cpp b/src/lib/netlist/devices/nld_82S16.cpp deleted file mode 100644 index cce10063061..00000000000 --- a/src/lib/netlist/devices/nld_82S16.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_82S16.c - * - */ - -#include "nld_82S16.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - NETLIB_OBJECT(82S16) - { - NETLIB_CONSTRUCTOR(82S16) - , m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }}, NETLIB_DELEGATE(82S16, addr)) - , m_CE1Q(*this, "CE1Q", NETLIB_DELEGATE(82S16, enq)) - , m_CE2Q(*this, "CE2Q", NETLIB_DELEGATE(82S16, enq)) - , m_CE3Q(*this, "CE3Q", NETLIB_DELEGATE(82S16, enq)) - , m_WEQ(*this, "WEQ") - , m_DIN(*this, "DIN") - , m_DOUTQ(*this, "DOUTQ") - , m_ram(*this, "m_ram", 0) - , m_addr(*this, "m_addr", 0) - , m_enq(*this, "m_enq", 0) - , m_power_pins(*this) - { - } - - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_HANDLERI(addr) - { - uint8_t adr = 0; - for (std::size_t i=0; i<8; i++) - { - //m_A[i].activate(); - adr |= (m_A[i]() << i); - } - m_addr = adr; - NETLIB_NAME(82S16)::update(); - } - NETLIB_HANDLERI(enq) - { - const auto last = m_enq; - m_enq = m_CE1Q() || m_CE2Q() || m_CE3Q(); - if (!last && m_enq) - { - // FIXME: Outputs are tristate. This needs to be properly implemented - m_DOUTQ.push(1, NLTIME_FROM_NS(20)); - for (std::size_t i=0; i<8; i++) - m_A[i].inactivate(); - m_WEQ.inactivate(); - m_DIN.inactivate(); - } - else if (last && !m_enq) - { - for (std::size_t i=0; i<8; i++) - m_A[i].activate(); - m_WEQ.activate(); - m_DIN.activate(); - NETLIB_NAME(82S16)::update(); - } - } - - - protected: - object_array_t<logic_input_t, 8> m_A; - logic_input_t m_CE1Q; - logic_input_t m_CE2Q; - logic_input_t m_CE3Q; - logic_input_t m_WEQ; - logic_input_t m_DIN; - logic_output_t m_DOUTQ; - - state_array<uint64_t, 4> m_ram; // 256 bits - state_var_u8 m_addr; // 256 bits - state_var_sig m_enq; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(82S16_dip, 82S16) - { - NETLIB_CONSTRUCTOR_DERIVED(82S16_dip, 82S16) - { - register_subalias("2", m_A[0]); - register_subalias("1", m_A[1]); - register_subalias("15", m_A[2]); - register_subalias("14", m_A[3]); - register_subalias("7", m_A[4]); - register_subalias("9", m_A[5]); - register_subalias("10", m_A[6]); - register_subalias("11", m_A[7]); - - register_subalias("3", m_CE1Q); - register_subalias("4", m_CE2Q); - register_subalias("5", m_CE3Q); - - register_subalias("12", m_WEQ); - register_subalias("13", m_DIN); - - register_subalias("6", m_DOUTQ); - - register_subalias("8", "GND"); - register_subalias("16", "VCC"); - } - }; - - // FIXME: timing! - // FIXME: optimize device (separate address decoder!) - NETLIB_UPDATE(82S16) - { - if (!m_enq) - { - const auto adr(m_addr); - if (!m_WEQ()) - { - m_ram[adr >> 6] = (m_ram[adr >> 6] - & ~(static_cast<uint64_t>(1) << (adr & 0x3f))) - | (static_cast<uint64_t>(m_DIN()) << (adr & 0x3f)); - } - m_DOUTQ.push(((m_ram[adr >> 6] >> (adr & 0x3f)) & 1) ^ 1, NLTIME_FROM_NS(20)); - } - } - - NETLIB_RESET(82S16) - { - for (std::size_t i=0; i<4; i++) - { - m_ram[i] = 0; - } - m_addr = 0; - m_enq = 0; - } - - NETLIB_DEVICE_IMPL(82S16, "TTL_82S16", "") - NETLIB_DEVICE_IMPL(82S16_dip, "TTL_82S16_DIP", "") - - } //namespace devices -} // namespace netlist diff --git a/src/lib/netlist/devices/nld_82S16.h b/src/lib/netlist/devices/nld_82S16.h deleted file mode 100644 index 47d6189a79b..00000000000 --- a/src/lib/netlist/devices/nld_82S16.h +++ /dev/null @@ -1,34 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_82S16.h - * - * DM82S16: 256 Bit bipolar ram - * - * +--------------+ - * A1 |1 ++ 16| VCC - * A0 |2 15| A2 - * CE1Q |3 14| A3 - * CE2Q |4 82S16 13| DIN - * CE3Q |5 12| WEQ - * DOUTQ |6 11| A7 - * A4 |7 10| A6 - * GND |8 9| A5 - * +--------------+ - * - * - * Naming conventions follow Signetics datasheet - * - */ - -#ifndef NLD_82S16_H_ -#define NLD_82S16_H_ - -#include "netlist/nl_setup.h" - -#define TTL_82S16(name) \ - NET_REGISTER_DEV(TTL_82S16, name) -#define TTL_82S16_DIP(name) \ - NET_REGISTER_DEV(TTL_82S16_DIP, name) - -#endif /* NLD_82S16_H_ */ diff --git a/src/lib/netlist/devices/nld_82s115.cpp b/src/lib/netlist/devices/nld_82s115.cpp new file mode 100644 index 00000000000..5c7db00f347 --- /dev/null +++ b/src/lib/netlist/devices/nld_82s115.cpp @@ -0,0 +1,94 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/* + * nld_82S115.cpp + * + * 82S115: 4K-bit TTL bipolar PROM (512 x 8) + * + * +--------------+ + * A3 |1 ++ 24| VCC + * A4 |2 23| A2 + * A5 |3 22| A1 + * A6 |4 82S115 21| A0 + * A7 |5 20| CE1Q + * A8 |6 19| CE2 + * O1 |7 18| STROBE + * O2 |8 17| O8 + * O3 |9 16| O7 + * O4 |10 15| O6 + * FE2 |11 14| O5 + * GND |12 13| FE1 + * +--------------+ + * + * + * Naming conventions follow Signetics datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + NETLIB_OBJECT(82S115) + { + NETLIB_CONSTRUCTOR(82S115) + , m_A(*this, {"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"}, NETLIB_DELEGATE(inputs)) + , m_CE1Q(*this, "CE1Q", NETLIB_DELEGATE(inputs)) + , m_CE2(*this, "CE2", NETLIB_DELEGATE(inputs)) + , m_STROBE(*this, "STROBE", NETLIB_DELEGATE(inputs)) + , m_O(*this, {"O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8"}) + , m_last_O(*this, "m_last_O", 0) + , m_ROM(*this, "ROM") + , m_power_pins(*this) + { + } + + NETLIB_RESETI() + { + m_last_O = 0; + } + + private: + // FIXME: timing! + NETLIB_HANDLERI(inputs) + { + unsigned o = 0; + + if (!m_CE1Q() && m_CE2()) + { + if (m_STROBE()) + { + unsigned a = 0; + for (std::size_t i=0; i<9; i++) + a |= (m_A[i]() << i); + + o = m_ROM[a]; + } + else + { + o = m_last_O; + } + } + + m_last_O = o; + + // FIXME: Outputs are tristate. This needs to be properly implemented + for (std::size_t i=0; i<8; i++) + m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(40)); // FIXME: Timing + } + + object_array_t<logic_input_t, 9> m_A; + logic_input_t m_CE1Q; + logic_input_t m_CE2; + logic_input_t m_STROBE; + object_array_t<logic_output_t, 8> m_O; + + state_var<unsigned> m_last_O; + + param_rom_t<uint8_t, 9, 8> m_ROM; // 4096 bits, 512x8 + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(82S115, "PROM_82S115", "+CE1Q,+CE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+STROBE,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_82s16.cpp b/src/lib/netlist/devices/nld_82s16.cpp new file mode 100644 index 00000000000..9ebc7c370c1 --- /dev/null +++ b/src/lib/netlist/devices/nld_82s16.cpp @@ -0,0 +1,124 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_82S16.cpp + * + * + * DM82S16: 256 Bit bipolar ram + * + * +--------------+ + * A1 |1 ++ 16| VCC + * A0 |2 15| A2 + * CE1Q |3 14| A3 + * CE2Q |4 82S16 13| DIN + * CE3Q |5 12| WEQ + * DOUTQ |6 11| A7 + * A4 |7 10| A6 + * GND |8 9| A5 + * +--------------+ + * + * + * Naming conventions follow Signetics datasheet + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + NETLIB_OBJECT(82S16) + { + NETLIB_CONSTRUCTOR(82S16) + , m_A(*this, {"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7"}, NETLIB_DELEGATE(addr)) + , m_CE1Q(*this, "CE1Q", NETLIB_DELEGATE(enq)) + , m_CE2Q(*this, "CE2Q", NETLIB_DELEGATE(enq)) + , m_CE3Q(*this, "CE3Q", NETLIB_DELEGATE(enq)) + , m_WEQ(*this, "WEQ", NETLIB_DELEGATE(inputs)) + , m_DIN(*this, "DIN", NETLIB_DELEGATE(inputs)) + , m_DOUTQ(*this, "DOUTQ") + , m_ram(*this, "m_ram", 0) + , m_addr(*this, "m_addr", 0) + , m_enq(*this, "m_enq", 0) + , m_power_pins(*this) + { + } + + NETLIB_RESETI() + { + for (std::size_t i=0; i<4; i++) + { + m_ram[i] = 0; + } + m_addr = 0; + m_enq = 0; + } + + private: + // FIXME: timing! + // FIXME: optimize device (separate address decoder!) + NETLIB_HANDLERI(inputs) + { + if (!m_enq) + { + const decltype(m_addr)::value_type adr(m_addr); + if (!m_WEQ()) + { + m_ram[adr >> 6] = (m_ram[adr >> 6] + & ~(static_cast<uint64_t>(1) << (adr & 0x3f))) + | (static_cast<uint64_t>(m_DIN()) << (adr & 0x3f)); + } + m_DOUTQ.push(((m_ram[adr >> 6] >> (adr & 0x3f)) & 1) ^ 1, NLTIME_FROM_NS(20)); + } + } + + NETLIB_HANDLERI(addr) + { + uint8_t adr = 0; + for (std::size_t i=0; i<8; i++) + { + //m_A[i].activate(); + adr |= (m_A[i]() << i); + } + m_addr = adr; + inputs(); + } + NETLIB_HANDLERI(enq) + { + const decltype(m_enq)::value_type last = m_enq; + m_enq = m_CE1Q() || m_CE2Q() || m_CE3Q(); + if (!last && m_enq) + { + // FIXME: Outputs are tristate. This needs to be properly implemented + m_DOUTQ.push(1, NLTIME_FROM_NS(20)); + for (std::size_t i=0; i<8; i++) + m_A[i].inactivate(); + m_WEQ.inactivate(); + m_DIN.inactivate(); + } + else if (last && !m_enq) + { + for (std::size_t i=0; i<8; i++) + m_A[i].activate(); + m_WEQ.activate(); + m_DIN.activate(); + inputs(); + } + } + + object_array_t<logic_input_t, 8> m_A; + logic_input_t m_CE1Q; + logic_input_t m_CE2Q; + logic_input_t m_CE3Q; + logic_input_t m_WEQ; + logic_input_t m_DIN; + logic_output_t m_DOUTQ; + + state_container<std::array<uint64_t, 4>> m_ram; // 256 bits + state_var_u8 m_addr; // 256 bits + state_var_sig m_enq; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(82S16, "TTL_82S16", "") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9310.cpp b/src/lib/netlist/devices/nld_9310.cpp index bb1e9cc46e3..c9b51b08985 100644 --- a/src/lib/netlist/devices/nld_9310.cpp +++ b/src/lib/netlist/devices/nld_9310.cpp @@ -1,223 +1,24 @@ -// license:GPL-2.0+ -//+opyright-holders:Couriersud +// license:BSD-3-Clause +// copyright-holders:Couriersud /* - * nld_9310.c + * nld_9310.cpp * */ -#include "nld_9310.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" +#include "nl_factory.h" -#define MAXCNT 9 +#include "nld_9316_base.hxx" -namespace netlist -{ - namespace devices - { +// FIXME: All detail can be found in nld_9316_base.hxx +// At least gcc-7.x needs the implementations of the base device +// in different compilation units. If created in the same file +// performance degrades horrible. - NETLIB_OBJECT(9310) - { - NETLIB_CONSTRUCTOR(9310) - , m_ENP(*this, "ENP") - , m_ENT(*this, "ENT") - , m_CLRQ(*this, "CLRQ") - , m_LOADQ(*this, "LOADQ") - , m_A(*this, "A", NETLIB_DELEGATE(9310, abcd)) - , m_B(*this, "B", NETLIB_DELEGATE(9310, abcd)) - , m_C(*this, "C", NETLIB_DELEGATE(9310, abcd)) - , m_D(*this, "D", NETLIB_DELEGATE(9310, abcd)) - , m_CLK(*this, "CLK", NETLIB_DELEGATE(9310, sub)) - , m_QA(*this, "QA") - , m_QB(*this, "QB") - , m_QC(*this, "QC") - , m_QD(*this, "QD") - , m_RC(*this, "RC") - , m_cnt(*this, "m_cnt", 0) - , m_loadq(*this, "m_loadq", 0) - , m_ent(*this, "m_ent", 0) - , m_power_pins(*this) - { - } +// FIXME: this file could be created programmatically - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - NETLIB_HANDLERI(abcd) { } // do nothing - - NETLIB_HANDLERI(sub) - { - auto cnt(m_cnt); - - if (m_loadq) - { - if (cnt < MAXCNT - 1) - { - ++cnt; - update_outputs(cnt); - } - else if (cnt == MAXCNT - 1) - { - cnt = MAXCNT; - m_RC.push(m_ent, NLTIME_FROM_NS(20)); - m_QA.push(1, NLTIME_FROM_NS(20)); - } - else // MAXCNT - { - m_RC.push(0, NLTIME_FROM_NS(20)); - cnt = 0; - update_outputs_all(cnt, NLTIME_FROM_NS(20)); - } - } - else - { - cnt = read_ABCD(); - m_RC.push(m_ent & (cnt == MAXCNT), NLTIME_FROM_NS(27)); - update_outputs_all(cnt, NLTIME_FROM_NS(22)); - } - m_cnt = cnt; - } - - protected: - - unsigned read_ABCD() const - { - return (m_D() << 3) | (m_C() << 2) | (m_B() << 1) | (m_A() << 0); - } - - void update_outputs_all(const unsigned cnt, const netlist_time out_delay) - { - m_QA.push((cnt >> 0) & 1, out_delay); - m_QB.push((cnt >> 1) & 1, out_delay); - m_QC.push((cnt >> 2) & 1, out_delay); - m_QD.push((cnt >> 3) & 1, out_delay); - } - - void update_outputs(const unsigned cnt) - { - /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20); - #if 0 - // for (int i=0; i<4; i++) - // m_Q[i], (cnt >> i) & 1, delay[i]); - m_QA.push((cnt >> 0) & 1, out_delay); - m_QB.push((cnt >> 1) & 1, out_delay); - m_QC.push((cnt >> 2) & 1, out_delay); - m_QD.push((cnt >> 3) & 1, out_delay); - #else - if ((cnt & 1) == 1) - m_QA.push(1, out_delay); - else - { - m_QA.push(0, out_delay); - switch (cnt) - { - case 0x00: - m_QB.push(0, out_delay); - m_QC.push(0, out_delay); - m_QD.push(0, out_delay); - break; - case 0x02: - case 0x06: - case 0x0A: - case 0x0E: - m_QB.push(1, out_delay); - break; - case 0x04: - case 0x0C: - m_QB.push(0, out_delay); - m_QC.push(1, out_delay); - break; - case 0x08: - m_QB.push(0, out_delay); - m_QC.push(0, out_delay); - m_QD.push(1, out_delay); - break; - } - - } - #endif - } - - logic_input_t m_ENP; - logic_input_t m_ENT; - logic_input_t m_CLRQ; - logic_input_t m_LOADQ; - logic_input_t m_A; - logic_input_t m_B; - logic_input_t m_C; - logic_input_t m_D; - logic_input_t m_CLK; - - logic_output_t m_QA; - logic_output_t m_QB; - logic_output_t m_QC; - logic_output_t m_QD; - logic_output_t m_RC; - - state_var<unsigned> m_cnt; - state_var<netlist_sig_t> m_loadq; - state_var<netlist_sig_t> m_ent; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(9310_dip, 9310) - { - NETLIB_CONSTRUCTOR_DERIVED(9310_dip, 9310) - { - register_subalias("1", m_CLRQ); - register_subalias("2", m_CLK); - register_subalias("3", m_A); - register_subalias("4", m_B); - register_subalias("5", m_C); - register_subalias("6", m_D); - register_subalias("7", m_ENP); - register_subalias("8", "GND"); - - register_subalias("9", m_LOADQ); - register_subalias("10", m_ENT); - register_subalias("11", m_QD); - register_subalias("12", m_QC); - register_subalias("13", m_QB); - register_subalias("14", m_QA); - register_subalias("15", m_RC); - register_subalias("16", "VCC"); - } - }; - - NETLIB_RESET(9310) - { - m_CLK.set_state(logic_t::STATE_INP_LH); - m_cnt = 0; - m_loadq = 1; - m_ent = 1; - } - - NETLIB_UPDATE(9310) - { - m_loadq = m_LOADQ(); - m_ent = m_ENT(); - const netlist_sig_t clrq = m_CLRQ(); - - if ((!m_loadq || (m_ent & m_ENP())) && clrq) - { - m_CLK.activate_lh(); - m_RC.push(m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(27)); - } - else - { - m_CLK.inactivate(); - if (!clrq && (m_cnt>0)) - { - update_outputs_all(0, NLTIME_FROM_NS(36)); - m_cnt = 0; - //return; - } - m_RC.push(m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(27)); - } - } +namespace netlist::devices { NETLIB_DEVICE_IMPL(9310, "TTL_9310", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D,@VCC,@GND") - NETLIB_DEVICE_IMPL(9310_dip, "TTL_9310_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9310.h b/src/lib/netlist/devices/nld_9310.h deleted file mode 100644 index fa6dc0a3351..00000000000 --- a/src/lib/netlist/devices/nld_9310.h +++ /dev/null @@ -1,67 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_9310.h - * - * DM9310: Synchronous 4-Bit Counters - * - * FIXME: This should be merged with the 9316. The only difference is MAXCNT! - * - * +--------------+ - * CLEAR |1 ++ 16| VCC - * CLOCK |2 15| RC (Ripple Carry) - * A |3 14| QA - * B |4 9310 13| QB - * C |5 12| QC - * D |6 11| QD - * Enable P |7 10| Enable T - * GND |8 9| LOAD - * +--------------+ - * - * Counter Sequence - * - * +-------++----+----+----+----+----+ - * | COUNT || QD | QC | QB | QA | RC | - * +=======++====+====+====+====+====+ - * | 0 || 0 | 0 | 0 | 0 | 0 | - * | 1 || 0 | 0 | 0 | 1 | 0 | - * | 2 || 0 | 0 | 1 | 0 | 0 | - * | 3 || 0 | 0 | 1 | 1 | 0 | - * | 4 || 0 | 1 | 0 | 0 | 0 | - * | 5 || 0 | 1 | 0 | 1 | 0 | - * | 6 || 0 | 1 | 1 | 0 | 0 | - * | 7 || 0 | 1 | 1 | 1 | 0 | - * | 8 || 1 | 0 | 0 | 0 | 0 | - * | 9 || 1 | 0 | 0 | 1 | 0 | - * +-------++----+----+----+----+----+ - * - * Reset count function: Please refer to - * National Semiconductor datasheet (timing diagram) - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_9310_H_ -#define NLD_9310_H_ - -#include "netlist/nl_setup.h" - -#define TTL_9310(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \ - NET_REGISTER_DEV(TTL_9310, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, ENP, cENP) \ - NET_CONNECT(name, ENT, cENT) \ - NET_CONNECT(name, CLRQ, cCLRQ) \ - NET_CONNECT(name, LOADQ,_LOADQ) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) - -#define TTL_9310_DIP(name) \ - NET_REGISTER_DEV(TTL_9310_DIP, name) - -#endif /* NLD_9310_H_ */ diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp index 8977f9d0364..54dcb7cc39e 100644 --- a/src/lib/netlist/devices/nld_9316.cpp +++ b/src/lib/netlist/devices/nld_9316.cpp @@ -1,141 +1,100 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_9316.c + * nld_9316.cpp + * + * DM9316: Synchronous 4-Bit Counters + * + * +--------------+ + * /CLEAR |1 ++ 16| VCC + * CLOCK |2 15| RC (Ripple Carry) + * A |3 14| QA + * B |4 9316 13| QB + * C |5 12| QC + * D |6 11| QD + * Enable P |7 10| Enable T + * GND |8 9| /LOAD + * +--------------+ + * + * Counter Sequence + * + * +-------++----+----+----+----+----+ + * | COUNT || QD | QC | QB | QA | RC | + * +=======++====+====+====+====+====+ + * | 0 || 0 | 0 | 0 | 0 | 0 | + * | 1 || 0 | 0 | 0 | 1 | 0 | + * | 2 || 0 | 0 | 1 | 0 | 0 | + * | 3 || 0 | 0 | 1 | 1 | 0 | + * | 4 || 0 | 1 | 0 | 0 | 0 | + * | 5 || 0 | 1 | 0 | 1 | 0 | + * | 6 || 0 | 1 | 1 | 0 | 0 | + * | 7 || 0 | 1 | 1 | 1 | 0 | + * | 8 || 1 | 0 | 0 | 0 | 0 | + * | 9 || 1 | 0 | 0 | 1 | 0 | + * | 10 || 1 | 0 | 1 | 0 | 0 | + * | 11 || 1 | 0 | 1 | 1 | 0 | + * | 12 || 1 | 1 | 0 | 0 | 0 | + * | 13 || 1 | 1 | 0 | 1 | 0 | + * | 14 || 1 | 1 | 1 | 0 | 0 | + * | 15 || 1 | 1 | 1 | 1 | 1 | + * +-------++----+----+----+----+----+ + * + * Reset count function: Please refer to + * National Semiconductor datasheet (timing diagram) + * + * Naming conventions follow National Semiconductor datasheet + * + * DM9310: Synchronous 4-Bit Counters + * + * +--------------+ + * CLEAR |1 ++ 16| VCC + * CLOCK |2 15| RC (Ripple Carry) + * A |3 14| QA + * B |4 9310 13| QB + * C |5 12| QC + * D |6 11| QD + * Enable P |7 10| Enable T + * GND |8 9| LOAD + * +--------------+ + * + * Counter Sequence + * + * +-------++----+----+----+----+----+ + * | COUNT || QD | QC | QB | QA | RC | + * +=======++====+====+====+====+====+ + * | 0 || 0 | 0 | 0 | 0 | 0 | + * | 1 || 0 | 0 | 0 | 1 | 0 | + * | 2 || 0 | 0 | 1 | 0 | 0 | + * | 3 || 0 | 0 | 1 | 1 | 0 | + * | 4 || 0 | 1 | 0 | 0 | 0 | + * | 5 || 0 | 1 | 0 | 1 | 0 | + * | 6 || 0 | 1 | 1 | 0 | 0 | + * | 7 || 0 | 1 | 1 | 1 | 0 | + * | 8 || 1 | 0 | 0 | 0 | 0 | + * | 9 || 1 | 0 | 0 | 1 | 0 | + * +-------++----+----+----+----+----+ + * + * Reset count function: Please refer to + * National Semiconductor datasheet (timing diagram) + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_9316.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" - -namespace netlist -{ - namespace devices - { - - static constexpr const unsigned MAXCNT = 15; - - NETLIB_OBJECT(9316) - { - NETLIB_CONSTRUCTOR(9316) - , m_CLK(*this, "CLK", NETLIB_DELEGATE(9316, clk)) - , m_ENT(*this, "ENT") - , m_RC(*this, "RC") - , m_LOADQ(*this, "LOADQ") - , m_ENP(*this, "ENP") - , m_CLRQ(*this, "CLRQ") - , m_ABCD(*this, {{"A", "B", "C", "D"}}, NETLIB_DELEGATE(9316, abcd)) - , m_Q(*this, {{ "QA", "QB", "QC", "QD" }}) - , m_cnt(*this, "m_cnt", 0) - , m_abcd(*this, "m_abcd", 0) - , m_loadq(*this, "m_loadq", 0) - , m_ent(*this, "m_ent", 0) - , m_power_pins(*this) - { - } - - private: - NETLIB_RESETI() - { - m_CLK.set_state(logic_t::STATE_INP_LH); - m_cnt = 0; - m_abcd = 0; - } - - NETLIB_UPDATEI() - { - const auto CLRQ(m_CLRQ()); - m_ent = m_ENT(); - m_loadq = m_LOADQ(); - - if (((m_loadq ^ 1) || (m_ent && m_ENP())) && CLRQ) - { - m_CLK.activate_lh(); - } - else - { - m_CLK.inactivate(); - if (!CLRQ && (m_cnt>0)) - { - update_outputs_all(0, NLTIME_FROM_NS(36)); - m_cnt = 0; - } - } - m_RC.push(m_ent && (m_cnt == MAXCNT), NLTIME_FROM_NS(27)); - } - - - NETLIB_HANDLERI(clk) - { - auto cnt = (m_loadq ? (m_cnt + 1) & MAXCNT: m_abcd); - m_RC.push(m_ent && (cnt == MAXCNT), NLTIME_FROM_NS(27)); - update_outputs_all(cnt, NLTIME_FROM_NS(20)); - m_cnt = cnt; - } - - NETLIB_HANDLERI(abcd) - { - m_abcd = static_cast<unsigned>((m_ABCD[0]() << 0) | (m_ABCD[1]() << 1) | (m_ABCD[2]() << 2) | (m_ABCD[3]() << 3)); - } - - logic_input_t m_CLK; - logic_input_t m_ENT; - - logic_output_t m_RC; - - logic_input_t m_LOADQ; - - logic_input_t m_ENP; - logic_input_t m_CLRQ; - - object_array_t<logic_input_t, 4> m_ABCD; - object_array_t<logic_output_t, 4> m_Q; - - /* counter state */ - state_var<unsigned> m_cnt; - /* cached pins */ - state_var<unsigned> m_abcd; - state_var_sig m_loadq; - state_var_sig m_ent; - nld_power_pins m_power_pins; +#include "nl_base.h" +#include "nl_factory.h" - void update_outputs_all(unsigned cnt, netlist_time out_delay) noexcept - { - m_Q[0].push((cnt >> 0) & 1, out_delay); - m_Q[1].push((cnt >> 1) & 1, out_delay); - m_Q[2].push((cnt >> 2) & 1, out_delay); - m_Q[3].push((cnt >> 3) & 1, out_delay); - } - }; +#include "nld_9316_base.hxx" - NETLIB_OBJECT_DERIVED(9316_dip, 9316) - { - NETLIB_CONSTRUCTOR_DERIVED(9316_dip, 9316) - { - register_subalias("1", "CLRQ"); - register_subalias("2", "CLK"); - register_subalias("3", "A"); - register_subalias("4", "B"); - register_subalias("5", "C"); - register_subalias("6", "D"); - register_subalias("7", "ENP"); - register_subalias("8", "GND"); +// FIXME: All detail can be found in nld_9316_base.hxx +// At least gcc-7.x needs the implementations of the base device +// in different compilation units. If created in the same file +// performance degrades horrible. - register_subalias("9", "LOADQ"); - register_subalias("10", "ENT"); - register_subalias("11", "QD"); - register_subalias("12", "QC"); - register_subalias("13", "QB"); - register_subalias("14", "QA"); - register_subalias("15", "RC"); - register_subalias("16", "VCC"); - } - }; +// FIXME: this file could be created programmatically +namespace netlist::devices { NETLIB_DEVICE_IMPL(9316, "TTL_9316", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D,@VCC,@GND") - NETLIB_DEVICE_IMPL(9316_dip, "TTL_9316_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9316.h b/src/lib/netlist/devices/nld_9316.h deleted file mode 100644 index bdd925fa9f5..00000000000 --- a/src/lib/netlist/devices/nld_9316.h +++ /dev/null @@ -1,73 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_9316.h - * - * DM9316: Synchronous 4-Bit Counters - * - * +--------------+ - * /CLEAR |1 ++ 16| VCC - * CLOCK |2 15| RC (Ripple Carry) - * A |3 14| QA - * B |4 9316 13| QB - * C |5 12| QC - * D |6 11| QD - * Enable P |7 10| Enable T - * GND |8 9| /LOAD - * +--------------+ - * - * Counter Sequence - * - * +-------++----+----+----+----+----+ - * | COUNT || QD | QC | QB | QA | RC | - * +=======++====+====+====+====+====+ - * | 0 || 0 | 0 | 0 | 0 | 0 | - * | 1 || 0 | 0 | 0 | 1 | 0 | - * | 2 || 0 | 0 | 1 | 0 | 0 | - * | 3 || 0 | 0 | 1 | 1 | 0 | - * | 4 || 0 | 1 | 0 | 0 | 0 | - * | 5 || 0 | 1 | 0 | 1 | 0 | - * | 6 || 0 | 1 | 1 | 0 | 0 | - * | 7 || 0 | 1 | 1 | 1 | 0 | - * | 8 || 1 | 0 | 0 | 0 | 0 | - * | 9 || 1 | 0 | 0 | 1 | 0 | - * | 10 || 1 | 0 | 1 | 0 | 0 | - * | 11 || 1 | 0 | 1 | 1 | 0 | - * | 12 || 1 | 1 | 0 | 0 | 0 | - * | 13 || 1 | 1 | 0 | 1 | 0 | - * | 14 || 1 | 1 | 1 | 0 | 0 | - * | 15 || 1 | 1 | 1 | 1 | 1 | - * +-------++----+----+----+----+----+ - * - * Reset count function: Please refer to - * National Semiconductor datasheet (timing diagram) - * - * Naming conventions follow National Semiconductor datasheet - * - * TODO: DM74161 is compatible to DM9316 (both asynchronous clear) - * DM74163 has asynchronous clear (on L to H transition of clock) - */ - -#ifndef NLD_9316_H_ -#define NLD_9316_H_ - -#include "netlist/nl_setup.h" - -#define TTL_9316(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \ - NET_REGISTER_DEV(TTL_9316, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CLK, cCLK) \ - NET_CONNECT(name, ENP, cENP) \ - NET_CONNECT(name, ENT, cENT) \ - NET_CONNECT(name, CLRQ, cCLRQ) \ - NET_CONNECT(name, LOADQ, cLOADQ) \ - NET_CONNECT(name, A, cA) \ - NET_CONNECT(name, B, cB) \ - NET_CONNECT(name, C, cC) \ - NET_CONNECT(name, D, cD) - -#define TTL_9316_DIP(name) \ - NET_REGISTER_DEV(TTL_9316_DIP, name) - -#endif /* NLD_9316_H_ */ diff --git a/src/lib/netlist/devices/nld_9316_base.hxx b/src/lib/netlist/devices/nld_9316_base.hxx new file mode 100644 index 00000000000..881d9986ed5 --- /dev/null +++ b/src/lib/netlist/devices/nld_9316_base.hxx @@ -0,0 +1,155 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_9316_base.hxx + * + */ + +#include "nl_base.h" +#include "nl_factory.h" + +namespace netlist::devices +{ + + template <unsigned N> + static constexpr unsigned rollover(unsigned v) noexcept { return v <= N ? v : 0; } + + template <> + constexpr unsigned rollover<15>(unsigned v) noexcept { return v & 15; } + + template <typename D> + NETLIB_OBJECT(9316_base) + { + NETLIB_CONSTRUCTOR(9316_base) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(clk)) + , m_ENT(*this, "ENT", NETLIB_DELEGATE(other)) + , m_LOADQ(*this, "LOADQ", NETLIB_DELEGATE(other)) + , m_ENP(*this, "ENP", NETLIB_DELEGATE(other)) + , m_CLRQ(*this, "CLRQ", NETLIB_DELEGATE(other)) + , m_ABCD(*this, {"A", "B", "C", "D"}, NETLIB_DELEGATE(abcd)) + , m_RC(*this, "RC") + , m_Q(*this, { "QA", "QB", "QC", "QD" }) + , m_cnt(*this, "m_cnt", 0) + , m_abcd(*this, "m_abcd", 0) + , m_loadq(*this, "m_loadq", 0) + , m_ent(*this, "m_ent", 0) + , m_power_pins(*this) + { + } + + private: + NETLIB_RESETI() + { + m_CLK.set_state(logic_t::STATE_INP_LH); + m_cnt = 0; + m_abcd = 0; + } + + NETLIB_HANDLERI(other) + { + const auto CLRQ(m_CLRQ()); + m_ent = m_ENT(); + m_loadq = m_LOADQ(); + + if (((m_loadq ^ 1) || (m_ent && m_ENP())) && (!D::ASYNC::value || CLRQ)) + { + m_CLK.activate_lh(); + } + else + { + m_CLK.inactivate(); + if (D::ASYNC::value && !CLRQ && (m_cnt>0)) + { + m_cnt = 0; + m_Q.push(0, D::tCLR::value(0)); + } + } + m_RC.push(m_ent && (m_cnt == D::MAXCNT::value), D::tRC::value(0)); + } + + NETLIB_HANDLERI(clk) + { + if (!D::ASYNC::value && !m_CLRQ()) + { + m_Q.push(0, D::tCLR::value(0)); + m_cnt = 0; + } + else + { + const unsigned cnt(m_loadq ? rollover<D::MAXCNT::value>(m_cnt + 1) : m_abcd); + m_RC.push(m_ent && (cnt == D::MAXCNT::value), D::tRC::value(0)); + m_Q.push(cnt, D::tLDCNT::value(0)); + m_cnt = cnt; + } + } + + NETLIB_HANDLERI(abcd) + { + m_abcd = static_cast<unsigned>(m_ABCD()); + } + + logic_input_t m_CLK; + logic_input_t m_ENT; + + logic_input_t m_LOADQ; + + logic_input_t m_ENP; + logic_input_t m_CLRQ; + + object_array_t<logic_input_t, 4> m_ABCD; + + logic_output_t m_RC; + object_array_t<logic_output_t, 4> m_Q; + + /* counter state */ + state_var<unsigned> m_cnt; + /* cached pins */ + state_var<unsigned> m_abcd; + state_var<unsigned> m_loadq; + state_var<unsigned> m_ent; + nld_power_pins m_power_pins; + + }; + struct desc_9316 : public desc_base + { + using ASYNC = desc_const_t<bool, true>; + using MAXCNT = desc_const_t<unsigned, 15>; + using tRC = time_ns<27>; + using tCLR = time_ns<36>; + using tLDCNT = time_ns<20>; + }; + + struct desc_9310 : public desc_base + { + using ASYNC = desc_const_t<bool, true>; + using MAXCNT = desc_const_t<unsigned, 9>; + using tRC = time_ns<27>; + using tCLR = time_ns<36>; + using tLDCNT = time_ns<20>; + }; + + struct desc_74161 : public desc_base + { + using ASYNC = desc_const_t<bool, true>; + using MAXCNT = desc_const_t<unsigned, 15>; + using tRC = time_ns<27>; + using tCLR = time_ns<36>; + using tLDCNT = time_ns<20>; + }; + + struct desc_74163 : public desc_base + { + using ASYNC = desc_const_t<bool, false>; + using MAXCNT = desc_const_t<unsigned, 15>; + using tRC = time_ns<27>; + using tCLR = time_ns<36>; + using tLDCNT = time_ns<20>; + }; + + using NETLIB_NAME(9310) = NETLIB_NAME(9316_base)<desc_9310>; + using NETLIB_NAME(9316) = NETLIB_NAME(9316_base)<desc_9316>; + using NETLIB_NAME(74161) = NETLIB_NAME(9316_base)<desc_74161>; + using NETLIB_NAME(74161_fixme) = NETLIB_NAME(9316_base)<desc_74161>; + using NETLIB_NAME(74163) = NETLIB_NAME(9316_base)<desc_74163>; + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9321.cpp b/src/lib/netlist/devices/nld_9321.cpp new file mode 100644 index 00000000000..479b83d497e --- /dev/null +++ b/src/lib/netlist/devices/nld_9321.cpp @@ -0,0 +1,66 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/* + * nld_9321.cpp + * + * 9321: Dual One-of-Four Decoder + * + * +------------+ + * /E |1 ++ 16| VCC + * A0 |2 15| /E + * A1 |3 14| A0 + * /D0 |4 9321 13| A1 + * /D1 |5 12| /D0 + * /D2 |6 11| /D1 + * /D3 |7 10| /D2 + * GND |8 9| /D3 + * +------------+ + * + */ + +#include "nl_base.h" + +namespace netlist::devices { + + // FIXME: m_E should activate deactivate m_A + + NETLIB_OBJECT(9321) + { + NETLIB_CONSTRUCTOR(9321) + , m_enable(*this, "m_enable", true) + , m_o(*this, "m_o", 0) + , m_A(*this, 0, "A{}", NETLIB_DELEGATE(in)) + , m_D(*this, 0, "D{}") + , m_E(*this, "E", NETLIB_DELEGATE(e)) + , m_power_pins(*this) + { + } + + private: + NETLIB_HANDLERI(in) + { + m_enable = m_E() ? false : true; // NOLINT + m_o = (m_A[1]() << 1) | m_A[0](); + for (std::size_t i=0; i<4; i++) + m_D[i].push((i == m_o && m_enable) ? 0 : 1, NLTIME_FROM_NS(21)); + } + + NETLIB_HANDLERI(e) + { + m_enable = m_E() ? false : true; // NOLINT + m_o = (m_A[1]() << 1) | m_A[0](); + for (std::size_t i=0; i<4; i++) + m_D[i].push((i == m_o && m_enable) ? 0 : 1, NLTIME_FROM_NS(18)); + } + + state_var<bool> m_enable; + state_var<uint32_t> m_o; + object_array_t<logic_input_t, 2> m_A; + object_array_t<logic_output_t, 4> m_D; + logic_input_t m_E; + nld_power_pins m_power_pins; + }; + + NETLIB_DEVICE_IMPL(9321, "TTL_9321", "+E,+A0,+A1") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9322.cpp b/src/lib/netlist/devices/nld_9322.cpp index 14b0a846053..c7ac59be619 100644 --- a/src/lib/netlist/devices/nld_9322.cpp +++ b/src/lib/netlist/devices/nld_9322.cpp @@ -3,35 +3,55 @@ /* * nld_9322.cpp * + * 9322: Quad 2-Line to 1-Line Data Selectors/Multiplexers + * + * +------------+ + * SELECT |1 ++ 16| VCC + * A1 |2 15| STROBE + * B1 |3 14| A4 + * Y1 |4 9322 13| B4 + * A2 |5 12| Y4 + * B2 |6 11| A3 + * Y2 |7 10| B3 + * GND |8 9| Y3 + * +------------+ + * */ -#include "nld_9322.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { class NETLIB_NAME(9322); - NETLIB_OBJECT(9322_selector) + NETLIB_OBJECT(9322_GATE) { - NETLIB_CONSTRUCTOR(9322_selector) - , m_parent(owner) - , m_A(*this, "A") - , m_B(*this, "B") + NETLIB_CONSTRUCTOR(9322_GATE) + , m_A(*this, "A", NETLIB_DELEGATE(inputs)) + , m_B(*this, "B", NETLIB_DELEGATE(inputs)) + , m_SELECT(*this, "SELECT", NETLIB_DELEGATE(inputs)) + , m_STROBE(*this, "STROBE", NETLIB_DELEGATE(inputs)) , m_Y(*this, "Y") , m_power_pins(*this) { } - NETLIB_UPDATEI(); + // FIXME: Timing + NETLIB_HANDLERI(inputs) + { + if (m_STROBE()) + m_Y.push(0, NLTIME_FROM_NS(21)); + else if (m_SELECT()) + m_Y.push(m_B(), NLTIME_FROM_NS(14)); + else + m_Y.push(m_A(), NLTIME_FROM_NS(14)); + } public: - NETLIB_NAME(9322) &m_parent; logic_input_t m_A; logic_input_t m_B; + logic_input_t m_SELECT; + logic_input_t m_STROBE; logic_output_t m_Y; nld_power_pins m_power_pins; }; @@ -39,25 +59,23 @@ namespace netlist NETLIB_OBJECT(9322) { NETLIB_CONSTRUCTOR(9322) - , m_SELECT(*this, "SELECT") - , m_STROBE(*this, "STROBE") , m_1(*this, "A") , m_2(*this, "B") , m_3(*this, "C") , m_4(*this, "D") { - register_subalias("A1", m_1.m_A); - register_subalias("B1", m_1.m_B); - register_subalias("Y1", m_1.m_Y); - register_subalias("A2", m_2.m_A); - register_subalias("B2", m_2.m_B); - register_subalias("Y2", m_2.m_Y); - register_subalias("A3", m_3.m_A); - register_subalias("B3", m_3.m_B); - register_subalias("Y3", m_3.m_Y); - register_subalias("A4", m_4.m_A); - register_subalias("B4", m_4.m_B); - register_subalias("Y4", m_4.m_Y); + register_sub_alias("A1", "A.A"); + register_sub_alias("B1", "A.B"); + register_sub_alias("Y1", "A.Y"); + register_sub_alias("A2", "B.A"); + register_sub_alias("B2", "B.B"); + register_sub_alias("Y2", "B.Y"); + register_sub_alias("A3", "C.A"); + register_sub_alias("B3", "C.B"); + register_sub_alias("Y3", "C.Y"); + register_sub_alias("A4", "D.A"); + register_sub_alias("B4", "D.B"); + register_sub_alias("Y4", "D.Y"); connect("A.VCC", "B.VCC"); connect("A.VCC", "C.VCC"); @@ -65,70 +83,27 @@ namespace netlist connect("A.GND", "B.GND"); connect("A.GND", "C.GND"); connect("A.GND", "D.GND"); - - register_subalias("GND", "A.GND"); - register_subalias("VCC", "B.VCC"); - + connect("A.SELECT", "B.SELECT"); + connect("A.SELECT", "C.SELECT"); + connect("A.SELECT", "D.SELECT"); + connect("A.STROBE", "B.STROBE"); + connect("A.STROBE", "C.STROBE"); + connect("A.STROBE", "D.STROBE"); + + register_sub_alias("SELECT", "A.SELECT"); + register_sub_alias("STROBE", "A.STROBE"); + register_sub_alias("GND", "A.GND"); + register_sub_alias("VCC", "B.VCC"); } - NETLIB_UPDATEI(); - - public: - logic_input_t m_SELECT; - logic_input_t m_STROBE; - protected: - NETLIB_SUB(9322_selector) m_1; - NETLIB_SUB(9322_selector) m_2; - NETLIB_SUB(9322_selector) m_3; - NETLIB_SUB(9322_selector) m_4; - - }; - - NETLIB_OBJECT_DERIVED(9322_dip, 9322) - { - NETLIB_CONSTRUCTOR_DERIVED(9322_dip, 9322) - { - register_subalias("1", m_SELECT); - register_subalias("2", m_1.m_A); - register_subalias("3", m_1.m_B); - register_subalias("4", m_1.m_Y); - register_subalias("5", m_2.m_A); - register_subalias("6", m_2.m_B); - register_subalias("7", m_2.m_Y); - register_subalias("8", "GND"); + private: + NETLIB_SUB(9322_GATE) m_1; + NETLIB_SUB(9322_GATE) m_2; + NETLIB_SUB(9322_GATE) m_3; + NETLIB_SUB(9322_GATE) m_4; - register_subalias("9", m_3.m_Y); - register_subalias("10", m_3.m_B); - register_subalias("11", m_3.m_A); - register_subalias("12", m_4.m_Y); - register_subalias("13", m_4.m_B); - register_subalias("14", m_4.m_A); - register_subalias("15", m_STROBE); - register_subalias("16", "VCC"); - } }; - // FIXME: Timing - NETLIB_UPDATE(9322_selector) - { - if (m_parent.m_STROBE()) - m_Y.push(0, NLTIME_FROM_NS(21)); - else if (m_parent.m_SELECT()) - m_Y.push(m_B(), NLTIME_FROM_NS(14)); - else - m_Y.push(m_A(), NLTIME_FROM_NS(14)); - } - - NETLIB_UPDATE(9322) - { - m_1.update(); - m_2.update(); - m_3.update(); - m_4.update(); - } - - NETLIB_DEVICE_IMPL(9322, "TTL_9322", "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE,@VCC,@GND") - NETLIB_DEVICE_IMPL(9322_dip, "TTL_9322_DIP", "") + NETLIB_DEVICE_IMPL(9322, "TTL_9322", "+SELECT,+A1,+B1,+A2,+B2,+A3,+B3,+A4,+B4,+STROBE,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_9322.h b/src/lib/netlist/devices/nld_9322.h deleted file mode 100644 index e55c73847b3..00000000000 --- a/src/lib/netlist/devices/nld_9322.h +++ /dev/null @@ -1,44 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_9322.h - * - * 9322: Quad 2-Line to 1-Line Data Selectors/Multiplexers - * - * +------------+ - * SELECT |1 ++ 16| VCC - * A1 |2 15| STROBE - * B1 |3 14| A4 - * Y1 |4 9322 13| B4 - * A2 |5 12| Y4 - * B2 |6 11| A3 - * Y2 |7 10| B3 - * GND |8 9| Y3 - * +------------+ - * - */ - -#ifndef NLD_9322_H_ -#define NLD_9322_H_ - -#include "netlist/nl_setup.h" - -#define TTL_9322(name, cSELECT, cA1, cB1, cA2, cB2, cA3, cB3, cA4, cB4, cSTROBE) \ - NET_REGISTER_DEV(TTL_9322, name) \ - NET_CONNECT(name, SELECT, cSELECT) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, B1, cB1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, B2, cB2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, B3, cB3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, B4, cB4) \ - NET_CONNECT(name, STROBE, cSTROBE) - -#define TTL_9322_DIP(name) \ - NET_REGISTER_DEV(TTL_9322_DIP, name) - -#endif /* NLD_9322_H_ */ diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp index d4a7cbe53b7..07b811ab0a9 100644 --- a/src/lib/netlist/devices/nld_am2847.cpp +++ b/src/lib/netlist/devices/nld_am2847.cpp @@ -3,39 +3,63 @@ /* * nld_am2847.cpp * + * Am2847: Quad 80-Bit Static Shift Register + * + * +--------------+ + * OUTA |1 ++ 16| VSS + * RCA |2 15| IND + * INA |3 14| RCD + * OUTB |4 Am2847 13| OUTD + * RCB |5 12| VGG + * INB |6 11| CP + * OUTC |7 10| INC + * VDD |8 9| RCC + * +--------------+ + * */ -#include "nld_am2847.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(Am2847_shifter) { - NETLIB_CONSTRUCTOR(Am2847_shifter) - , m_RC(*this, "RC") - , m_IN(*this, "IN") + NETLIB_CONSTRUCTOR_MODEL(Am2847_shifter, "CD4XXX") + , m_RC(*this, "RC", NETLIB_DELEGATE(inputs)) + , m_IN(*this, "IN", NETLIB_DELEGATE(inputs)) , m_buffer(*this, "m_buffer", 0) , m_OUT(*this, "OUT") - , m_power_pins(*this, "VSS", "VDD") + , m_power_pins(*this) { } - NETLIB_UPDATEI(); - public: - void shift(); + void shift() noexcept + { + uint32_t out = m_buffer[0] & 1; + uint32_t in = (m_RC() ? out : m_IN()); + for (std::size_t i=0; i < 5; i++) + { + uint32_t shift_in = (i == 4) ? in : m_buffer[i + 1]; + m_buffer[i] >>= 1; + m_buffer[i] |= shift_in << 15; + } + + m_OUT.push(out, NLTIME_FROM_NS(200)); + } logic_input_t m_RC; logic_input_t m_IN; - state_array<uint16_t, 5> m_buffer; + state_container<std::array<uint16_t, 5>> m_buffer; logic_output_t m_OUT; nld_power_pins m_power_pins; + private: + NETLIB_HANDLERI(inputs) + { + /* do nothing */ + } }; NETLIB_OBJECT(AM2847) @@ -45,22 +69,22 @@ namespace netlist , m_B(*this, "B") , m_C(*this, "C") , m_D(*this, "D") - , m_CP(*this, "CP") + , m_CP(*this, "CP", NETLIB_DELEGATE(cp)) , m_last_CP(*this, "m_last_CP", 0) // FIXME: needs family! { - register_subalias("OUTA", m_A.m_OUT); - register_subalias("OUTB", m_B.m_OUT); - register_subalias("OUTC", m_C.m_OUT); - register_subalias("OUTD", m_D.m_OUT); - register_subalias("INA", m_A.m_IN); - register_subalias("INB", m_B.m_IN); - register_subalias("INC", m_C.m_IN); - register_subalias("IND", m_D.m_IN); - register_subalias("RCA", m_A.m_RC); - register_subalias("RCB", m_B.m_RC); - register_subalias("RCC", m_C.m_RC); - register_subalias("RCD", m_D.m_RC); + register_sub_alias("OUTA", "A.OUT"); + register_sub_alias("OUTB", "B.OUT"); + register_sub_alias("OUTC", "C.OUT"); + register_sub_alias("OUTD", "D.OUT"); + register_sub_alias("INA", "A.IN"); + register_sub_alias("INB", "B.IN"); + register_sub_alias("INC", "C.IN"); + register_sub_alias("IND", "D.IN"); + register_sub_alias("RCA", "A.RC"); + register_sub_alias("RCB", "B.RC"); + register_sub_alias("RCC", "C.RC"); + register_sub_alias("RCD", "D.RC"); connect("A.VSS", "B.VSS"); connect("A.VSS", "C.VSS"); @@ -69,14 +93,28 @@ namespace netlist connect("A.VDD", "C.VDD"); connect("A.VDD", "D.VDD"); - register_subalias("VSS", "A.VSS"); - register_subalias("VDD", "A.VDD"); + register_sub_alias("VSS", "A.VSS"); + register_sub_alias("VDD", "A.VDD"); + } + + NETLIB_RESETI() + { + m_last_CP = 0; } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + private: + NETLIB_HANDLERI(cp) + { + if (m_last_CP && !m_CP()) + { + m_A().shift(); + m_B().shift(); + m_C().shift(); + m_D().shift(); + } + m_last_CP = m_CP(); + } - protected: NETLIB_SUB(Am2847_shifter) m_A; NETLIB_SUB(Am2847_shifter) m_B; NETLIB_SUB(Am2847_shifter) m_C; @@ -86,67 +124,6 @@ namespace netlist state_var<uint32_t> m_last_CP; }; - NETLIB_OBJECT_DERIVED(AM2847_dip, AM2847) - { - NETLIB_CONSTRUCTOR_DERIVED(AM2847_dip, AM2847) - { - register_subalias("1", m_A.m_OUT); - register_subalias("2", m_A.m_RC); - register_subalias("3", m_A.m_IN); - register_subalias("4", m_B.m_OUT); - register_subalias("5", m_B.m_RC); - register_subalias("6", m_B.m_IN); - register_subalias("7", m_C.m_OUT); - register_subalias("8", "VDD"); - - register_subalias("9", m_C.m_RC); - register_subalias("10", m_C.m_IN); - register_subalias("11", m_CP); - register_subalias("13", m_D.m_OUT); - register_subalias("14", m_D.m_RC); - register_subalias("15", m_D.m_IN); - register_subalias("16", "VSS"); - } - }; - - NETLIB_RESET(AM2847) - { - m_last_CP = 0; - } - - NETLIB_UPDATE(AM2847) - { - if (m_last_CP && !m_CP()) - { - m_A.shift(); - m_B.shift(); - m_C.shift(); - m_D.shift(); - } - m_last_CP = m_CP(); - } - - NETLIB_UPDATE(Am2847_shifter) - { - /* do nothing */ - } - - NETLIB_FUNC_VOID(Am2847_shifter, shift, ()) - { - uint32_t out = m_buffer[0] & 1; - uint32_t in = (m_RC() ? out : m_IN()); - for (std::size_t i=0; i < 5; i++) - { - uint32_t shift_in = (i == 4) ? in : m_buffer[i + 1]; - m_buffer[i] >>= 1; - m_buffer[i] |= shift_in << 15; - } - - m_OUT.push(out, NLTIME_FROM_NS(200)); - } - NETLIB_DEVICE_IMPL(AM2847, "TTL_AM2847", "+CP,+INA,+INB,+INC,+IND,+RCA,+RCB,+RCC,+RCD,@VSS,@VDD") - NETLIB_DEVICE_IMPL(AM2847_dip, "TTL_AM2847_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_am2847.h b/src/lib/netlist/devices/nld_am2847.h deleted file mode 100644 index f1347545984..00000000000 --- a/src/lib/netlist/devices/nld_am2847.h +++ /dev/null @@ -1,43 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_am2847.h - * - * Am2847: Quad 80-Bit Static Shift Register - * - * +--------------+ - * OUTA |1 ++ 16| VSS - * RCA |2 15| IND - * INA |3 14| RCD - * OUTB |4 Am2847 13| OUTD - * RCB |5 12| VGG - * INB |6 11| CP - * OUTC |7 10| INC - * VDD |8 9| RCC - * +--------------+ - * - */ - -#ifndef NLD_AM2847_H_ -#define NLD_AM2847_H_ - -#include "netlist/nl_setup.h" - -#define TTL_AM2847(name, cCP, cINA, cINB, cINC, cIND, cRCA, cRCB, cRCC, cRCD) \ - NET_REGISTER_DEV(TTL_AM2847, name) \ - NET_CONNECT(name, VDD, VDD) \ - NET_CONNECT(name, VSS, VSS) \ - NET_CONNECT(name, CP, cCP) \ - NET_CONNECT(name, INA, cINA) \ - NET_CONNECT(name, INB, cINB) \ - NET_CONNECT(name, INC, cINC) \ - NET_CONNECT(name, IND, cIND) \ - NET_CONNECT(name, RCA, cRCA) \ - NET_CONNECT(name, RCB, cRCB) \ - NET_CONNECT(name, RCC, cRCC) \ - NET_CONNECT(name, RCD, cRCD) - -#define TTL_AM2847_DIP(name) \ - NET_REGISTER_DEV(TTL_AM2847_DIP, name) - -#endif /* NLD_AM2847_H_ */ diff --git a/src/lib/netlist/devices/nld_dm9314.cpp b/src/lib/netlist/devices/nld_dm9314.cpp index e193fd08f46..e8241af09de 100644 --- a/src/lib/netlist/devices/nld_dm9314.cpp +++ b/src/lib/netlist/devices/nld_dm9314.cpp @@ -3,24 +3,33 @@ /* * nld_dm9314.cpp * + * DM9314: 4-Bit Latches + * + * +--------------+ + * /E |1 ++ 16| VCC + * /S0 |2 15| Q0 + * D0 |3 14| /S1 + * D1 |4 DM9314 13| Q1 + * /S2 |5 12| Q2 + * D2 |6 11| /S3 + * D3 |7 10| Q3 + * GND |8 9| /MR + * +--------------+ + * */ -#include "nld_dm9314.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(9314) { NETLIB_CONSTRUCTOR(9314) - , m_EQ(*this, "EQ") - , m_MRQ(*this, "MRQ") - , m_SQ(*this, {{"S0Q", "S1Q", "S2Q", "S3Q"}}) - , m_D(*this, {{"D0", "D1", "D2", "D3"}}) - , m_Q(*this, {{"Q0", "Q1", "Q2", "Q3"}}) + , m_EQ(*this, "EQ", NETLIB_DELEGATE(inputs)) + , m_MRQ(*this, "MRQ", NETLIB_DELEGATE(inputs)) + , m_SQ(*this, {"S0Q", "S1Q", "S2Q", "S3Q"}, NETLIB_DELEGATE(inputs)) + , m_D(*this, {"D0", "D1", "D2", "D3"}, NETLIB_DELEGATE(inputs)) + , m_Q(*this, {"Q0", "Q1", "Q2", "Q3"}) , m_last_EQ(*this, "m_last_EQ", 0) , m_last_MRQ(*this, "m_last_MRQ", 0) , m_last_SQ(*this, "m_last_SQ", 0) @@ -30,10 +39,59 @@ namespace netlist { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + private: + + NETLIB_RESETI() + { + m_last_MRQ = 0; + m_last_EQ = 0; + m_last_SQ = 0; + m_last_D = 0; + m_last_Q = 0; + } + + NETLIB_HANDLERI(inputs) + { + netlist_time delay = NLTIME_FROM_NS(24); //FIXME! + if (!m_MRQ()) + { + /* Reset! */ + for (std::size_t i=0; i<4; i++) + m_Q[i].push(0, delay); + } else { + for (std::size_t i=0; i<4; i++) + { + if (m_SQ[i]()) + { + /* R-S Mode */ + // RS mode is just an "extension of regular D mode" + // The way RS mode works is that D and S bar go high (keeps old value) + // S bar going low sets output high + // D going low and S bar high sets output low + // S bar going low AND D going low sets output low (D takes precedence) + if (!m_EQ()) + { + if (!m_D[i]()) // if D low and SQ high we clear the bit + { + m_last_Q &= ~(1 << i); + m_Q[i].push((m_last_Q & (1<<i))>>i, delay); + } + } + } + else + { + /* D Mode */ + if (!m_EQ()) + { + m_Q[i].push(m_D[i](), delay); + m_last_Q &= ~(1 << i); + m_last_Q |= (m_D[i]() << i); + } + } + } + } + } - protected: logic_input_t m_EQ; logic_input_t m_MRQ; object_array_t<logic_input_t, 4> m_SQ; @@ -48,72 +106,6 @@ namespace netlist nld_power_pins m_power_pins; }; - NETLIB_OBJECT_DERIVED(9314_dip, 9314) - { - NETLIB_CONSTRUCTOR_DERIVED(9314_dip, 9314) - { - register_subalias("1", m_EQ); - register_subalias("2", m_SQ[0]); - register_subalias("3", m_D[0]); - register_subalias("4", m_D[1]); - register_subalias("5", m_SQ[2]); - register_subalias("6", m_D[2]); - register_subalias("7", m_D[3]); - register_subalias("8", "GND"); - - register_subalias("9", m_MRQ); - register_subalias("10", m_Q[3]); - register_subalias("11", m_SQ[3]); - register_subalias("12", m_Q[2]); - register_subalias("13", m_Q[1]); - register_subalias("14", m_SQ[1]); - register_subalias("15", m_Q[0]); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_RESET(9314) - { - m_last_MRQ = 0; - m_last_EQ = 0; - m_last_SQ = 0; - m_last_D = 0; - m_last_Q = 0; - } - - NETLIB_UPDATE(9314) - { - netlist_time delay = NLTIME_FROM_NS(24); //FIXME! - if (!m_MRQ()) - { - /* Reset! */ - for (std::size_t i=0; i<4; i++) - m_Q[i].push(0, delay); - } else { - for (std::size_t i=0; i<4; i++) - { - if (m_SQ[i]()) - { - /* R-S Mode */ - // FIXME: R-S mode is not yet implemented! - } - else - { - /* D Mode */ - if (!m_EQ()) - { - m_Q[i].push(m_D[i](), delay); - m_last_Q &= ~(1 << i); - m_last_Q |= (m_D[i]() << i); - } - } - } - } - } - NETLIB_DEVICE_IMPL(9314, "TTL_9314", "+EQ,+MRQ,+S0Q,+S1Q,+S2Q,+S3Q,+D0,+D1,+D2,+D3,@VCC,@GND") - NETLIB_DEVICE_IMPL(9314_dip, "TTL_9314_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_dm9314.h b/src/lib/netlist/devices/nld_dm9314.h deleted file mode 100644 index 73edfaa1205..00000000000 --- a/src/lib/netlist/devices/nld_dm9314.h +++ /dev/null @@ -1,44 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Felipe Sanches -/* - * nld_DM9314.h - * - * DM9314: 4-Bit Latches - * - * +--------------+ - * /E |1 ++ 16| VCC - * /S0 |2 15| Q0 - * D0 |3 14| /S1 - * D1 |4 DM9314 13| Q1 - * /S2 |5 12| Q2 - * D2 |6 11| /S3 - * D3 |7 10| Q3 - * GND |8 9| /MR - * +--------------+ - * - */ - -#ifndef NLD_DM9314_H_ -#define NLD_DM9314_H_ - -#include "netlist/nl_setup.h" - -#define TTL_9314(name, cEQ, cMRQ, cS0Q, cS1Q, cS2Q, cS3Q, cD0, cD1, cD2, cD3) \ - NET_REGISTER_DEV(TTL_9314, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, EQ, cEQ) \ - NET_CONNECT(name, MRQ, cMRQ) \ - NET_CONNECT(name, S0Q, cS0Q) \ - NET_CONNECT(name, S1Q, cS1Q) \ - NET_CONNECT(name, S2Q, cS2Q) \ - NET_CONNECT(name, S3Q, cS3Q) \ - NET_CONNECT(name, D0, cD0) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, D2, cD2) \ - NET_CONNECT(name, D3, cD3) - -#define TTL_9314_DIP(name) \ - NET_REGISTER_DEV(TTL_9314_DIP, name) - -#endif /* NLD_DM9314_H_ */ diff --git a/src/lib/netlist/devices/nld_dm9334.cpp b/src/lib/netlist/devices/nld_dm9334.cpp index 56226b36fe6..1631ed99264 100644 --- a/src/lib/netlist/devices/nld_dm9334.cpp +++ b/src/lib/netlist/devices/nld_dm9334.cpp @@ -3,24 +3,77 @@ /* * nld_dm9334.cpp * + * DM9334: 8-Bit Addressable Latch + * + * +--------------+ + * A0 |1 ++ 16| VCC + * A1 |2 15| /C + * A2 |3 14| /E + * Q0 |4 DM9334 13| D + * Q1 |5 12| Q7 + * Q2 |6 11| Q6 + * Q3 |7 10| Q5 + * GND |8 9| Q4 + * +--------------+ + * + * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ + * | C | E || D || A0| A1| A2|| Q0| Q1| Q2| Q3| Q4| Q5| Q6| Q7| + * +===+===++===++===+===+===++===+===+===+===+===+===+===+===+ + * | 1 | 0 || X || X | X | X || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ + * | 1 | 1 || 0 || 0 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 0 | 0 | 0 || 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 0 || 0 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 0 | 0 | 1 || 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 0 || 0 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 0 | 1 | 0 || 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 0 || 0 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 0 | 1 | 1 || 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 0 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | + * | 1 | 1 || 0 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | + * | 1 | 1 || 0 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | + * | 1 | 1 || 0 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * | 1 | 1 || 1 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | + * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ + * | 0 | 0 || X || X | X | X || P | P | P | P | P | P | P | P | + * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ + * | 0 | 1 || 0 || 0 | 0 | 0 || 0 | P | P | P | P | P | P | P | + * | 0 | 1 || 1 || 0 | 0 | 0 || 1 | P | P | P | P | P | P | P | + * | 0 | 1 || 0 || 0 | 0 | 1 || P | 0 | P | P | P | P | P | P | + * | 0 | 1 || 1 || 0 | 0 | 1 || P | 1 | P | P | P | P | P | P | + * | 0 | 1 || 0 || 0 | 1 | 0 || P | P | 0 | P | P | P | P | P | + * | 0 | 1 || 1 || 0 | 1 | 0 || P | P | 1 | P | P | P | P | P | + * | 0 | 1 || 0 || 0 | 1 | 1 || P | P | P | 0 | P | P | P | P | + * | 0 | 1 || 1 || 0 | 1 | 1 || P | P | P | 1 | P | P | P | P | + * | 0 | 1 || 0 || 1 | 0 | 0 || P | P | P | P | 0 | P | P | P | + * | 0 | 1 || 1 || 1 | 0 | 0 || P | P | P | P | 1 | P | P | P | + * | 0 | 1 || 0 || 1 | 0 | 1 || P | P | P | P | P | 0 | P | P | + * | 0 | 1 || 1 || 1 | 0 | 1 || P | P | P | P | P | 1 | P | P | + * | 0 | 1 || 0 || 1 | 1 | 0 || P | P | P | P | P | P | 0 | P | + * | 0 | 1 || 1 || 1 | 1 | 0 || P | P | P | P | P | P | 1 | P | + * | 0 | 1 || 0 || 1 | 1 | 1 || P | P | P | P | P | P | P | 0 | + * | 0 | 1 || 1 || 1 | 1 | 1 || P | P | P | P | P | P | P | 1 | + * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ + * + * Naming convention attempts to follow Texas Instruments / National Semiconductor datasheet Literature Number SNOS382A + * */ -#include "nld_dm9334.h" -#include "netlist/nl_base.h" -#include "nlid_system.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(9334) { NETLIB_CONSTRUCTOR(9334) - , m_CQ(*this, "CQ") - , m_EQ(*this, "EQ") - , m_D(*this, "D") - , m_A(*this, {{"A0", "A1", "A2"}}) - , m_Q(*this, {{"Q0", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7"}}) + , m_CQ(*this, "CQ", NETLIB_DELEGATE(inputs)) + , m_EQ(*this, "EQ", NETLIB_DELEGATE(inputs)) + , m_D(*this, "D", NETLIB_DELEGATE(inputs)) + , m_A(*this, {"A0", "A1", "A2"}, NETLIB_DELEGATE(inputs)) + , m_Q(*this, {"Q0", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7"}) , m_last_CQ(*this, "m_last_CQ", 0) , m_last_EQ(*this, "m_last_EQ", 0) , m_last_D(*this, "m_last_D", 0) @@ -30,126 +83,96 @@ namespace netlist { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - - protected: - logic_input_t m_CQ; - logic_input_t m_EQ; - logic_input_t m_D; - object_array_t<logic_input_t, 3> m_A; - object_array_t<logic_output_t, 8> m_Q; - - state_var<unsigned> m_last_CQ; - state_var<unsigned> m_last_EQ; - state_var<unsigned> m_last_D; - state_var<unsigned> m_last_A; - state_var<unsigned> m_last_Q; - nld_power_pins m_power_pins; - }; - - NETLIB_OBJECT_DERIVED(9334_dip, 9334) - { - NETLIB_CONSTRUCTOR_DERIVED(9334_dip, 9334) - { - register_subalias("1", m_A[0]); - register_subalias("2", m_A[1]); - register_subalias("3", m_A[2]); - register_subalias("4", m_Q[0]); - register_subalias("5", m_Q[1]); - register_subalias("6", m_Q[2]); - register_subalias("7", m_Q[3]); - register_subalias("8", "GND"); - - register_subalias("9", m_Q[4]); - register_subalias("10", m_Q[5]); - register_subalias("11", m_Q[6]); - register_subalias("12", m_Q[7]); - register_subalias("13", m_D); - register_subalias("14", m_EQ); - register_subalias("15", m_CQ); - register_subalias("16", "VCC"); - - } - }; - - NETLIB_RESET(9334) - { - m_last_CQ = 0; - m_last_EQ = 0; - m_last_D = 0; - m_last_A = 0; - m_last_Q = 0; - } - - NETLIB_UPDATE(9334) - { - uint_fast8_t a = 0; - for (std::size_t i=0; i<3; i++) + private: + NETLIB_RESETI() { - a |= (m_A[i]() << i); + m_last_CQ = 0; + m_last_EQ = 0; + m_last_D = 0; + m_last_A = 0; + m_last_Q = 0; } - netlist_time delay = NLTIME_FROM_NS(27); // Clear Low to High Level Output (not documented, making reasonable guess) - - if (a != m_last_A) + NETLIB_HANDLERI(inputs) { - delay = NLTIME_FROM_NS(35); - } - else if (m_D() != m_last_D) - { - if (m_last_D) + uint_fast8_t a = 0; + for (std::size_t i=0; i<3; i++) { - delay = NLTIME_FROM_NS(28); + a |= (m_A[i]() << i); } - else + + netlist_time delay = NLTIME_FROM_NS(27); // Clear Low to High Level Output (not documented, making reasonable guess) + + if (a != m_last_A) { delay = NLTIME_FROM_NS(35); } - } - else if (m_EQ() != m_last_EQ) - { - if (m_last_EQ) + else if (m_D() != m_last_D) { - delay = NLTIME_FROM_NS(27); + if (m_last_D) + { + delay = NLTIME_FROM_NS(28); + } + else + { + delay = NLTIME_FROM_NS(35); + } } - else + else if (m_EQ() != m_last_EQ) { - delay = NLTIME_FROM_NS(28); + if (m_last_EQ) + { + delay = NLTIME_FROM_NS(27); + } + else + { + delay = NLTIME_FROM_NS(28); + } } - } - unsigned q = m_last_Q; + unsigned q = m_last_Q; - if (!m_CQ()) - { - if (m_EQ()) + if (!m_CQ()) { - q = 0; + if (m_EQ()) + { + q = 0; + } + else + { + q = m_D() << a; + } } - else + else if(!m_EQ()) { - q = m_D() << a; + q &= ~(1 << a); + q |= (m_D() << a); } - } - else if(!m_EQ()) - { - q &= ~(1 << a); - q |= (m_D() << a); + + m_last_CQ = m_CQ(); + m_last_EQ = m_EQ(); + m_last_D = m_D(); + m_last_A = a; + m_last_Q = q; + + for (std::size_t i=0; i<8; i++) + m_Q[i].push((q >> i) & 1, delay); } - m_last_CQ = m_CQ(); - m_last_EQ = m_EQ(); - m_last_D = m_D(); - m_last_A = a; - m_last_Q = q; + logic_input_t m_CQ; + logic_input_t m_EQ; + logic_input_t m_D; + object_array_t<logic_input_t, 3> m_A; + object_array_t<logic_output_t, 8> m_Q; - for (std::size_t i=0; i<8; i++) - m_Q[i].push((q >> i) & 1, delay); - } + state_var<unsigned> m_last_CQ; + state_var<unsigned> m_last_EQ; + state_var<unsigned> m_last_D; + state_var<unsigned> m_last_A; + state_var<unsigned> m_last_Q; + nld_power_pins m_power_pins; + }; NETLIB_DEVICE_IMPL(9334, "TTL_9334", "+CQ,+EQ,+D,+A0,+A1,+A2,@VCC,@GND") - NETLIB_DEVICE_IMPL(9334_dip, "TTL_9334_DIP", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_dm9334.h b/src/lib/netlist/devices/nld_dm9334.h deleted file mode 100644 index 2f4ab1f18c1..00000000000 --- a/src/lib/netlist/devices/nld_dm9334.h +++ /dev/null @@ -1,84 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_DM9334.h - * - * DM9334: 8-Bit Addressable Latch - * - * +--------------+ - * A0 |1 ++ 16| VCC - * A1 |2 15| /C - * A2 |3 14| /E - * Q0 |4 DM9334 13| D - * Q1 |5 12| Q7 - * Q2 |6 11| Q6 - * Q3 |7 10| Q5 - * GND |8 9| Q4 - * +--------------+ - * - * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ - * | C | E || D || A0| A1| A2|| Q0| Q1| Q2| Q3| Q4| Q5| Q6| Q7| - * +===+===++===++===+===+===++===+===+===+===+===+===+===+===+ - * | 1 | 0 || X || X | X | X || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ - * | 1 | 1 || 0 || 0 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 0 | 0 | 0 || 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 0 || 0 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 0 | 0 | 1 || 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 0 || 0 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 0 | 1 | 0 || 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 0 || 0 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 0 | 1 | 1 || 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 0 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | - * | 1 | 1 || 0 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | - * | 1 | 1 || 0 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | - * | 1 | 1 || 0 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | - * | 1 | 1 || 1 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | - * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ - * | 0 | 0 || X || X | X | X || P | P | P | P | P | P | P | P | - * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ - * | 0 | 1 || 0 || 0 | 0 | 0 || 0 | P | P | P | P | P | P | P | - * | 0 | 1 || 1 || 0 | 0 | 0 || 1 | P | P | P | P | P | P | P | - * | 0 | 1 || 0 || 0 | 0 | 1 || P | 0 | P | P | P | P | P | P | - * | 0 | 1 || 1 || 0 | 0 | 1 || P | 1 | P | P | P | P | P | P | - * | 0 | 1 || 0 || 0 | 1 | 0 || P | P | 0 | P | P | P | P | P | - * | 0 | 1 || 1 || 0 | 1 | 0 || P | P | 1 | P | P | P | P | P | - * | 0 | 1 || 0 || 0 | 1 | 1 || P | P | P | 0 | P | P | P | P | - * | 0 | 1 || 1 || 0 | 1 | 1 || P | P | P | 1 | P | P | P | P | - * | 0 | 1 || 0 || 1 | 0 | 0 || P | P | P | P | 0 | P | P | P | - * | 0 | 1 || 1 || 1 | 0 | 0 || P | P | P | P | 1 | P | P | P | - * | 0 | 1 || 0 || 1 | 0 | 1 || P | P | P | P | P | 0 | P | P | - * | 0 | 1 || 1 || 1 | 0 | 1 || P | P | P | P | P | 1 | P | P | - * | 0 | 1 || 0 || 1 | 1 | 0 || P | P | P | P | P | P | 0 | P | - * | 0 | 1 || 1 || 1 | 1 | 0 || P | P | P | P | P | P | 1 | P | - * | 0 | 1 || 0 || 1 | 1 | 1 || P | P | P | P | P | P | P | 0 | - * | 0 | 1 || 1 || 1 | 1 | 1 || P | P | P | P | P | P | P | 1 | - * +---+---++---++---+---+---++---+---+---+---+---+---+---+---+ - * - * Naming convention attempts to follow Texas Instruments / National Semiconductor datasheet Literature Number SNOS382A - * - */ - -#ifndef NLD_DM9334_H_ -#define NLD_DM9334_H_ - -#include "netlist/nl_setup.h" - -#define TTL_9334(name, cCQ, cEQ, cD, cA0, cA1, cA2) \ - NET_REGISTER_DEV(TTL_9334, name) \ - NET_CONNECT(name, GND, GND) \ - NET_CONNECT(name, VCC, VCC) \ - NET_CONNECT(name, CQ, cCQ) \ - NET_CONNECT(name, EQ, cEQ) \ - NET_CONNECT(name, D, cD) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) - -#define TTL_9334_DIP(name) \ - NET_REGISTER_DEV(TTL_9334_DIP, name) - -#endif /* NLD_DM9334_H_ */ diff --git a/src/lib/netlist/devices/nld_legacy.cpp b/src/lib/netlist/devices/nld_legacy.cpp index 738230646e0..cbc44f589a8 100644 --- a/src/lib/netlist/devices/nld_legacy.cpp +++ b/src/lib/netlist/devices/nld_legacy.cpp @@ -1,31 +1,45 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* * nld_legacy.c * */ -#include "nld_legacy.h" -#include "netlist/nl_base.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(nicRSFF) { NETLIB_CONSTRUCTOR(nicRSFF) - , m_S(*this, "S") - , m_R(*this, "R") + , m_S(*this, "S", NETLIB_DELEGATE(inputs)) + , m_R(*this, "R", NETLIB_DELEGATE(inputs)) , m_Q(*this, "Q") , m_QQ(*this, "QQ") { } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + m_Q.initial(0); + m_QQ.initial(1); + } private: + NETLIB_HANDLERI(inputs) + { + if (!m_S()) + { + m_Q.push(1, NLTIME_FROM_NS(20)); + m_QQ.push(0, NLTIME_FROM_NS(20)); + } + else if (!m_R()) + { + m_Q.push(0, NLTIME_FROM_NS(20)); + m_QQ.push(1, NLTIME_FROM_NS(20)); + } + } + logic_input_t m_S; logic_input_t m_R; @@ -37,7 +51,7 @@ namespace netlist NETLIB_OBJECT(nicDelay) { NETLIB_CONSTRUCTOR(nicDelay) - , m_I(*this, "1") + , m_I(*this, "1", NETLIB_DELEGATE(input)) , m_Q(*this, "2") , m_L_to_H(*this, "L_TO_H", 10) , m_H_to_L(*this, "H_TO_L", 10) @@ -46,10 +60,28 @@ namespace netlist } //NETLIB_UPDATE_PARAMI(); - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_RESETI() + { + //m_Q.initial(0); + } private: + NETLIB_HANDLERI(input) + { + netlist_sig_t nval = m_I(); + if (nval && !m_last) + { + // L_to_H + m_Q.push(1, NLTIME_FROM_NS(static_cast<unsigned>(m_L_to_H()))); + } + else if (!nval && m_last) + { + // H_to_L + m_Q.push(0, NLTIME_FROM_NS(static_cast<unsigned>(m_H_to_L()))); + } + m_last = nval; + } + logic_input_t m_I; logic_output_t m_Q; @@ -59,49 +91,7 @@ namespace netlist state_var<netlist_sig_t> m_last; }; - NETLIB_RESET(nicRSFF) - { - m_Q.initial(0); - m_QQ.initial(1); - } - - NETLIB_UPDATE(nicRSFF) - { - if (!m_S()) - { - m_Q.push(1, NLTIME_FROM_NS(20)); - m_QQ.push(0, NLTIME_FROM_NS(20)); - } - else if (!m_R()) - { - m_Q.push(0, NLTIME_FROM_NS(20)); - m_QQ.push(1, NLTIME_FROM_NS(20)); - } - } - - NETLIB_RESET(nicDelay) - { - //m_Q.initial(0); - } - - NETLIB_UPDATE(nicDelay) - { - netlist_sig_t nval = m_I(); - if (nval && !m_last) - { - // L_to_H - m_Q.push(1, NLTIME_FROM_NS(static_cast<unsigned>(m_L_to_H()))); - } - else if (!nval && m_last) - { - // H_to_L - m_Q.push(0, NLTIME_FROM_NS(static_cast<unsigned>(m_H_to_L()))); - } - m_last = nval; - } - NETLIB_DEVICE_IMPL(nicRSFF, "NETDEV_RSFF", "") NETLIB_DEVICE_IMPL(nicDelay, "NETDEV_DELAY", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_legacy.h b/src/lib/netlist/devices/nld_legacy.h deleted file mode 100644 index aa3aec6f147..00000000000 --- a/src/lib/netlist/devices/nld_legacy.h +++ /dev/null @@ -1,39 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_legacy.h - * - * All of the devices below needs to disappear at some time ..... - * - * - */ - -#pragma once - -#ifndef NLD_LEGACY_H_ -#define NLD_LEGACY_H_ - -#include "netlist/nl_setup.h" - -// ---------------------------------------------------------------------------------------- -// Macros -// ---------------------------------------------------------------------------------------- - -#define NETDEV_RSFF(name) \ - NET_REGISTER_DEV(NETDEV_RSFF, name) - -#define NETDEV_DELAY(name) \ - NET_REGISTER_DEV(NETDEV_DELAY, name) - -// ---------------------------------------------------------------------------------------- -// Devices ... -// ---------------------------------------------------------------------------------------- - -namespace netlist -{ - namespace devices - { - } //namespace devices -} // namespace netlist - -#endif /* NLD_LEGACY_H_ */ diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp index c8569f473c3..a3dae6a4b39 100644 --- a/src/lib/netlist/devices/nld_log.cpp +++ b/src/lib/netlist/devices/nld_log.cpp @@ -1,59 +1,152 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_log.c + * nld_log.cpp + * + * Devices supporting analysis and logging + * + * nld_log: + * + * +---------+ + * | ++ | + * I | | ==> Log to file "netlist_" + name() + ".log" + * | | + * +---------+ * */ -#include "netlist/nl_base.h" -#include "nld_log.h" +#include "nl_base.h" #include "plib/pfmtlog.h" +#include "plib/pmulti_threading.h" #include "plib/pstream.h" //#include "sound/wavwrite.h" -namespace netlist -{ - namespace devices - { +#include <array> +#include <atomic> +#include <functional> +#include <mutex> +#include <thread> +#include <vector> + +namespace netlist::devices { + NETLIB_OBJECT(log) { NETLIB_CONSTRUCTOR(log) - , m_I(*this, "I") + , m_I(*this, "I", NETLIB_DELEGATE(input)) , m_strm(plib::filesystem::u8path(plib::pfmt("{1}.log")(this->name()))) , m_writer(&m_strm) + , m_reset(false) + , m_done(false) + , m_sem_w(0) + , m_sem_r(0) + , m_w(0) + , m_r(0) { if (m_strm.fail()) throw plib::file_open_e(plib::pfmt("{1}.log")(this->name())); m_strm.imbue(std::locale::classic()); + + //m_write_thread = std::thread(std::bind(&nld_log::thread_writer, this)); + m_write_thread = std::thread([this]{this->thread_writer(); }); + m_sem_r.acquire(); + } + + PCOPYASSIGNMOVE(NETLIB_NAME(log), delete) + + NETLIB_DESTRUCTOR(log) + { + if (m_reset) + log_value(m_I()); + m_sem_w.release(); + m_done = true; + m_write_thread.join(); } - NETLIB_UPDATEI() + NETLIB_HANDLERI(input) { - /* use pstring::sprintf, it is a LOT faster */ - m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_double()).e(static_cast<double>(m_I()))); + log_value(static_cast<nl_fptype>(m_I())); } - NETLIB_RESETI() { } + void log_value(nl_fptype val) + { + if (m_buffers[m_w].size() == BUF_SIZE) + { + m_sem_w.release(); + m_sem_r.acquire(); + m_w++; + if (m_w >= BUFFERS) + m_w = 0; + } + m_buffers[m_w].push_back({exec().time(), val}); + } + + NETLIB_RESETI() { m_reset = true; } protected: + + void thread_writer() + { + m_sem_r.release(BUFFERS); + while (true) + { + if (!m_sem_w.try_acquire()) + { + if (m_done) + break; + m_sem_w.acquire(); + } + auto &b = m_buffers[m_r]; + + for (auto &e : b) + /* use pstring::sprintf, it is a LOT faster */ + m_writer.write_line(plib::pfmt("{1:.9} {2}").e(e.t.as_fp<nl_fptype>()).e(e.v)); + b.clear(); + m_sem_r.release(); + m_r++; + if (m_r >= BUFFERS) + m_r = 0; + } + } + + struct entry + { + netlist_time_ext t; + nl_fptype v; + }; + static constexpr std::size_t BUF_SIZE=16384; + static constexpr std::size_t BUFFERS=4; analog_input_t m_I; - std::ofstream m_strm; + private: + plib::ofstream m_strm; plib::putf8_writer m_writer; + bool m_reset; + std::array<std::vector<entry>, BUFFERS> m_buffers; + std::atomic<bool> m_done; + plib::psemaphore m_sem_w; + plib::psemaphore m_sem_r; + std::size_t m_w; + std::size_t m_r; + std::thread m_write_thread; }; - NETLIB_OBJECT_DERIVED(logD, log) + class NETLIB_NAME(logD) : public NETLIB_NAME(log) { - NETLIB_CONSTRUCTOR_DERIVED(logD, log) - , m_I2(*this, "I2") + public: + NETLIB_NAME(logD)(constructor_param_t data) + : NETLIB_NAME(log)(data) + , m_I2(*this, "I2", nl_delegate(&NETLIB_NAME(logD)::input, this)) { + m_I.set_delegate(nl_delegate(&NETLIB_NAME(logD)::input, this)); } - NETLIB_UPDATEI() + private: + NETLIB_HANDLERI(input) { - m_writer.writeline(plib::pfmt("{1:.9} {2}").e(exec().time().as_double()).e(static_cast<double>(m_I() - m_I2()))); + log_value(static_cast<nl_fptype>(m_I() - m_I2())); } - NETLIB_RESETI() { } + //NETLIB_RESETI() {} analog_input_t m_I2; }; @@ -62,7 +155,7 @@ namespace netlist ~NETLIB_NAME(wav)(); analog_input_t m_I; private: - // FIXME: rewrite sound/wavwrite.h to be an object ... + // FIXME: rewrite `sound/wavwrite.h` to be an object ... void *m_file; ); #endif @@ -71,7 +164,7 @@ namespace netlist // FIXME: Implement wav later, this must be clock triggered device where the input to be written - // is on a subdevice .. + // is on a sub device .. #if 0 NETLIB_START(wav) { @@ -83,7 +176,7 @@ namespace netlist NETLIB_UPDATE(wav) { - fprintf(m_file, "%e %e\n", netlist().time().as_double(), m_I()); + fprintf(m_file, "%e %e\n", netlist().time().as_fp<nl_fptype>(), m_I()); } NETLIB_NAME(log)::~NETLIB_NAME(wav)() @@ -96,5 +189,4 @@ namespace netlist NETLIB_DEVICE_IMPL(log, "LOG", "+I") NETLIB_DEVICE_IMPL(logD, "LOGD", "+I,+I2") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_log.h b/src/lib/netlist/devices/nld_log.h deleted file mode 100644 index 13c71ea7257..00000000000 --- a/src/lib/netlist/devices/nld_log.h +++ /dev/null @@ -1,32 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_log.h - * - * Devices supporting analysis and logging - * - * nld_log: - * - * +---------+ - * | ++ | - * I | | ==> Log to file "netlist_" + name() + ".log" - * | | - * +---------+ - * - */ - -#ifndef NLD_LOG_H_ -#define NLD_LOG_H_ - -#include "netlist/nl_setup.h" - -#define LOG(name, cI) \ - NET_REGISTER_DEV(LOG, name) \ - NET_CONNECT(name, I, cI) - -#define LOGD(name, cI, cI2) \ - NET_REGISTER_DEV(LOGD, name) \ - NET_CONNECT(name, I, cI) \ - NET_CONNECT(name, I2, cI2) - -#endif /* NLD_LOG_H_ */ diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp index a8add5aaeea..cd92ce1e5df 100644 --- a/src/lib/netlist/devices/nld_mm5837.cpp +++ b/src/lib/netlist/devices/nld_mm5837.cpp @@ -1,57 +1,106 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_MM5837.c + * nld_MM5837.cpp + * + * MM5837: Digital noise source + * + * +--------+ + * VDD |1 ++ 8| NC + * VGG |2 7| NC + * OUT |3 6| NC + * VSS |4 5| NC + * +--------+ + * + * Naming conventions follow National Semiconductor datasheet * */ -#include "nld_mm5837.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/solver/nld_matrix_solver.h" +#include "analog/nlid_twoterm.h" +#include "solver/nld_matrix_solver.h" -#define R_LOW (1000.0) -#define R_HIGH (1000.0) +namespace netlist::devices { -namespace netlist -{ - namespace devices + NETLIB_OBJECT(MM5837) { - NETLIB_OBJECT(MM5837_dip) - { - NETLIB_CONSTRUCTOR(MM5837_dip) + NETLIB_CONSTRUCTOR(MM5837) , m_RV(*this, "_RV") - , m_VDD(*this, "1") - , m_VGG(*this, "2") - , m_VSS(*this, "4") - , m_FREQ(*this, "FREQ", 24000) + , m_VDD(*this, "VDD", NETLIB_DELEGATE(inputs)) + , m_VGG(*this, "VGG", NETLIB_DELEGATE(inputs)) + , m_VSS(*this, "VSS", NETLIB_DELEGATE(inputs)) + , m_FREQ(*this, "FREQ", 24000 * 2) + , m_R_LOW(*this, "R_LOW", 1000) + , m_R_HIGH(*this, "R_HIGH", 1000) /* clock */ - , m_feedback(*this, "_FB") + , m_feedback(*this, "_FB", NETLIB_DELEGATE(inputs)) , m_Q(*this, "_Q") - , m_inc(netlist_time::from_hz(24000)) + , m_inc(netlist_time::from_hz(24000 * 2)) , m_shift(*this, "m_shift", 0) - , m_is_timestep(false) { - connect(m_feedback, m_Q); + connect("_FB", "_Q"); + + // output + connect("_RV.2", "VDD"); + register_sub_alias("OUT", "_RV.1"); + } - /* output */ - //register_term("_RV1", m_RV.m_P); - //register_term("_RV2", m_RV.m_N); - connect(m_RV.m_N, m_VDD); + NETLIB_RESETI() + { + //m_V0.initial(0.0); + //m_RV.do_reset(); + m_RV().set_G_V_I(plib::reciprocal(m_R_LOW()), + nlconst::zero(), + nlconst::zero()); + m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); + if (m_FREQ() < nlconst::magic(24000*2) || m_FREQ() > nlconst::magic(56000*2)) + log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); + + m_shift = 0x1ffff; + } - /* device */ - register_subalias("3", m_RV.m_P); + NETLIB_UPDATE_PARAMI() + { + m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ())); + if (m_FREQ() < nlconst::magic(24000*2) || m_FREQ() > nlconst::magic(56000*2)) + log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); } - NETLIB_RESETI(); - NETLIB_UPDATEI(); - NETLIB_UPDATE_PARAMI(); + private: + NETLIB_HANDLERI(inputs) + { + m_Q.push(!m_feedback(), m_inc); + + /* shift register + * + * 17 bits, bits 17 & 14 feed back to input + * + */ + + const auto last_state = m_shift & 0x01; + /* shift */ + m_shift = (m_shift >> 1) | (((m_shift & 0x01) ^ ((m_shift >> 3) & 0x01)) << 16); + const auto state = m_shift & 0x01; + + if (state != last_state) + { + const nl_fptype R = state ? m_R_HIGH : m_R_LOW; + const nl_fptype V = state ? m_VDD() : m_VSS(); + + m_RV().change_state([this, &R, &V]() + { + m_RV().set_G_V_I(plib::reciprocal(R), V, nlconst::zero()); + }); + } + + } - protected: - analog::NETLIB_SUB(twoterm) m_RV; + NETLIB_SUB_NS(analog, two_terminal) m_RV; analog_input_t m_VDD; analog_input_t m_VGG; analog_input_t m_VSS; - param_double_t m_FREQ; + param_fp_t m_FREQ; + param_fp_t m_R_LOW; + param_fp_t m_R_HIGH; /* clock stage */ logic_input_t m_feedback; @@ -60,61 +109,8 @@ namespace netlist /* state */ state_var_u32 m_shift; - - /* cache */ - bool m_is_timestep; }; - NETLIB_RESET(MM5837_dip) - { - //m_V0.initial(0.0); - //m_RV.do_reset(); - m_RV.set_G_V_I(plib::constants<nl_double>::one() / R_LOW, 0.0, 0.0); - m_inc = netlist_time::from_double(1.0 / m_FREQ()); - if (m_FREQ() < 24000 || m_FREQ() > 56000) - log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); - - m_shift = 0x1ffff; - m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices(); - } - - NETLIB_UPDATE_PARAM(MM5837_dip) - { - m_inc = netlist_time::from_double(1.0 / m_FREQ()); - if (m_FREQ() < 24000 || m_FREQ() > 56000) - log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ())); - } - - NETLIB_UPDATE(MM5837_dip) - { - m_Q.push(!m_feedback(), m_inc); - - /* shift register - * - * 17 bits, bits 17 & 14 feed back to input - * - */ - - const auto last_state = m_shift & 0x01; - /* shift */ - m_shift = (m_shift >> 1) | (((m_shift & 0x01) ^ ((m_shift >> 3) & 0x01)) << 16); - const auto state = m_shift & 0x01; - - if (state != last_state) - { - const nl_double R = state ? R_HIGH : R_LOW; - const nl_double V = state ? m_VDD() : m_VSS(); - - // We only need to update the net first if this is a time stepping net - if (m_is_timestep) - m_RV.update(); - m_RV.set_G_V_I(plib::constants<nl_double>::one() / R, V, plib::constants<nl_double>::zero()); - m_RV.solve_later(NLTIME_FROM_NS(1)); - } - - } - - NETLIB_DEVICE_IMPL(MM5837_dip, "MM5837_DIP", "") + NETLIB_DEVICE_IMPL(MM5837, "MM5837", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_mm5837.h b/src/lib/netlist/devices/nld_mm5837.h deleted file mode 100644 index 8f764aa651f..00000000000 --- a/src/lib/netlist/devices/nld_mm5837.h +++ /dev/null @@ -1,27 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_MM5837.h - * - * MM5837: Digital noise source - * - * +--------+ - * VDD |1 ++ 8| NC - * VGG |2 7| NC - * OUT |3 6| NC - * VSS |4 5| NC - * +--------+ - * - * Naming conventions follow National Semiconductor datasheet - * - */ - -#ifndef NLD_MM5837_H_ -#define NLD_MM5837_H_ - -#include "netlist/nl_setup.h" - -#define MM5837_DIP(name) \ - NET_REGISTER_DEV(MM5837_DIP, name) - -#endif /* NLD_MM5837_H_ */ diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp index dc6e3e5696a..a94d868373d 100644 --- a/src/lib/netlist/devices/nld_ne555.cpp +++ b/src/lib/netlist/devices/nld_ne555.cpp @@ -1,61 +1,17 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/*! - * \file nld_NE555.cpp - * - * \page NE555 NE555: PRECISION TIMERS - * - * The Swiss army knife for timing purposes - * - * \section ne555_1 Synopsis - * - * \snippet devsyn.dox.h NE555 synopsis - * \snippet devsyn.dox.h NE555_DIP synopsis - - * \section ne555_11 "C" Synopsis - * - * \snippet devsyn.dox.h NE555 csynopsis - * \snippet devsyn.dox.h NE555_DIP csynopsis - * - * For the \c NE555 use verbose pin assignments like \c name.TRIG or \c name.OUT. - * For the \c NE555_DIP use pin numbers like \c name.1. - * - * \section ne555_2 Connection Diagram - * - * <pre> - * +--------+ - * GND |1 ++ 8| VCC - * TRIG |2 7| DISCH - * OUT |3 6| THRES - * RESET |4 5| CONT - * +--------+ - * </pre> - * - * Naming conventions follow Texas Instruments datasheet - * - * \section ne555_3 Function Table - * - * Please refer to the datasheet. - * - * \section ne555_4 Limitations - * - * Internal resistor network currently fixed to 5k. - * - * \section ne555_5 Example - * \snippet ne555_astable.c ne555 example - */ - -#include "nld_ne555.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/solver/nld_solver.h" + + +#include "analog/nlid_twoterm.h" +#include "solver/nld_solver.h" + +#include "plib/pmath.h" #define R_OFF (1E20) -#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2 +#define R_ON (1) + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(NE555) { NETLIB_CONSTRUCTOR(NE555) @@ -64,35 +20,122 @@ namespace netlist , m_R3(*this, "R3") , m_ROUT(*this, "ROUT") , m_RDIS(*this, "RDIS") - , m_RESET(*this, "RESET") // Pin 4 - , m_THRES(*this, "THRESH") // Pin 6 - , m_TRIG(*this, "TRIG") // Pin 2 + , m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs)) // Pin 4 + , m_THRES(*this, "THRESH", NETLIB_DELEGATE(inputs)) // Pin 6 + , m_TRIG(*this, "TRIG", NETLIB_DELEGATE(inputs)) // Pin 2 , m_OUT(*this, "_OUT") // to Pin 3 via ROUT , m_last_out(*this, "m_last_out", false) , m_ff(*this, "m_ff", false) , m_last_reset(*this, "m_last_reset", false) + , m_overshoot(*this, "m_overshoot", 0.0) + , m_undershoot(*this, "m_undershoot", 0.0) + , m_overshoot_limit(0.0) { - register_subalias("GND", m_R3.m_N); // Pin 1 - register_subalias("CONT", m_R1.m_N); // Pin 5 - register_subalias("DISCH", m_RDIS.m_P); // Pin 7 - register_subalias("VCC", m_R1.m_P); // Pin 8 - register_subalias("OUT", m_ROUT.m_P); // Pin 3 - - connect(m_R1.m_N, m_R2.m_P); - connect(m_R2.m_N, m_R3.m_P); - connect(m_RDIS.m_N, m_R3.m_N); - connect(m_OUT, m_ROUT.m_N); + register_sub_alias("GND", "R3.2"); // Pin 1 + register_sub_alias("CONT", "R1.2"); // Pin 5 + register_sub_alias("DISCH", "RDIS.1"); // Pin 7 + register_sub_alias("VCC", "R1.1"); // Pin 8 + register_sub_alias("OUT", "ROUT.1"); // Pin 3 + + connect("R1.2", "R2.1"); + connect("R2.2", "R3.1"); + connect("RDIS.2", "R3.2"); + connect("_OUT", "ROUT.2"); } - NETLIB_UPDATEI(); - NETLIB_RESETI(); + NETLIB_RESETI() + { + /* FIXME make resistances a parameter, properly model other variants */ + m_R1().set_R(nlconst::magic(5000)); + m_R2().set_R(nlconst::magic(5000)); + m_R3().set_R(nlconst::magic(5000)); + m_ROUT().set_R(nlconst::magic(20)); + m_RDIS().set_R(nlconst::magic(R_OFF)); + + m_last_out = true; + // Check for astable setup, usually TRIG AND THRES connected. Enable + // overshoot compensation in this case. + if (m_TRIG.net() == m_THRES.net()) + m_overshoot_limit = nlconst::magic(0.5); + } private: - analog::NETLIB_SUB(R_base) m_R1; - analog::NETLIB_SUB(R_base) m_R2; - analog::NETLIB_SUB(R_base) m_R3; - analog::NETLIB_SUB(R_base) m_ROUT; - analog::NETLIB_SUB(R_base) m_RDIS; + NETLIB_HANDLERI(inputs) + { + // FIXME: assumes GND is connected to 0V. + + const auto reset = m_RESET(); + + const nl_fptype v_threshold = clamp_hl(m_R2().P()(), nlconst::magic(0.7), nlconst::magic(1.4)); + const nl_fptype v_trigger = clamp_hl(m_R2().N()(), nlconst::magic(0.7), nlconst::magic(1.4)); + + // avoid artificial oscillation due to overshoot compensation when + // the control input is used. + const auto overshoot_limit = std::min(m_overshoot_limit, std::max(0.0, (v_threshold - v_trigger) / 3.0)); + + if (!reset && m_last_reset) + { + m_ff = false; + } + else + { +#if (NL_USE_BACKWARD_EULER) + const bool threshold_exceeded = (m_THRES() + m_overshoot > v_threshold); + const bool trigger_exceeded = (m_TRIG() - m_overshoot > v_trigger); +#else + const bool threshold_exceeded = (m_THRES() + m_overshoot > v_threshold); + const bool trigger_exceeded = (m_TRIG() - m_undershoot > v_trigger); +#endif + if (!trigger_exceeded) + m_ff = true; + else if (threshold_exceeded) + { + m_ff = false; + } + } + + const bool out = (!reset ? false : m_ff); + + if (m_last_out && !out) + { +#if (NL_USE_BACKWARD_EULER) + m_overshoot += ((m_THRES() - v_threshold)) * 2.0; +#else + m_overshoot += ((m_THRES() - v_threshold)); +#endif + m_overshoot = plib::clamp(m_overshoot(), nlconst::zero(), overshoot_limit); + //if (this->name() == "IC6_2") + // printf("%f %s %f %f %f\n", exec().time().as_double(), this->name().c_str(), m_overshoot(), m_R2.P()(), m_THRES()); + m_RDIS().change_state([this]() + { + m_RDIS().set_R(nlconst::magic(R_ON)); + }); + m_OUT.push(m_R3().N()()); + } + else if (!m_last_out && out) + { +#if (NL_USE_BACKWARD_EULER) + m_overshoot += (v_trigger - m_TRIG()) * 2.0; + m_overshoot = plib::clamp(m_overshoot(), nlconst::zero(), overshoot_limit); +#else + m_undershoot += (v_trigger - m_TRIG()); + m_undershoot = plib::clamp(m_undershoot(), nlconst::zero(), overshoot_limit); +#endif + m_RDIS().change_state([this]() + { + m_RDIS().set_R(nlconst::magic(R_OFF)); + }); + // FIXME: Should be delayed by 100ns + m_OUT.push(m_R1().P()()); + } + m_last_reset = reset; + m_last_out = out; + } + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; + NETLIB_SUB_NS(analog, R_base) m_R3; + NETLIB_SUB_NS(analog, R_base) m_ROUT; + NETLIB_SUB_NS(analog, R_base) m_RDIS; logic_input_t m_RESET; analog_input_t m_THRES; @@ -102,98 +145,19 @@ namespace netlist state_var<bool> m_last_out; state_var<bool> m_ff; state_var<bool> m_last_reset; + state_var<nl_fptype> m_overshoot; + state_var<nl_fptype> m_undershoot; + nl_fptype m_overshoot_limit; - nl_double clamp(const nl_double v, const nl_double a, const nl_double b) - { - nl_double ret = v; - nl_double vcc = m_R1.m_P(); - - if (ret > vcc - a) - ret = vcc - a; - if (ret < b) - ret = b; - return ret; - } - }; - - NETLIB_OBJECT_DERIVED(NE555_dip, NE555) - { - NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555) + nl_fptype clamp_hl(const nl_fptype v, const nl_fptype a, const nl_fptype b) noexcept { - register_subalias("1", "GND"); // Pin 1 - register_subalias("2", "TRIG"); // Pin 2 - register_subalias("3", "OUT"); // Pin 3 - register_subalias("4", "RESET"); // Pin 4 - register_subalias("5", "CONT"); // Pin 5 - register_subalias("6", "THRESH"); // Pin 6 - register_subalias("7", "DISCH"); // Pin 7 - register_subalias("8", "VCC"); // Pin 8 + const nl_fptype vcc = m_R1().P()(); + return plib::clamp(v, b, vcc - a); } }; - NETLIB_RESET(NE555) - { - m_R1.reset(); - m_R2.reset(); - m_R3.reset(); - m_ROUT.reset(); - m_RDIS.reset(); - - /* FIXME make resistances a parameter, properly model other variants */ - m_R1.set_R(5000); - m_R2.set_R(5000); - m_R3.set_R(5000); - m_ROUT.set_R(20); - m_RDIS.set_R(R_OFF); - - m_last_out = true; - } - - NETLIB_UPDATE(NE555) - { - // FIXME: assumes GND is connected to 0V. - - const auto reset = m_RESET(); - - if (!reset && m_last_reset) - { - m_ff = false; - } - else - { - const nl_double vt = clamp(m_R2.m_P(), 0.7, 1.4); - const bool bthresh = (m_THRES() > vt); - const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4)); - - if (!btrig) - m_ff = true; - else if (bthresh) - m_ff = false; - } - - const bool out = (!reset ? false : m_ff); - - if (m_last_out && !out) - { - m_RDIS.update(); - m_OUT.push(m_R3.m_N()); - m_RDIS.set_R(R_ON); - } - else if (!m_last_out && out) - { - m_RDIS.update(); - // FIXME: Should be delayed by 100ns - m_OUT.push(m_R1.m_P()); - m_RDIS.set_R(R_OFF); - } - m_last_reset = reset; - m_last_out = out; - } - NETLIB_DEVICE_IMPL(NE555, "NE555", "") - NETLIB_DEVICE_IMPL(NE555_dip, "NE555_DIP", "") NETLIB_DEVICE_IMPL_ALIAS(MC1455P, NE555, "MC1455P", "") - NETLIB_DEVICE_IMPL_ALIAS(MC1455P_dip, NE555_dip, "MC1455P_DIP", "") - } //namespace devices -} // namespace netlist + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_ne555.h b/src/lib/netlist/devices/nld_ne555.h deleted file mode 100644 index fc575d914b7..00000000000 --- a/src/lib/netlist/devices/nld_ne555.h +++ /dev/null @@ -1,21 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud - -#ifndef NLD_NE555_H_ -#define NLD_NE555_H_ - -#include "netlist/nl_setup.h" - -#define NE555(name) \ - NET_REGISTER_DEV(NE555, name) - -#define NE555_DIP(name) \ - NET_REGISTER_DEV(NE555_DIP, name) - -#define MC1455P(name) \ - NET_REGISTER_DEV(MC1455P, name) - -#define MC1455P_DIP(name) \ - NET_REGISTER_DEV(MC1455P_DIP, name) - -#endif /* NLD_NE555_H_ */ diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp index 284b6673f76..efff78d9ca8 100644 --- a/src/lib/netlist/devices/nld_r2r_dac.cpp +++ b/src/lib/netlist/devices/nld_r2r_dac.cpp @@ -1,55 +1,94 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_R2R_dac.c + * nld_r2r_dac.cpp + * + * DMR2R_DAC: R-2R DAC + * + * Generic R-2R DAC ... This is fast. + * 2R + * Bit n >----RRR----+---------> Vout + * | + * R + * R R + * R + * | + * . + * . + * 2R | + * Bit 2 >----RRR----+ + * | + * R + * R R + * R + * | + * 2R | + * Bit 1 >----RRR----+ + * | + * R + * R 2R + * R + * | + * V0 + * + * Using Thevenin's Theorem, this can be written as + * + * +---RRR-----------> Vout + * | + * V + * V V = VAL / 2^n * Vin + * V + * | + * V0 * */ -#include "netlist/nl_base.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/nl_factory.h" +#include "nl_base.h" +#include "nl_factory.h" + +#include "analog/nlid_twoterm.h" -namespace netlist +namespace netlist::analog { - namespace analog - { - NETLIB_OBJECT_DERIVED(r2r_dac, twoterm) + + class nld_r2r_dac : public nld_two_terminal { - NETLIB_CONSTRUCTOR_DERIVED(r2r_dac, twoterm) - , m_VIN(*this, "VIN", 1.0) - , m_R(*this, "R", 1.0) + public: + nld_r2r_dac(constructor_param_t data) + : nld_two_terminal(data) + , m_VIN(*this, "VIN", nlconst::one()) + , m_R(*this, "R", nlconst::one()) , m_num(*this, "N", 1) , m_val(*this, "VAL", 1) { - register_subalias("VOUT", m_P); - register_subalias("VGND", m_N); + register_sub_alias("VOUT", P()); + register_sub_alias("VGND", N()); } NETLIB_UPDATE_PARAMI(); - //NETLIB_RESETI(); - //NETLIB_UPDATEI(); + // NETLIB_RESETI(); protected: - param_double_t m_VIN; - param_double_t m_R; + param_fp_t m_VIN; + param_fp_t m_R; param_int_t m_num; param_int_t m_val; }; - NETLIB_UPDATE_PARAM(r2r_dac) { - solve_now(); + nl_fptype V = m_VIN() / static_cast<nl_fptype>(1 << m_num()) + * static_cast<nl_fptype>(m_val()); + change_state( + [this, &V]() + { this->set_G_V_I(plib::reciprocal(m_R()), V, nlconst::zero()); }); + } - double V = m_VIN() / static_cast<double>(1 << m_num()) - * static_cast<double>(m_val()); +} // namespace netlist::analog - this->set_G_V_I(1.0 / m_R(), V, 0.0); - } - } //namespace analog +namespace netlist::devices +{ - namespace devices { - NETLIB_DEVICE_IMPL_NS(analog, r2r_dac, "R2R_DAC", "VIN,R,N") - } // namespace devices + NETLIB_DEVICE_IMPL_NS(analog, r2r_dac, "R2R_DAC", "VIN,R,N") -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_r2r_dac.h b/src/lib/netlist/devices/nld_r2r_dac.h deleted file mode 100644 index 8a4257a3cbf..00000000000 --- a/src/lib/netlist/devices/nld_r2r_dac.h +++ /dev/null @@ -1,57 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_R2R_DAC.h - * - * DMR2R_DAC: R-2R DAC - * - * Generic R-2R DAC ... This is fast. - * 2R - * Bit n >----RRR----+---------> Vout - * | - * R - * R R - * R - * | - * . - * . - * 2R | - * Bit 2 >----RRR----+ - * | - * R - * R R - * R - * | - * 2R | - * Bit 1 >----RRR----+ - * | - * R - * R 2R - * R - * | - * V0 - * - * Using Thevenin's Theorem, this can be written as - * - * +---RRR-----------> Vout - * | - * V - * V V = VAL / 2^n * Vin - * V - * | - * V0 - * - */ - -#ifndef NLD_R2R_DAC_H_ -#define NLD_R2R_DAC_H_ - -#include "netlist/nl_setup.h" - -#define R2R_DAC(name, p_VIN, p_R, p_N) \ - NET_REGISTER_DEV(R2R_DAC, name) \ - NETDEV_PARAMI(name, VIN, p_VIN) \ - NETDEV_PARAMI(name, R, p_R) \ - NETDEV_PARAMI(name, N, p_N) - -#endif /* NLD_R2R_DAC_H_ */ diff --git a/src/lib/netlist/devices/nld_roms.cpp b/src/lib/netlist/devices/nld_roms.cpp new file mode 100644 index 00000000000..a9d52850dba --- /dev/null +++ b/src/lib/netlist/devices/nld_roms.cpp @@ -0,0 +1,311 @@ +// license:BSD-3-Clause +// copyright-holders:Couriersud +/* + * nld_roms.cpp + * + */ + +#include "nl_base.h" +#include "nl_factory.h" + +template <typename N, typename T> +constexpr bool TOR(N n, T &a) +{ + return (n == 0) ? false : (TOR(n - 1, a) || a[n - 1]()); +} + +template <typename T> +constexpr bool TOR(T &a) +{ + return TOR(a.size(), a); +} + +namespace netlist::devices { + + NETLIB_OBJECT(mk28000_prom) + { + NETLIB_CONSTRUCTOR(mk28000_prom) + , m_TE(*this, "FORCE_TRISTATE_LOGIC", 0) + , m_enable_lo(*this, "m_enable_lo", false) + , m_enable_hi(*this, "m_enable_hi", false) + , m_latched_rom(*this, "m_latched_rom", 0) + , m_A(*this, 1, "A{}", NETLIB_DELEGATE(addr)) + , m_ARQ(*this, "ARQ", NETLIB_DELEGATE(addr)) + , m_OE1(*this, "OE1", NETLIB_DELEGATE(oe1)) + , m_OE2(*this, "OE2", NETLIB_DELEGATE(oe2)) + , m_O(*this, 1, "O{}", m_TE()) + , m_ROM(*this, "ROM") + , m_power_pins(*this) + { + } + + private: + NETLIB_HANDLERI(oe1) + { + m_enable_lo = m_OE1(); + uint8_t o = m_enable_lo ? m_latched_rom : 0; + for (std::size_t i=0; i<4; i++) + { + m_O.set_tristate(!m_enable_lo, NLTIME_FROM_NS(600), NLTIME_FROM_NS(600)); + m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(600)); + } + } + + NETLIB_HANDLERI(oe2) + { + m_enable_hi = m_OE2(); + uint8_t o = m_enable_hi ? m_latched_rom : 0; + for (std::size_t i=4; i<8; i++) + { + m_O.set_tristate(!m_enable_hi, NLTIME_FROM_NS(600), NLTIME_FROM_NS(600)); + m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(600)); + } + } + + NETLIB_HANDLERI(addr) + { + if (!m_ARQ()) + { + const auto addr = m_A(); + m_latched_rom = m_ROM[addr]; + } + uint8_t o = (m_enable_hi || m_enable_lo) ? m_latched_rom : 0; + for (std::size_t i=0; i<4; i++) + { + m_O.set_tristate(!m_enable_lo, NLTIME_FROM_NS(600), NLTIME_FROM_NS(600)); + m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(600)); + } + for (std::size_t i=4; i<8; i++) + { + m_O.set_tristate(!m_enable_hi, NLTIME_FROM_NS(600), NLTIME_FROM_NS(600)); + m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(600)); + } + } + + param_logic_t m_TE; + state_var<bool> m_enable_lo; + state_var<bool> m_enable_hi; + state_var<uint8_t> m_latched_rom; + object_array_t<logic_input_t, 11> m_A; + logic_input_t m_ARQ; + logic_input_t m_OE1; + logic_input_t m_OE2; + object_array_t<tristate_output_t, 8> m_O; + + param_rom_t<uint8_t, 11, 8> m_ROM; + nld_power_pins m_power_pins; + }; + + NETLIB_OBJECT(mcm14524_rom) + { + NETLIB_CONSTRUCTOR_MODEL(mcm14524_rom, "CD4XXX") + , m_enabled(*this, "m_enabled", true) + , m_latched_rom(*this, "m_latched_rom", 0) + , m_A(*this, 1, "A{}", NETLIB_DELEGATE(addr)) + , m_CLK(*this, "CLK", NETLIB_DELEGATE(addr)) + , m_clk_old(*this, "m_clk_old", true) + , m_EN(*this, "EN", NETLIB_DELEGATE(en)) + , m_B(*this, 1, "B{}", 0) + , m_ROM(*this, "ROM") + , m_taccc(*this, "m_taccc", netlist_time::from_nsec(1350)) + , m_taccen(*this, "m_taccen", netlist_time::from_nsec(245)) + , m_power_pins(*this, NETLIB_DELEGATE(vdd_vss)) + { + } + + private: + NETLIB_HANDLERI(en) + { + m_enabled = m_EN(); + uint8_t o = m_enabled ? m_latched_rom : 0; // outputs are forced to 0 by enable going low; this chip does not have tri-state outputs! + for (std::size_t i=0; i<4; i++) + { + m_B[i].push((o >> i) & 1, m_taccen); + } + } + + NETLIB_HANDLERI(addr) + { + if (!m_CLK() && m_clk_old) // latch on falling edge + { + const auto addr = m_A(); + m_latched_rom = m_ROM[addr]; + } + m_clk_old = m_CLK(); + uint8_t o = m_enabled ? m_latched_rom : 0; // outputs are forced to 0 by enable going low; this chip does not have tri-state outputs! + for (std::size_t i=0; i<4; i++) + { + m_B[i].push((o >> i) & 1, m_taccc); + } + } + + NETLIB_HANDLERI(vdd_vss) + { + auto d = m_power_pins.VCC()() - m_power_pins.GND()(); + if (d > 0.1) // avoid unrealistic values + { + m_taccc = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(7615.5 / d - 181)); + m_taccen = netlist_time::from_nsec(gsl::narrow_cast<unsigned>(1292.5 / d - 14.6)); + } + } + + state_var<bool> m_enabled; + state_var<uint8_t> m_latched_rom; + object_array_t<logic_input_t, 8> m_A; + logic_input_t m_CLK; + state_var<bool> m_clk_old; + logic_input_t m_EN; + object_array_t<tristate_output_t, 4> m_B; + param_rom_t<uint8_t, 8, 4> m_ROM; + state_var<netlist_time> m_taccc; // propagation time for data vs CLK + state_var<netlist_time> m_taccen; // propagation time for data vs /EN + nld_power_pins m_power_pins; + }; + + template <typename D> + NETLIB_OBJECT(generic_prom) + { + NETLIB_CONSTRUCTOR(generic_prom) + , m_enabled(*this, "m_enabled", true) + , m_TE(*this, "FORCE_TRISTATE_LOGIC", 0) + , m_A(*this, 0, "A{}", NETLIB_DELEGATE(addr)) + , m_CEQ(*this, 1, + D::chip_enable_mask::value ^ static_cast<size_t>(0xffff), pstring("CE{}"), + // Causes a expected primary expression before { with gcc9 + //std::array<nl_delegate, 3>{NETLIB_DELEGATE(ce<0>), + // NETLIB_DELEGATE(ce<1>), + // NETLIB_DELEGATE(ce<2>)}) + std::array<nl_delegate, 3>{nl_delegate(& NETLIB_NAME(generic_prom) :: ce<0>, this), + nl_delegate(& NETLIB_NAME(generic_prom) :: ce<1>, this), + nl_delegate(& NETLIB_NAME(generic_prom) :: ce<2>, this)}) + , m_O(*this, D::data_name_offset::value, "O{}", m_TE()) + , m_ROM(*this, "ROM") + , m_power_pins(*this) + { + } + + using data_type = typename plib::least_type_for_bits<D::data_width::value>::type; + + private: + + template <std::size_t N> + NETLIB_HANDLERI(ce) + { + using cet = typename D::chip_enable_time; + m_enabled = (m_CEQ() == D::chip_enable_mask::value); + switch (D::output_id::value) + { + case 0: // logic + { + m_O.push(m_ROM[m_A()], D::access_time::value()); + } + break; + case 1: // tristate + { + m_O.set_tristate(!m_enabled, cet::value(N), cet::value(N)); + m_O.push(m_ROM[m_A()], D::access_time::value()); + } + break; + default: // 2, open collector + { + const auto delay = m_enabled ? D::access_time::value() : cet::value(N); + const data_type o = m_enabled ? m_ROM[m_A()] : + (1 << D::data_width::value) - 1; + m_O.push(o, delay); + } + break; + } + + } + + NETLIB_HANDLERI(addr) + { + if (m_enabled) + { + m_O.push(m_ROM[m_A()], D::access_time::value()); + } + } + + state_var<bool> m_enabled; + param_logic_t m_TE; + object_array_t<logic_input_t, D::address_width::value> m_A; + object_array_t<logic_input_t, D::chip_enable_inputs::value> m_CEQ; + object_array_t<typename D::output_type, D::data_width::value> m_O; + + param_rom_t<uint8_t, D::address_width::value, D::data_width::value> m_ROM; + nld_power_pins m_power_pins; + }; + + struct desc_82S126 : public desc_base + { + using address_width = desc_const<8>; + using data_width = desc_const<4>; + using data_name_offset = desc_const<1>; // O1, O2, .. + using chip_enable_inputs = desc_const<2>; + // MATCH_MASK : all 0 ==> all bits inverted + using chip_enable_mask = desc_const<0x00>; + + using chip_enable_time = times_ns2<25, 25>; + using access_time = time_ns<40>; + + using output_type = tristate_output_t; + using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector + }; + + struct desc_74S287 : public desc_82S126 + { + using data_name_offset = desc_const<0>; // O0, O1, ... according to National Semiconductor datasheet + using chip_enable_time = times_ns2<15, 15>; + using access_time = time_ns<35>; + }; + + struct desc_82S123 : public desc_base + { + // FIXME: tristate outputs, add 82S23 (open collector) + using address_width = desc_const<5>; + using data_width = desc_const<8>; + using data_name_offset = desc_const<0>; // O0, O1, .. + using chip_enable_inputs = desc_const<1>; + // MATCH_MASK : all 0 ==> all bits inverted + using chip_enable_mask = desc_const<0x00>; + + using chip_enable_time = times_ns1<35>; + using access_time = time_ns<45>; + + using output_type = tristate_output_t; + using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector + }; + + struct desc_2716 : public desc_base + { + // FIXME: tristate outputs + using address_width = desc_const<11>; + using data_width = desc_const<8>; + using data_name_offset = desc_const<0>; // O0, O1, .. + + using chip_enable_inputs = desc_const<2>; + // MATCH_MASK : all 0 ==> all bits inverted + using chip_enable_mask = desc_const<0x00>; + + using chip_enable_time = times_ns2<450, 100>; //CE, OE + using access_time = time_ns<450>; + + using output_type = tristate_output_t; + using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector + }; + + using NETLIB_NAME(82S123) = NETLIB_NAME(generic_prom)<desc_82S123>; // 256 bits, 32x8, used as 256x4 + using NETLIB_NAME(82S126) = NETLIB_NAME(generic_prom)<desc_82S126>; // 1024 bits, 32x32, used as 256x4 + using NETLIB_NAME(74S287) = NETLIB_NAME(generic_prom)<desc_74S287>; // 1024 bits, 32x32, used as 256x4 + using NETLIB_NAME(2716) = NETLIB_NAME(generic_prom)<desc_2716>; // CE2Q = OE, CE1Q = CE + using NETLIB_NAME(MK28000) = NETLIB_NAME(mk28000_prom); // 16384 bits, either 2048x8 or 4096x4, determined by OE1/OE2 use + using NETLIB_NAME(MCM14524) = NETLIB_NAME(mcm14524_rom); // 1024 bits, 256x4, latched address + + NETLIB_DEVICE_IMPL(82S126, "PROM_82S126", "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,@VCC,@GND") + NETLIB_DEVICE_IMPL(74S287, "PROM_74S287", "+CE1Q,+CE2Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,@VCC,@GND") + NETLIB_DEVICE_IMPL(82S123, "PROM_82S123", "+CEQ,+A0,+A1,+A2,+A3,+A4,@VCC,@GND") + NETLIB_DEVICE_IMPL(2716, "EPROM_2716", "+CE2Q,+CE1Q,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10,@VCC,@GND") + NETLIB_DEVICE_IMPL(MK28000, "PROM_MK28000", "+OE1,+OE2,+ARQ,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10,+A11,@VCC,@GND") + NETLIB_DEVICE_IMPL(MCM14524, "ROM_MCM14524", "+EN,+CLK,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,@VCC,@GND") + +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_schmitt.cpp b/src/lib/netlist/devices/nld_schmitt.cpp index f219d215520..a6134f3a953 100644 --- a/src/lib/netlist/devices/nld_schmitt.cpp +++ b/src/lib/netlist/devices/nld_schmitt.cpp @@ -5,127 +5,118 @@ * */ -#include "nld_schmitt.h" +#include "analog/nlid_twoterm.h" +#include "nl_base.h" +#include "nl_errstr.h" +#include "solver/nld_solver.h" -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/nl_base.h" -#include "netlist/nl_errstr.h" -#include "netlist/solver/nld_solver.h" +namespace netlist::devices { -#include <cmath> + /* + * Over-simplified TTL Schmitt trigger model + * It's good enough to work for 74xx/74LSxx if it isn't abused too badly + * It would need major changes to support 4000 or 74HCxx behaviour + * The input is over-simplified - it's actually more like a resistor in series with a diode, and can only source current + * Similarly, high output can only source current and low output can only sink current + * Propagation delays are ignored + * + */ - -namespace netlist -{ - namespace devices + class schmitt_trigger_model_t { - - /* - * Over-simplified TTL Schmitt trigger model - * It's good enough to work for 74xx/74LSxx if it isn't abused too badly - * It would need major changes to support 4000 or 74HCxx behaviour - * The input is over-simplified - it's actually more like a resistor in series with a diode, and can only source current - * Similarly, high output can only source current and low output can only sink current - * Propagation delays are ignored - * - */ - - class schmitt_trigger_model_t : public param_model_t + public: + schmitt_trigger_model_t(param_model_t &model) + : m_VTP(model, "VTP") + , m_VTM(model, "VTM") + , m_VI(model, "VI") + , m_RI(model, "RI") + , m_VOH(model, "VOH") + , m_ROH(model, "ROH") + , m_VOL(model, "VOL") + , m_ROL(model, "ROL") + , m_TPLH(model, "TPLH") + , m_TPHL(model, "TPHL") { - public: - schmitt_trigger_model_t(device_t &device, const pstring &name, const pstring &val) - : param_model_t(device, name, val) - , m_VTP(*this, "VTP") - , m_VTM(*this, "VTM") - , m_VI(*this, "VI") - , m_RI(*this, "RI") - , m_VOH(*this, "VOH") - , m_ROH(*this, "ROH") - , m_VOL(*this, "VOL") - , m_ROL(*this, "ROL") - , m_TPLH(*this, "TPLH") - , m_TPHL(*this, "TPHL") - { - } + } - value_t m_VTP; - value_t m_VTM; - value_t m_VI; - value_t m_RI; - value_t m_VOH; - value_t m_ROH; - value_t m_VOL; - value_t m_ROL; - value_t m_TPLH; - value_t m_TPHL; - }; + param_model_t::value_t m_VTP; + param_model_t::value_t m_VTM; + param_model_t::value_t m_VI; + param_model_t::value_t m_RI; + param_model_t::value_t m_VOH; + param_model_t::value_t m_ROH; + param_model_t::value_t m_VOL; + param_model_t::value_t m_ROL; + param_model_t::value_t m_TPLH; + param_model_t::value_t m_TPHL; + }; - NETLIB_OBJECT(schmitt_trigger) + NETLIB_OBJECT(schmitt_trigger) + { + NETLIB_CONSTRUCTOR(schmitt_trigger) + , m_A(*this, "A", NETLIB_DELEGATE(input)) + , m_supply(*this) + , m_RVI(*this, "RVI") + , m_RVO(*this, "RVO") + , m_stmodel(*this, "STMODEL", "TTL_7414_GATE") + , m_modacc(m_stmodel) + , m_last_state(*this, "m_last_var", 1) { - NETLIB_CONSTRUCTOR(schmitt_trigger) - , m_A(*this, "A") - , m_GND(*this, "GND") - , m_RVI(*this, "RVI") - , m_RVO(*this, "RVO") - , m_model(*this, "MODEL", "TTL_7414_GATE") - , m_last_state(*this, "m_last_var", 1) - , m_is_timestep(false) - { - register_subalias("Q", m_RVO.m_P); + register_sub_alias("Q", "RVO.1"); - connect(m_A, m_RVI.m_P); - connect(m_GND, m_RVI.m_N); - connect(m_GND, m_RVO.m_N); - } + connect("A", "RVI.1"); + // FIXME: need a symbolic reference from connect as well + connect(m_supply.GND(), m_RVI().N()); + connect(m_supply.GND(), m_RVO().N()); + } - protected: - NETLIB_RESETI() - { - m_last_state = 1; - m_RVI.reset(); - m_RVO.reset(); - m_is_timestep = m_RVO.m_P.net().solver()->has_timestep_devices(); - m_RVI.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_RI, m_model.m_VI, 0.0); - m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROL, m_model.m_VOL, 0.0); - } + protected: + NETLIB_RESETI() + { + m_last_state = 1; + m_RVI().reset(); + m_RVO().reset(); + m_RVI().set_G_V_I(plib::reciprocal(m_modacc.m_RI()), m_modacc.m_VI, nlconst::zero()); + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); + } - NETLIB_UPDATEI() + private: + NETLIB_HANDLERI(input) + { + const auto va(m_A.Q_Analog() - m_supply.GND().Q_Analog()); + if (m_last_state) { - if (m_last_state) + if (va < m_modacc.m_VTM) { - if (m_A.Q_Analog() < m_model.m_VTM) + m_last_state = 0; + m_RVO().change_state([this]() { - m_last_state = 0; - if (m_is_timestep) - m_RVO.update(); - m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROH, m_model.m_VOH, 0.0); - m_RVO.solve_later(); - } + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROH()), m_modacc.m_VOH, nlconst::zero()); + }); } - else + } + else + { + if (va > m_modacc.m_VTP) { - if (m_A.Q_Analog() > m_model.m_VTP) + m_last_state = 1; + m_RVO().change_state([this]() { - m_last_state = 1; - if (m_is_timestep) - m_RVO.update(); - m_RVO.set_G_V_I(plib::constants<nl_double>::one() / m_model.m_ROL, m_model.m_VOL, 0.0); - m_RVO.solve_later(); - } + m_RVO().set_G_V_I(plib::reciprocal(m_modacc.m_ROL()), m_modacc.m_VOL, nlconst::zero()); + }); } } + } - private: - analog_input_t m_A; - analog_input_t m_GND; - analog::NETLIB_SUB(twoterm) m_RVI; - analog::NETLIB_SUB(twoterm) m_RVO; - schmitt_trigger_model_t m_model; - state_var<int> m_last_state; - bool m_is_timestep; - }; + analog_input_t m_A; + NETLIB_NAME(power_pins) m_supply; + NETLIB_SUB_NS(analog, two_terminal) m_RVI; + NETLIB_SUB_NS(analog, two_terminal) m_RVO; + param_model_t m_stmodel; + schmitt_trigger_model_t m_modacc; + state_var<int> m_last_state; + }; - NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "MODEL") + NETLIB_DEVICE_IMPL(schmitt_trigger, "SCHMITT_TRIGGER", "STMODEL") - } // namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_schmitt.h b/src/lib/netlist/devices/nld_schmitt.h deleted file mode 100644 index 20666b29cf7..00000000000 --- a/src/lib/netlist/devices/nld_schmitt.h +++ /dev/null @@ -1,25 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/* - * nld_schmitt.h - * - */ - -//#pragma once - -#ifndef NLD_SCHMITT_H_ -#define NLD_SCHMITT_H_ - - -#include "netlist/nl_setup.h" - -// ---------------------------------------------------------------------------------------- -// Macros -// ---------------------------------------------------------------------------------------- - -#define SCHMITT_TRIGGER(name, model) \ - NET_REGISTER_DEV(SCHMITT_TRIGGER, name) \ - NETDEV_PARAMI(name, MODEL, model) - - -#endif /* NLD_SCHMITT_H_ */ diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp index 5a1868bb775..e2580a296c6 100644 --- a/src/lib/netlist/devices/nld_system.cpp +++ b/src/lib/netlist/devices/nld_system.cpp @@ -1,123 +1,197 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud /* - * nld_system.c + * nld_system.cpp * */ -#include "netlist/solver/nld_solver.h" -#include "netlist/solver/nld_matrix_solver.h" +#include "solver/nld_solver.h" #include "nlid_system.h" +#include "solver/nld_matrix_solver.h" -namespace netlist -{ - namespace devices - { - // ---------------------------------------------------------------------------------------- - // netlistparams - // ---------------------------------------------------------------------------------------- +#include "plib/pstrutil.h" +namespace netlist::devices { - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // extclock - // ---------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - NETLIB_RESET(extclock) + NETLIB_OBJECT(extclock) { - m_cnt = 0; - m_off = netlist_time::from_double(m_offset()); - m_feedback.m_delegate = NETLIB_DELEGATE(extclock, update); + NETLIB_CONSTRUCTOR(extclock) + , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0)) + , m_pattern(*this, "PATTERN", "1,1") + , m_offset(*this, "OFFSET", nlconst::zero()) + , m_feedback(*this, "FB", NETLIB_DELEGATE(first)) + , m_Q(*this, "Q") + , m_cnt(*this, "m_cnt", 0) + , m_off(*this, "m_off", netlist_time::zero()) + { + m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + + connect("FB", "Q"); + + netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + std::vector<pstring> pat(plib::psplit(m_pattern(),',')); + m_off = netlist_time::from_fp(m_offset()); + + std::array<std::int64_t, 32> pati = { 0 }; + + m_size = static_cast<std::uint8_t>(pat.size()); + netlist_time::mult_type total = 0; + for (unsigned i=0; i<m_size; i++) + { + pati[i] = plib::pstonum<std::int64_t>(pat[i]); + total += pati[i]; + } + netlist_time ttotal = netlist_time::zero(); + auto sm1 = static_cast<uint8_t>(m_size - 1); + for (unsigned i=0; i < sm1; i++) + { + m_inc[i] = base * pati[i]; + ttotal += m_inc[i]; + } + m_inc[sm1] = base * total - ttotal; - //m_feedback.m_delegate .set(&NETLIB_NAME(extclock)::update, this); - //m_Q.initial(0); - } + } - NETLIB_HANDLER(extclock, clk2) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); - if (++m_cnt >= m_size) + NETLIB_RESETI() + { m_cnt = 0; - } + m_off = netlist_time::from_fp<param_fp_t::value_type>(m_offset()); + m_feedback.set_delegate(NETLIB_DELEGATE(first)); + } + //NETLIB_UPDATE_PARAMI(); - NETLIB_HANDLER(extclock, clk2_pow2) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); - m_cnt = (++m_cnt) & (m_size-1); - } + private: - NETLIB_UPDATE(extclock) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off); - m_off = netlist_time::zero(); - if (++m_cnt >= m_size) - m_cnt = 0; + NETLIB_HANDLERI(clk2) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); + if (++m_cnt >= m_size) + m_cnt = 0; + } - // continue with optimized clock handlers .... + NETLIB_HANDLERI(clk2_pow2) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); + m_cnt = (++m_cnt) & (m_size-1); + } - if ((m_size & (m_size-1)) == 0) // power of 2? - m_feedback.m_delegate.set(&NETLIB_NAME(extclock)::clk2_pow2, this); - else - m_feedback.m_delegate.set(&NETLIB_NAME(extclock)::clk2, this); - } + NETLIB_HANDLERI(first) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off()); + m_off = netlist_time::zero(); + if (++m_cnt >= m_size) + m_cnt = 0; - // ----------------------------------------------------------------------------- - // nld_res_sw - // ----------------------------------------------------------------------------- + // continue with optimized clock handlers .... - NETLIB_RESET(res_sw) - { - m_last_state = 0; - m_R.set_R(m_ROFF()); - } + if ((m_size & (m_size-1)) == 0) // power of 2? + m_feedback.set_delegate(nl_delegate(&NETLIB_NAME(extclock)::clk2_pow2, this)); + else + m_feedback.set_delegate(nl_delegate(&NETLIB_NAME(extclock)::clk2, this)); + } + + + param_fp_t m_freq; + param_str_t m_pattern; + param_fp_t m_offset; + + logic_input_t m_feedback; + logic_output_t m_Q; + state_var_u8 m_cnt; + std::uint8_t m_size; + state_var<netlist_time> m_off; + std::array<netlist_time, 32> m_inc; + }; - NETLIB_UPDATE(res_sw) + // ------------------------------------------------------------------------- + // sys_pulse + // ------------------------------------------------------------------------- + + NETLIB_OBJECT(sys_pulse) { - const netlist_sig_t state = m_I(); - if (state != m_last_state) + NETLIB_CONSTRUCTOR(sys_pulse) + , m_I(*this, "I", NETLIB_DELEGATE(input)) + , m_FB(*this, "FB", NETLIB_DELEGATE(feedback)) + , m_Q(*this, "Q") + , m_delay(*this, "DELAY", 10) + , m_duration(*this, "DURATION", 100) + , m_invert_input(*this, "INVERT_INPUT", 1) + , m_invert_output(*this, "INVERT_OUTPUT", 1) + , m_last(*this, "m_last", 0) { - m_last_state = state; - const nl_double R = state ? m_RON() : m_ROFF(); - - // FIXME: We only need to update the net first if this is a time stepping net - m_R.update(); - m_R.set_R(R); - m_R.solve_later(); + connect(m_Q, m_FB); } - } - /* ----------------------------------------------------------------------------- - * nld_function - * ----------------------------------------------------------------------------- */ + //NETLIB_UPDATE_PARAMI(); + NETLIB_RESETI() + { + //m_Q.initial(0); + } - NETLIB_RESET(function) - { - //m_Q.initial(0.0); - } + private: + NETLIB_HANDLERI(input) + { + netlist_sig_t nval = m_I() ^ m_invert_input; + if (nval && !m_last) + { + // L_to_H + m_Q.push(1 ^ m_invert_output, NLTIME_FROM_NS(static_cast<unsigned>(m_delay()))); + } + m_last = nval; + } - NETLIB_UPDATE(function) - { - for (std::size_t i=0; i < static_cast<unsigned>(m_N()); i++) + NETLIB_HANDLERI(feedback) { - m_vals[i] = (*m_I[i])(); + if (m_FB() == (1 ^ m_invert_output)) + m_Q.push(0 ^ m_invert_output, NLTIME_FROM_NS(static_cast<unsigned>(m_duration()))); } - m_Q.push(m_compiled.evaluate(m_vals)); - } + logic_input_t m_I; + logic_input_t m_FB; + logic_output_t m_Q; + + param_int_t m_delay; + param_int_t m_duration; + param_logic_t m_invert_input; + param_logic_t m_invert_output; - NETLIB_DEVICE_IMPL(dummy_input, "DUMMY_INPUT", "") - NETLIB_DEVICE_IMPL(frontier, "FRONTIER_DEV", "+I,+G,+Q") - NETLIB_DEVICE_IMPL(function, "AFUNC", "N,FUNC") + state_var<netlist_sig_t> m_last; + }; + + + NETLIB_DEVICE_IMPL(netlistparams, "PARAMETER", "") + NETLIB_DEVICE_IMPL(nc_pin, "NC_PIN", "") + + NETLIB_DEVICE_IMPL(frontier, "FRONTIER_DEV", "+I,+G,+Q") + NETLIB_DEVICE_IMPL(function, "AFUNC", "N,FUNC") NETLIB_DEVICE_IMPL(analog_input, "ANALOG_INPUT", "IN") NETLIB_DEVICE_IMPL(clock, "CLOCK", "FREQ") - NETLIB_DEVICE_IMPL(varclock, "VARCLOCK", "FUNC") + NETLIB_DEVICE_IMPL(varclock, "VARCLOCK", "N,FUNC") NETLIB_DEVICE_IMPL(extclock, "EXTCLOCK", "FREQ,PATTERN") - NETLIB_DEVICE_IMPL(res_sw, "RES_SWITCH", "+IN,+P1,+P2") + NETLIB_DEVICE_IMPL(sys_dsw1, "SYS_DSW", "+I,+1,+2") + NETLIB_DEVICE_IMPL(sys_dsw2, "SYS_DSW2", "") + NETLIB_DEVICE_IMPL(sys_compd, "SYS_COMPD", "") + NETLIB_DEVICE_IMPL(sys_pulse, "SYS_PULSE", "DELAY,DURATION,INVERT_INPUT,INVERT_OUTPUT") + + using NETLIB_NAME(sys_noise_mt_u) = + NETLIB_NAME(sys_noise)<plib::mt19937_64, plib::uniform_distribution_t>; + NETLIB_DEVICE_IMPL(sys_noise_mt_u, "SYS_NOISE_MT_U", "SIGMA") + + using NETLIB_NAME(sys_noise_mt_n) = + NETLIB_NAME(sys_noise)<plib::mt19937_64, plib::normal_distribution_t>; + NETLIB_DEVICE_IMPL(sys_noise_mt_n, "SYS_NOISE_MT_N", "SIGMA") + NETLIB_DEVICE_IMPL(mainclock, "MAINCLOCK", "FREQ") - NETLIB_DEVICE_IMPL(gnd, "GND", "") - NETLIB_DEVICE_IMPL(netlistparams, "PARAMETER", "") + NETLIB_DEVICE_IMPL(gnd, "GNDA", "") + + using NETLIB_NAME(logic_input8) = NETLIB_NAME(logic_inputN)<8>; + NETLIB_DEVICE_IMPL(logic_input8, "LOGIC_INPUT8", "IN,MODEL") - NETLIB_DEVICE_IMPL(logic_input, "LOGIC_INPUT", "IN,FAMILY") + NETLIB_DEVICE_IMPL(logic_input, "LOGIC_INPUT", "IN,MODEL") NETLIB_DEVICE_IMPL_ALIAS(logic_input_ttl, logic_input, "TTL_INPUT", "IN") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_system.h b/src/lib/netlist/devices/nld_system.h deleted file mode 100644 index e2b70455411..00000000000 --- a/src/lib/netlist/devices/nld_system.h +++ /dev/null @@ -1,77 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_system.h - * - * netlist devices defined in the core - */ - -#ifndef NLD_SYSTEM_H_ -#define NLD_SYSTEM_H_ - -#include "netlist/nl_setup.h" - -// ----------------------------------------------------------------------------- -// Macros -// ----------------------------------------------------------------------------- - -#define TTL_INPUT(name, v) \ - NET_REGISTER_DEV(TTL_INPUT, name) \ - PARAM(name.IN, v) - -#define LOGIC_INPUT(name, v, family) \ - NET_REGISTER_DEV(LOGIC_INPUT, name) \ - PARAM(name.IN, v) \ - PARAM(name.FAMILY, family) - -#define ANALOG_INPUT(name, v) \ - NET_REGISTER_DEV(ANALOG_INPUT, name) \ - PARAM(name.IN, v) - -#define MAINCLOCK(name, freq) \ - NET_REGISTER_DEV(MAINCLOCK, name) \ - PARAM(name.FREQ, freq) - -#define CLOCK(name, freq) \ - NET_REGISTER_DEV(CLOCK, name) \ - PARAM(name.FREQ, freq) - -#define VARCLOCK(name, func) \ - NET_REGISTER_DEV(VARCLOCK, name) \ - PARAM(name.FUNC, func) - -#define EXTCLOCK(name, freq, pattern) \ - NET_REGISTER_DEV(EXTCLOCK, name) \ - PARAM(name.FREQ, freq) \ - PARAM(name.PATTERN, pattern) - -#define GNDA() \ - NET_REGISTER_DEV(GNDA, GND) - -#define DUMMY_INPUT(name) \ - NET_REGISTER_DEV(DUMMY_INPUT, name) - -//FIXME: Usage discouraged, use OPTIMIZE_FRONTIER instead -#define FRONTIER_DEV(name, cIN, cG, cOUT) \ - NET_REGISTER_DEV(FRONTIER_DEV, name) \ - NET_C(cIN, name.I) \ - NET_C(cG, name.G) \ - NET_C(cOUT, name.Q) - -#define RES_SWITCH(name, cIN, cP1, cP2) \ - NET_REGISTER_DEV(RES_SWITCH, name) \ - NET_C(cIN, name.I) \ - NET_C(cP1, name.1) \ - NET_C(cP2, name.2) - -/* Default device to hold netlist parameters */ -#define PARAMETERS(name) \ - NET_REGISTER_DEV(PARAMETERS, name) - -#define AFUNC(name, p_N, p_F) \ - NET_REGISTER_DEV(AFUNC, name) \ - PARAM(name.N, p_N) \ - PARAM(name.FUNC, p_F) - - -#endif /* NLD_SYSTEM_H_ */ diff --git a/src/lib/netlist/devices/nld_tms4800.cpp b/src/lib/netlist/devices/nld_tms4800.cpp index 24729b10e72..55b14921b2d 100644 --- a/src/lib/netlist/devices/nld_tms4800.cpp +++ b/src/lib/netlist/devices/nld_tms4800.cpp @@ -3,31 +3,74 @@ /* * nld_tms4800.cpp * + * TMS-4800: 16 Kbit (2Kb x 8) READ ONLY MEMORY + * + * +----------------+ + * VSS |1 ++ 24| OE1 + * A1 |2 23| O1 + * A2 |3 22| O2 + * A3 |4 TMS-4800 21| O3 + * A4 |5 20| O4 + * A5 |6 19| O5 + * A6 |7 18| O6 + * A10 |8 17| O7 + * VGG |9 16| O8 + * A9 |10 15| A11 + * A8 |11 14| OE2 + * A7 |12 13| AR + * +----------------+ + * + * + * Naming conventions follow Texas Instruments datasheet: + * http://bitsavers.trailing-edge.com/components/ti/_dataBooks/1975_TI_The_Semiconductor_Memory_Data_Book.pdf */ -#include "nld_tms4800.h" -#include "netlist/nl_base.h" +#include "nl_base.h" + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(TMS4800) { NETLIB_CONSTRUCTOR(TMS4800) - , m_A(*this, {{ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10" }}) - , m_AR(*this, "AR") - , m_OE1(*this, "OE1") - , m_OE2(*this, "OE2") - , m_D(*this, {{ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7" }}) + , m_A(*this, { "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10" }, NETLIB_DELEGATE(inputs)) + , m_AR(*this, "AR", NETLIB_DELEGATE(inputs)) + , m_OE1(*this, "OE1", NETLIB_DELEGATE(inputs)) + , m_OE2(*this, "OE2", NETLIB_DELEGATE(inputs)) + , m_D(*this, { "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7" }) , m_last_data(*this, "m_last_data", 1) , m_ROM(*this, "ROM") + , m_supply(*this) { } - NETLIB_UPDATEI(); + private: + // FIXME: timing! + // FIXME: CS: The code looks odd, looks like m_last_data should be pushed out. + NETLIB_HANDLERI(inputs) + { + netlist_time delay = NLTIME_FROM_NS(450); + if (m_AR()) + { + unsigned a = 0; + for (std::size_t i=0; i<11; i++) + a |= (m_A[i]() << i); + + m_last_data = m_ROM[a]; + } + else + { + unsigned d = 0x00; + for (std::size_t i=0; i<4; i++) + { + if (m_OE1()) + m_D[i].push((d >> i) & 1, delay); + + if (m_OE2()) + m_D[i+4].push((d >> (i+4)) & 1, delay); + } + } + } - protected: object_array_t<logic_input_t, 11> m_A; logic_input_t m_AR; logic_input_t m_OE1; @@ -37,68 +80,10 @@ namespace netlist state_var<unsigned> m_last_data; param_rom_t<uint8_t, 11, 8> m_ROM; // 16 Kbits, used as 2 Kbit x 8 + NETLIB_NAME(power_pins) m_supply; }; - NETLIB_OBJECT_DERIVED(TMS4800_dip, TMS4800) - { - NETLIB_CONSTRUCTOR_DERIVED(TMS4800_dip, TMS4800) - { - register_subalias("2", m_A[0]); - register_subalias("3", m_A[1]); - register_subalias("4", m_A[2]); - register_subalias("5", m_A[3]); - register_subalias("6", m_A[4]); - register_subalias("7", m_A[5]); - register_subalias("12", m_A[6]); - register_subalias("11", m_A[7]); - register_subalias("10", m_A[8]); - register_subalias("8", m_A[9]); - register_subalias("15", m_A[10]); - - register_subalias("13", m_AR); - register_subalias("24", m_OE1); - register_subalias("14", m_OE2); - - register_subalias("23", m_D[0]); - register_subalias("22", m_D[1]); - register_subalias("21", m_D[2]); - register_subalias("20", m_D[3]); - register_subalias("19", m_D[4]); - register_subalias("18", m_D[5]); - register_subalias("17", m_D[6]); - register_subalias("16", m_D[7]); - } - }; - - // FIXME: timing! - NETLIB_UPDATE(TMS4800) - { - unsigned d = 0x00; - - netlist_time delay = NLTIME_FROM_NS(450); - if (m_AR()) - { - unsigned a = 0; - for (std::size_t i=0; i<11; i++) - a |= (m_A[i]() << i); - - m_last_data = m_ROM[a]; - } - else - { - for (std::size_t i=0; i<4; i++) - { - if (m_OE1()) - m_D[i].push((d >> i) & 1, delay); - - if (m_OE2()) - m_D[i+4].push((d >> (i+4)) & 1, delay); - } - } - } - NETLIB_DEVICE_IMPL(TMS4800, "ROM_TMS4800", "+AR,+OE1,+OE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10") - NETLIB_DEVICE_IMPL(TMS4800_dip, "ROM_TMS4800_DIP", "") + NETLIB_DEVICE_IMPL(TMS4800, "ROM_TMS4800", "+AR,+OE1,+OE2,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10,@VCC,@GND") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_tms4800.h b/src/lib/netlist/devices/nld_tms4800.h deleted file mode 100644 index c5bcd1337f0..00000000000 --- a/src/lib/netlist/devices/nld_tms4800.h +++ /dev/null @@ -1,53 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Felipe Sanches -/* - * nld_tms4800.h - * - * TMS-4800: 16 Kbit (2Kb x 8) READ ONLY MEMORY - * - * +----------------+ - * VSS |1 ++ 24| OE1 - * A1 |2 23| O1 - * A2 |3 22| O2 - * A3 |4 TMS-4800 21| O3 - * A4 |5 20| O4 - * A5 |6 19| O5 - * A6 |7 18| O6 - * A10 |8 17| O7 - * VGG |9 16| O8 - * A9 |10 15| A11 - * A8 |11 14| OE2 - * A7 |12 13| AR - * +----------------+ - * - * - * Naming conventions follow Texas Instruments datasheet: - * http://bitsavers.trailing-edge.com/components/ti/_dataBooks/1975_TI_The_Semiconductor_Memory_Data_Book.pdf - */ - -#ifndef NLD_TMS4800_H_ -#define NLD_TMS4800_H_ - -#include "netlist/nl_setup.h" - -#define ROM_TMS4800(name, cAR, cOE1, cOE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cA10) \ - NET_REGISTER_DEV(ROM_TMS4800, name) \ - NET_CONNECT(name, AR, cAR) \ - NET_CONNECT(name, OE1, cOE1) \ - NET_CONNECT(name, OE2, cOE2) \ - NET_CONNECT(name, A0, cA0) \ - NET_CONNECT(name, A1, cA1) \ - NET_CONNECT(name, A2, cA2) \ - NET_CONNECT(name, A3, cA3) \ - NET_CONNECT(name, A4, cA4) \ - NET_CONNECT(name, A5, cA5) \ - NET_CONNECT(name, A6, cA6) \ - NET_CONNECT(name, A7, cA7) \ - NET_CONNECT(name, A8, cA8) \ - NET_CONNECT(name, A9, cA9) \ - NET_CONNECT(name, A10, cA10) - -#define ROM_TMS4800_DIP(name) \ - NET_REGISTER_DEV(ROM_TMS4800_DIP, name) - -#endif /* NLD_TMS4800_H_ */ diff --git a/src/lib/netlist/devices/nld_tristate.cpp b/src/lib/netlist/devices/nld_tristate.cpp index b05d09ea71e..75576313af5 100644 --- a/src/lib/netlist/devices/nld_tristate.cpp +++ b/src/lib/netlist/devices/nld_tristate.cpp @@ -3,75 +3,72 @@ /* * nld_tristate.cpp * + * tristate: Hack to merge two tri-stated outputs together + * */ -#include "nld_tristate.h" -#include "netlist/nl_base.h" +#include "nl_base.h" + +// FIXME: netlist now supports proper tristate outputs. All of this is legacy +// now and needs to be removed at some time. + +namespace netlist::devices { -namespace netlist -{ - namespace devices - { NETLIB_OBJECT(tristate) { NETLIB_CONSTRUCTOR(tristate) - , m_CEQ(*this, {{ "CEQ1", "CEQ2" }}) - , m_D(*this, {{ "D1", "D2" }}) + , m_CEQ(*this, { "CEQ1", "CEQ2" }, NETLIB_DELEGATE(inputs)) + , m_D(*this, { "D1", "D2" }, NETLIB_DELEGATE(inputs)) , m_Q(*this, "Q") { } - NETLIB_UPDATEI(); - protected: object_array_t<logic_input_t, 2> m_CEQ; object_array_t<logic_input_t, 2> m_D; logic_output_t m_Q; + private: + NETLIB_HANDLERI(inputs) + { + unsigned q = 0; + if (!m_CEQ[0]()) + q |= m_D[0](); + if (!m_CEQ[1]()) + q |= m_D[1](); + + m_Q.push(q, NLTIME_FROM_NS(1)); + } }; NETLIB_OBJECT(tristate3) { NETLIB_CONSTRUCTOR(tristate3) - , m_CEQ(*this, {{ "CEQ1", "CEQ2", "CEQ3" }} ) - , m_D(*this, {{ "D1", "D2", "D3" }} ) + , m_CEQ(*this, { "CEQ1", "CEQ2", "CEQ3" }, NETLIB_DELEGATE(inputs) ) + , m_D(*this, { "D1", "D2", "D3" }, NETLIB_DELEGATE(inputs) ) , m_Q(*this, "Q") { } - NETLIB_UPDATEI(); - protected: object_array_t<logic_input_t, 3> m_CEQ; object_array_t<logic_input_t, 3> m_D; logic_output_t m_Q; - }; - - NETLIB_UPDATE(tristate) - { - unsigned q = 0; - if (!m_CEQ[0]()) - q |= m_D[0](); - if (!m_CEQ[1]()) - q |= m_D[1](); - - m_Q.push(q, NLTIME_FROM_NS(1)); - } - - NETLIB_UPDATE(tristate3) - { - unsigned q = 0; - if (!m_CEQ[0]()) - q |= m_D[0](); - if (!m_CEQ[1]()) - q |= m_D[1](); - if (!m_CEQ[2]()) - q |= m_D[2](); + private: + NETLIB_HANDLERI(inputs) + { + unsigned q = 0; + if (!m_CEQ[0]()) + q |= m_D[0](); + if (!m_CEQ[1]()) + q |= m_D[1](); + if (!m_CEQ[2]()) + q |= m_D[2](); - m_Q.push(q, NLTIME_FROM_NS(1)); - } + m_Q.push(q, NLTIME_FROM_NS(1)); + } + }; NETLIB_DEVICE_IMPL(tristate, "TTL_TRISTATE", "+CEQ1,+D1,+CEQ2,+D2") NETLIB_DEVICE_IMPL(tristate3, "TTL_TRISTATE3", "") - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nld_tristate.h b/src/lib/netlist/devices/nld_tristate.h deleted file mode 100644 index 71f97d9812d..00000000000 --- a/src/lib/netlist/devices/nld_tristate.h +++ /dev/null @@ -1,31 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* - * nld_tristate.h - * - * tristate: Hack to merge two tri-stated outputs together - * - */ - -#ifndef NLD_TRISTATE_H_ -#define NLD_TRISTATE_H_ - -#include "netlist/nl_setup.h" - -#define TTL_TRISTATE(name, cCEQ1, cD1, cCEQ2, cD2) \ - NET_REGISTER_DEV(TTL_TRISTATE, name) \ - NET_CONNECT(name, CEQ1, cCEQ1) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, CEQ2, cCEQ2) \ - NET_CONNECT(name, D2, cD2) - -#define TTL_TRISTATE3(name, cCEQ1, cD1, cCEQ2, cD2, cCEQ3, cD3) \ - NET_REGISTER_DEV(TTL_TRISTATE3, name) \ - NET_CONNECT(name, CEQ1, cCEQ1) \ - NET_CONNECT(name, D1, cD1) \ - NET_CONNECT(name, CEQ2, cCEQ2) \ - NET_CONNECT(name, D2, cD2) \ - NET_CONNECT(name, CEQ3, cCEQ3) \ - NET_CONNECT(name, D3, cD3) - -#endif /* NLD_TRISTATE_H_ */ diff --git a/src/lib/netlist/devices/nlid_cmos.h b/src/lib/netlist/devices/nlid_cmos.h deleted file mode 100644 index 06388a73535..00000000000 --- a/src/lib/netlist/devices/nlid_cmos.h +++ /dev/null @@ -1,41 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_cmos.h - * - */ - -#ifndef NLID_CMOS_H_ -#define NLID_CMOS_H_ - -#include "netlist/nl_base.h" -#include "netlist/nl_setup.h" - -namespace netlist -{ -namespace devices -{ - // FIXME: this needs to be removed - NETLIB_OBJECT(vdd_vss) - { - NETLIB_CONSTRUCTOR(vdd_vss) - , m_vdd(*this, "VDD") - , m_vss(*this, "VSS") - { - } - - NETLIB_UPDATEI() {} - NETLIB_RESETI() {} - - public: - nl_double vdd() { return m_vdd(); } - nl_double vss() { return m_vss(); } - - analog_input_t m_vdd; - analog_input_t m_vss; - }; - -} //namespace devices -} // namespace netlist - -#endif /* NLID_CMOS_H_ */ diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index 2a9fccd1dc6..0ab77e84e7d 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -1,62 +1,100 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * nlid_proxy.cpp - * - */ + +/// +/// \file nlid_proxy.cpp +/// +/// #include "nlid_proxy.h" -#include "netlist/solver/nld_solver.h" +#include "core/setup.h" +#include "nl_errstr.h" +#include "solver/nld_solver.h" -namespace netlist -{ - namespace devices - { +#include <array> + +namespace netlist::devices { // ----------------------------------------------------------------------------- // nld_base_proxy // ----------------------------------------------------------------------------- - nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name, - logic_t *inout_proxied, detail::core_terminal_t *proxy_inout) - : device_t(anetlist, name) + static constexpr std::array<std::pair<const char *, const char *>, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}}; + + nld_base_proxy::nld_base_proxy(device_param_t data, + const logic_t *inout_proxied) + : device_t(data, inout_proxied->logic_family()) + , m_tp(nullptr) + , m_tn(nullptr) { - m_logic_family = inout_proxied->logic_family(); - m_term_proxied = inout_proxied; - m_proxy_term = proxy_inout; + if (logic_family() == nullptr) + { + throw nl_exception(MF_NULLPTR_FAMILY_NP("nld_base_proxy")); + } + + bool f = false; + for (const auto & pwr_sym : power_syms) + { + pstring devname = inout_proxied->device().name(); + + auto *tp_ct(state().setup().find_terminal(devname + "." + pstring(pwr_sym.first), + /*detail::terminal_type::INPUT,*/ false)); + auto *tp_cn(state().setup().find_terminal(devname + "." + pstring(pwr_sym.second), + /*detail::terminal_type::INPUT,*/ false)); + if ((tp_ct != nullptr) && (tp_cn != nullptr)) + { + if (!tp_ct->is_analog()) + throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_ct->name())); + if (!tp_cn->is_analog()) + throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_cn->name())); + + auto tp_t = plib::dynamic_downcast<analog_t* >(tp_ct); + auto tn_t = plib::dynamic_downcast<analog_t *>(tp_cn); + if (f && (tp_t && tn_t)) + log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(), + m_tp->name(), m_tn->name(), + tp_t ? (*tp_t)->name() : "", + tn_t ? (*tn_t)->name() : "")); + else if (tp_t && tn_t) + { + m_tp = *tp_t; + m_tn = *tn_t; + f = true; + } + } + } + if (!f) + throw nl_exception(MF_NO_POWER_TERMINALS_ON_DEVICE_2(name(), state().setup().de_alias(inout_proxied->device().name()))); + + log().verbose("D/A Proxy: Found power terminals on device {1}", inout_proxied->device().name()); } // ---------------------------------------------------------------------------------------- // nld_a_to_d_proxy // ---------------------------------------------------------------------------------------- - nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, - logic_input_t *in_proxied, detail::core_terminal_t *in_proxy) - : nld_base_proxy(anetlist, name, in_proxied, in_proxy) - , m_Q(*this, "Q") - { - } - - nld_a_to_d_proxy::nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *in_proxied) - : nld_base_a_to_d_proxy(anetlist, name, in_proxied, &m_I) - , m_I(*this, "I") + nld_base_a_to_d_proxy::nld_base_a_to_d_proxy(device_param_t data, + const logic_input_t *in_proxied) + : nld_base_proxy(data, in_proxied) { } - NETLIB_RESET(a_to_d_proxy) + nld_a_to_d_proxy::nld_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied) + : nld_base_a_to_d_proxy(data, in_proxied) + , m_Q(*this, "Q") + , m_I(*this, "I", nl_delegate(&nld_a_to_d_proxy::input, this)) { } - NETLIB_UPDATE(a_to_d_proxy) + NETLIB_HANDLER(a_to_d_proxy, input) { - nl_assert(m_logic_family != nullptr); - // FIXME: Variable supply voltage! - double supply_V = logic_family()->fixed_V(); - if (supply_V == 0.0) supply_V = 5.0; + const auto v(m_I.Q_Analog()); + const auto vn(m_tn->net().Q_Analog()); + const auto vp(m_tp->net().Q_Analog()); - if (m_I.Q_Analog() > logic_family()->high_thresh_V(0.0, supply_V)) + if (logic_family()->is_above_high_threshold_V(v, vn, vp)) out().push(1, netlist_time::quantum()); - else if (m_I.Q_Analog() < logic_family()->low_thresh_V(0.0, supply_V)) + else if (logic_family()->is_below_low_threshold_V(v, vn, vp)) out().push(0, netlist_time::quantum()); else { @@ -68,132 +106,79 @@ namespace netlist // nld_d_to_a_proxy // ---------------------------------------------------------------------------------------- - nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, - logic_output_t *out_proxied, detail::core_terminal_t &proxy_out) - : nld_base_proxy(anetlist, name, out_proxied, &proxy_out) - , m_I(*this, "I") + nld_base_d_to_a_proxy::nld_base_d_to_a_proxy(device_param_t data, + const logic_output_t *out_proxied) + : nld_base_proxy(data, out_proxied) { } - nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *out_proxied) - : nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RN.m_P) + nld_d_to_a_proxy::nld_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied) + : nld_base_d_to_a_proxy(data, out_proxied) + , m_I(*this, "I", nl_delegate(&nld_d_to_a_proxy :: input, this)) , m_RP(*this, "RP") , m_RN(*this, "RN") - , m_last_state(*this, "m_last_var", -1) - , m_is_timestep(false) + , m_last_state(*this, "m_last_var", terminal_t::OUT_TRISTATE()) { - const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}; + register_sub_alias("Q", "RN.1"); - register_subalias("Q", m_RN.m_P); + connect(m_RN().N(), *m_tn); + connect(m_RP().P(), *m_tp); - bool f = false; - detail::core_terminal_t *tp(nullptr); - detail::core_terminal_t *tn(nullptr); - for (auto & pwr_sym : power_syms) - { - pstring devname = out_proxied->device().name(); - auto tp_t = setup().find_terminal(devname + "." + pwr_sym.first, - /*detail::terminal_type::INPUT,*/ false); - auto tn_t = setup().find_terminal(devname + "." + pwr_sym.second, - /*detail::terminal_type::INPUT,*/ false); - if (f && (tp_t != nullptr && tn_t != nullptr)) - log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(out_proxied->device().name(), - tp->name(), tn->name(), - tp_t ? tp_t->name() : "", - tn_t ? tn_t->name() : "")); - else if (tp_t != nullptr && tn_t != nullptr) - { - /* alternative logic */ - tp = tp_t; - tn = tn_t; - f = true; - } - } - //FIXME: Use power terminals and change info to warning or error - if (!f) - { - if (logic_family()->fixed_V() == 0.0) - log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name()))); - else - log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name()))); - m_GNDHack = plib::make_unique<analog_output_t>(*this, "_QGND"); - m_VCCHack = plib::make_unique<analog_output_t>(*this, "_QVCC"); - - connect(m_RN.m_N, *m_GNDHack); - connect(m_RP.m_P, *m_VCCHack); - connect(m_RN.m_P, m_RP.m_N); - } - else - { - log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name()); - if (setup().is_validation()) - { - // During validation, don't connect to terminals found - // This will cause terminals not connected to a rail net to - // fail connection stage. - connect(m_RN.m_N, m_RP.m_P); - } - else - { - connect(m_RN.m_N, *tn); - connect(m_RP.m_P, *tp); - } - connect(m_RN.m_P, m_RP.m_N); - } - //printf("vcc: %f\n", logic_family()->fixed_V()); + connect(m_RN().P(), m_RP().N()); } void nld_d_to_a_proxy::reset() { - // FIXME: Variable voltage - double supply_V = logic_family()->fixed_V(); - if (supply_V == 0.0) supply_V = 5.0; - //m_Q.initial(0.0); - m_last_state = -1; - m_RN.reset(); - m_RP.reset(); - if (m_GNDHack) - m_GNDHack->initial(0); - if (m_VCCHack) - m_VCCHack->initial(supply_V); - m_is_timestep = m_RN.m_P.net().solver()->has_timestep_devices(); - m_RN.set_G_V_I(plib::constants<nl_double>::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); - m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); + m_last_state = terminal_t::OUT_TRISTATE(); + m_RN().reset(); + m_RP().reset(); + m_RN().set_G_V_I(plib::reciprocal(logic_family()->R_low()), + logic_family()->low_offset_V(), nlconst::zero()); + m_RP().set_G_V_I(G_OFF, + nlconst::zero(), + nlconst::zero()); } - NETLIB_UPDATE(d_to_a_proxy) + NETLIB_HANDLER(d_to_a_proxy ,input) { - const auto state = static_cast<int>(m_I()); + const auto state = m_I(); if (state != m_last_state) { - // We only need to update the net first if this is a time stepping net - if (m_is_timestep) - { - m_RN.update(); // RN, RP are connected ... - } - if (state) - { - m_RN.set_G_V_I(G_OFF, - 0.0, 0.0); - m_RP.set_G_V_I(plib::constants<nl_double>::one() / logic_family()->R_high(), - logic_family()->high_offset_V(), 0.0); - } - else + // RN, RP are connected ... + m_RN().change_state([this, &state]() { - m_RN.set_G_V_I(plib::constants<nl_double>::one() / logic_family()->R_low(), - logic_family()->low_offset_V(), 0.0); - m_RP.set_G_V_I(G_OFF, - 0.0, 0.0); - } - m_RN.solve_later(); // RN, RP are connected ... + switch (state) + { + case 0: + m_RN().set_G_V_I(plib::reciprocal(logic_family()->R_low()), + logic_family()->low_offset_V(), nlconst::zero()); + m_RP().set_G_V_I(G_OFF, + nlconst::zero(), + nlconst::zero()); + break; + case 1: + m_RN().set_G_V_I(G_OFF, + nlconst::zero(), + nlconst::zero()); + m_RP().set_G_V_I(plib::reciprocal(logic_family()->R_high()), + logic_family()->high_offset_V(), nlconst::zero()); + break; + case terminal_t::OUT_TRISTATE(): + m_RN().set_G_V_I(G_OFF, + nlconst::zero(), + nlconst::zero()); + m_RP().set_G_V_I(G_OFF, + nlconst::zero(), + nlconst::zero()); + break; + default: + plib::terminate("unknown state for proxy: this should never happen!"); + } + }); m_last_state = state; } } - - } //namespace devices -} // namespace netlist +} // namespace netlist::devices diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h index 7a8377276a1..0f1b2ffeacd 100644 --- a/src/lib/netlist/devices/nlid_proxy.h +++ b/src/lib/netlist/devices/nlid_proxy.h @@ -1,120 +1,120 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * nlid_proxy.h - * - * netlist proxy devices - * - * This file contains internal headers - */ #ifndef NLID_PROXY_H_ #define NLID_PROXY_H_ -#include "netlist/analog/nlid_twoterm.h" -#include "netlist/nl_setup.h" +/// +/// \file nlid_proxy.h +/// +/// netlist proxy devices +/// +/// This file contains internal headers +/// -namespace netlist -{ - namespace devices - { + +#include "analog/nlid_twoterm.h" +#include "nl_base.h" + +namespace netlist::devices { // ----------------------------------------------------------------------------- // nld_base_proxy // ----------------------------------------------------------------------------- - NETLIB_OBJECT(base_proxy) + class nld_base_proxy : public device_t { public: - nld_base_proxy(netlist_state_t &anetlist, const pstring &name, - logic_t *inout_proxied, detail::core_terminal_t *proxy_inout); + nld_base_proxy(device_param_t data, const logic_t *inout_proxied); - logic_t &term_proxied() const { return *m_term_proxied; } - detail::core_terminal_t &proxy_term() const { return *m_proxy_term; } + // only used during setup + virtual detail::core_terminal_t &proxy_term() noexcept = 0; protected: + // FIXME: these should be core_terminal_t and only used for connecting + // inputs. Fix, once the ugly hacks have been removed + analog_t *m_tp; + analog_t *m_tn; - private: - logic_t *m_term_proxied; - detail::core_terminal_t *m_proxy_term; }; // ----------------------------------------------------------------------------- // nld_a_to_d_proxy // ----------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(base_a_to_d_proxy, base_proxy) + class nld_base_a_to_d_proxy : public nld_base_proxy { public: - - virtual logic_output_t &out() { return m_Q; } + virtual logic_output_t &out() noexcept = 0; protected: - - nld_base_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, - logic_input_t *in_proxied, detail::core_terminal_t *in_proxy); - - private: - - logic_output_t m_Q; + nld_base_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied); }; - NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_a_to_d_proxy) + class nld_a_to_d_proxy : public nld_base_a_to_d_proxy { public: - nld_a_to_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *in_proxied); - - analog_input_t m_I; + nld_a_to_d_proxy(device_param_t data, const logic_input_t *in_proxied); - protected: + logic_output_t &out() noexcept override { return m_Q; } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + detail::core_terminal_t &proxy_term() noexcept override + { + return m_I; + } + protected: + //NETLIB_RESETI(); private: + NETLIB_HANDLERI(input); + + logic_output_t m_Q; + analog_input_t m_I; }; // ----------------------------------------------------------------------------- // nld_base_d_to_a_proxy // ----------------------------------------------------------------------------- - NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy) + class nld_base_d_to_a_proxy : public nld_base_proxy { public: - - virtual logic_input_t &in() { return m_I; } + // only used in setup + virtual logic_input_t &in() noexcept = 0; protected: - nld_base_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, - logic_output_t *out_proxied, detail::core_terminal_t &proxy_out); + nld_base_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied); - logic_input_t m_I; }; - NETLIB_OBJECT_DERIVED(d_to_a_proxy, base_d_to_a_proxy) + class nld_d_to_a_proxy : public nld_base_d_to_a_proxy { public: - nld_d_to_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *out_proxied); + nld_d_to_a_proxy(device_param_t data, const logic_output_t *out_proxied); + + logic_input_t &in() noexcept override { return m_I; } + + detail::core_terminal_t &proxy_term() noexcept override + { + return m_RN().setup_P(); + } protected: NETLIB_RESETI(); - NETLIB_UPDATEI(); private: + NETLIB_HANDLERI(input); - static constexpr const nl_double G_OFF = 1e-9; + static constexpr const nl_fptype G_OFF = nlconst::cgmin(); - plib::unique_ptr<analog_output_t> m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd - plib::unique_ptr<analog_output_t> m_VCCHack; // FIXME: Long term, we need to connect proxy gnd to device gnd - analog::NETLIB_NAME(twoterm) m_RP; - analog::NETLIB_NAME(twoterm) m_RN; - state_var<int> m_last_state; - bool m_is_timestep; -}; + logic_input_t m_I; + NETLIB_SUB_NS(analog, two_terminal) m_RP; + NETLIB_SUB_NS(analog, two_terminal) m_RN; + state_var<netlist_sig_t> m_last_state; + }; - } //namespace devices -} // namespace netlist +} // namespace netlist::devices -#endif /* NLD_PROXY_H_ */ +#endif // NLD_PROXY_H_ diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index 89a525ef69f..fee4fad0333 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -1,86 +1,22 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // 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 "netlist/analog/nlid_twoterm.h" -#include "netlist/nl_base.h" -#include "netlist/nl_setup.h" -#include "plib/putil.h" +/// +/// \file nlid_system.h +/// -namespace netlist -{ -namespace devices -{ - // ----------------------------------------------------------------------------- - // netlistparams - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT(netlistparams) - { - NETLIB_CONSTRUCTOR(netlistparams) - , m_use_deactivate(*this, "USE_DEACTIVATE", false) - , m_startup_strategy(*this, "STARTUP_STRATEGY", 1) - , m_mos_capmodel(*this, "DEFAULT_MOS_CAPMODEL", 2) - , m_max_link_loops(*this, "MAX_LINK_RESOLVE_LOOPS", 100) - { - } - NETLIB_UPDATEI() { } - //NETLIB_RESETI() { } - //NETLIB_UPDATE_PARAMI() { } - public: - param_logic_t m_use_deactivate; - param_num_t<unsigned> m_startup_strategy; - param_num_t<unsigned> m_mos_capmodel; - //! How many times do we try to resolve links (connections) - param_num_t<unsigned> m_max_link_loops; - }; - - // ----------------------------------------------------------------------------- - // mainclock - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT(mainclock) - { - NETLIB_CONSTRUCTOR(mainclock) - , m_Q(*this, "Q") - , m_freq(*this, "FREQ", 7159000.0 * 5) - { - m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0)); - } - - NETLIB_RESETI() - { - m_Q.net().set_next_scheduled_time(netlist_time::zero()); - } - - NETLIB_UPDATE_PARAMI() - { - m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0)); - } +#include "analog/nlid_twoterm.h" +#include "nl_base.h" +#include "nl_factory.h" +#include "plib/prandom.h" +#include "plib/pstonum.h" +#include "plib/putil.h" - NETLIB_UPDATEI() - { - logic_net_t &net = m_Q.net(); - // this is only called during setup ... - net.toggle_new_Q(); - net.set_next_scheduled_time(exec().time() + m_inc); - } +#include <random> - public: - logic_output_t m_Q; - netlist_time m_inc; - private: - param_double_t m_freq; - }; +namespace netlist::devices { // ----------------------------------------------------------------------------- // clock @@ -89,134 +25,99 @@ namespace devices NETLIB_OBJECT(clock) { NETLIB_CONSTRUCTOR(clock) - , m_feedback(*this, "FB") + , m_feedback(*this, "FB", NETLIB_DELEGATE(fb)) , m_Q(*this, "Q") - , m_freq(*this, "FREQ", 7159000.0 * 5.0) + , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0)) + , m_supply(*this) { - m_inc = netlist_time::from_double(1.0 / (m_freq()*2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); - connect(m_feedback, m_Q); + connect("FB", "Q"); } - //NETLIB_RESETI(); NETLIB_UPDATE_PARAMI() { - m_inc = netlist_time::from_double(1.0 / (m_freq() * 2.0)); + m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); } - NETLIB_UPDATEI() + NETLIB_HANDLERI(fb) { - m_Q.push(!m_feedback(), m_inc); + m_Q.push(m_feedback() ^ 1, m_inc); } private: logic_input_t m_feedback; logic_output_t m_Q; - param_double_t m_freq; + param_fp_t m_freq; netlist_time m_inc; - }; + + NETLIB_NAME(power_pins) m_supply; +}; // ----------------------------------------------------------------------------- - // varclock + // variable clock // ----------------------------------------------------------------------------- NETLIB_OBJECT(varclock) { NETLIB_CONSTRUCTOR(varclock) - , m_feedback(*this, "FB") + , m_N(*this, "N", 1) + , m_func(*this,"FUNC", "T") + , m_feedback(*this, "FB", NETLIB_DELEGATE(fb)) , m_Q(*this, "Q") - , m_func(*this,"FUNC", "") - , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) - , m_funcparam({0.0}) + , m_compiled(*this, "m_compiled") + , m_supply(*this) { - if (m_func() != "") - m_compiled.compile(std::vector<pstring>({{"T"}}), m_func()); - connect(m_feedback, m_Q); + if (!m_func().empty()) + { + std::vector<pstring> inputs; + + m_I.reserve(m_N()); + inputs.reserve(m_N() + 1); + m_vals.reserve(m_N() + 1); + + // add time parameter to the front + inputs.emplace_back("T"); + m_vals.push_back(nlconst::zero()); + + for (std::uint64_t i=0; i < m_N(); i++) + { + pstring input_name = plib::pfmt("A{1}")(i); + m_I.push_back(state().make_pool_object<analog_input_t>(*this, input_name, NETLIB_DELEGATE(fb))); + inputs.push_back(input_name); + m_vals.push_back(nlconst::zero()); + } + m_compiled->compile(m_func(), inputs); + } + connect("FB", "Q"); } //NETLIB_RESETI(); //NETLIB_UPDATE_PARAMI() - NETLIB_UPDATEI() - { - m_funcparam[0] = exec().time().as_double(); - const netlist_time m_inc = netlist_time::from_double(m_compiled.evaluate(m_funcparam)); - m_Q.push(!m_feedback(), m_inc); - } - private: - logic_input_t m_feedback; - logic_output_t m_Q; - - param_str_t m_func; - plib::pfunction m_compiled; - std::vector<double> m_funcparam; - }; - - // ----------------------------------------------------------------------------- - // 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) - , m_feedback(*this, "FB") - , m_Q(*this, "Q") - , m_cnt(*this, "m_cnt", 0) - , m_off(*this, "m_off", netlist_time::zero()) + NETLIB_HANDLERI(fb) { - m_inc[0] = netlist_time::from_double(1.0 / (m_freq() * 2.0)); - - connect(m_feedback, m_Q); - - netlist_time base = netlist_time::from_double(1.0 / (m_freq()*2.0)); - std::vector<pstring> pat(plib::psplit(m_pattern(),",")); - m_off = netlist_time::from_double(m_offset()); - - std::array<std::int64_t, 32> pati = { 0 }; - - m_size = static_cast<std::uint8_t>(pat.size()); - netlist_time::mult_type total = 0; - for (unsigned i=0; i<m_size; i++) - { - // FIXME: use pstonum_ne - //pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]); - pati[i] = plib::pstonum<std::int64_t>(pat[i]); - total += pati[i]; - } - netlist_time ttotal = netlist_time::zero(); - auto sm1 = static_cast<uint8_t>(m_size - 1); - for (unsigned i=0; i < sm1; i++) + m_vals[0] = exec().time().as_fp<nl_fptype>(); + for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++) { - m_inc[i] = base * pati[i]; - ttotal += m_inc[i]; + m_vals[i+1] = (*m_I[i])(); } - m_inc[sm1] = base * total - ttotal; - + const netlist_time m_inc = netlist_time::from_fp(m_compiled->evaluate(m_vals)); + m_Q.push(m_feedback() ^ 1, m_inc); } - NETLIB_UPDATEI(); - NETLIB_RESETI(); - //NETLIB_UPDATE_PARAMI(); - - NETLIB_HANDLERI(clk2); - NETLIB_HANDLERI(clk2_pow2); - - private: - - param_double_t m_freq; - param_str_t m_pattern; - param_double_t m_offset; - + using pf_type = plib::pfunction<nl_fptype>; + param_num_t<std::uint64_t> m_N; + param_str_t m_func; logic_input_t m_feedback; logic_output_t m_Q; - state_var_u8 m_cnt; - std::uint8_t m_size; - state_var<netlist_time> m_off; - std::array<netlist_time, 32> m_inc; + std::vector<device_arena::unique_ptr<analog_input_t>> m_I; + + pf_type::values_container m_vals; + state_var<pf_type> m_compiled; + + NETLIB_NAME(power_pins) m_supply; }; // ----------------------------------------------------------------------------- @@ -228,241 +129,466 @@ namespace devices NETLIB_CONSTRUCTOR(logic_input) , m_Q(*this, "Q") , m_IN(*this, "IN", false) - /* make sure we get the family first */ - , m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)") + , m_supply(*this) { - set_logic_family(setup().family_from_model(m_FAMILY())); - m_Q.set_logic_family(this->logic_family()); } - NETLIB_UPDATEI() { } NETLIB_RESETI() { m_Q.initial(0); } - NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); } + NETLIB_UPDATE_PARAMI() + { + //printf("%s %d\n", name().c_str(), m_IN()); + m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); + } private: logic_output_t m_Q; param_logic_t m_IN; - param_model_t m_FAMILY; + NETLIB_NAME(power_pins) m_supply; }; - NETLIB_OBJECT(analog_input) + template<std::size_t N> + NETLIB_OBJECT(logic_inputN) { - NETLIB_CONSTRUCTOR(analog_input) - , m_Q(*this, "Q") - , m_IN(*this, "IN", 0.0) + NETLIB_CONSTRUCTOR(logic_inputN) + , m_Q(*this, "Q{}") + , m_IN(*this, "IN", 0) + , m_supply(*this) { } - NETLIB_UPDATEI() { } - NETLIB_RESETI() { m_Q.initial(0.0); } - NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); } + NETLIB_RESETI() { for (auto &q : m_Q) q.initial(0); } + NETLIB_UPDATE_PARAMI() + { + //printf("%s %d\n", name().c_str(), m_IN()); + for (std::size_t i=0; i<N; i++) + m_Q[i].push((m_IN()>>i) & 1, netlist_time::from_nsec(1)); + } private: - analog_output_t m_Q; - param_double_t m_IN; - }; + object_array_t<logic_output_t, N> m_Q; - // ----------------------------------------------------------------------------- - // nld_gnd - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT(gnd) - { - NETLIB_CONSTRUCTOR(gnd) - , m_Q(*this, "Q") - { - } - NETLIB_UPDATEI() - { - m_Q.push(0.0); - } - NETLIB_RESETI() { } - protected: - analog_output_t m_Q; + param_int_t m_IN; + NETLIB_NAME(power_pins) m_supply; }; - // ----------------------------------------------------------------------------- - // nld_dummy_input - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT(dummy_input) + NETLIB_OBJECT(analog_input) { - public: - NETLIB_CONSTRUCTOR(dummy_input) - , m_I(*this, "I") + NETLIB_CONSTRUCTOR(analog_input) + , m_Q(*this, "Q") + , m_IN(*this, "IN", nlconst::zero()) { } - protected: - - NETLIB_RESETI() { } - NETLIB_UPDATEI() { } + NETLIB_RESETI() { m_Q.initial(nlconst::zero()); } + NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); } private: - analog_input_t m_I; - + analog_output_t m_Q; + param_fp_t m_IN; }; + // ----------------------------------------------------------------------------- // nld_frontier // ----------------------------------------------------------------------------- + + /// \brief Frontiers divides a netlist into sub netlist + /// + /// Example: + /// + /// Consider the following mixing stage + /// + /// R1 + /// I1 >-----1RRRR2---------+ + /// | + /// R2 | + /// I2 >-----1RRRR2---------+----------> Out + /// | + /// R + /// R3 R + /// R + /// | + /// GND + /// + /// With OPTIMIZE_FRONTIER(R2.1, R2, RX) where RX is the impedance of the + /// output connected to I2 this becomes: + /// + /// R1 + /// I1 >-----1RRRR2--------------------------------+ + /// | + /// ########################## | + /// # RX # R2 | + /// I2 >----->--+-AnIn AnOut>--RRRR--->---1RRRR2---+----------> Out + /// # | # | + /// # R # R + /// # R R2 # R3 R + /// # R # R + /// # | # | + /// # GND Frontier # GND + /// # # + /// ########################## + /// + /// As a result, provided there are no other connections between the parts + /// generating S1 and S2 the "S2 part" will now have a separate solver. + /// + /// The size (aka number of nets) of the solver for I1 will be smaller. + /// The size of the solver for I2 and the rest of the circuit will be smaller + /// as well. + /// + NETLIB_OBJECT(frontier) { - public: NETLIB_CONSTRUCTOR(frontier) - , m_RIN(*this, "m_RIN", true) - , m_ROUT(*this, "m_ROUT", true) - , m_I(*this, "_I") + , m_RIN(*this, "m_RIN", NETLIB_DELEGATE(input)) // FIXME: does not look right + , m_ROUT(*this, "m_ROUT", NETLIB_DELEGATE(input)) // FIXME: does not look right + , m_I(*this, "_I", NETLIB_DELEGATE(input)) , m_Q(*this, "_Q") - , m_p_RIN(*this, "RIN", 1.0e6) - , m_p_ROUT(*this, "ROUT", 50.0) + , m_p_RIN(*this, "RIN", nlconst::magic(1.0e6)) + , m_p_ROUT(*this, "ROUT", nlconst::magic(50.0)) { - register_subalias("I", m_RIN.m_P); - register_subalias("G", m_RIN.m_N); - connect(m_I, m_RIN.m_P); + register_sub_alias("I", "m_RIN.1"); + register_sub_alias("G", "m_RIN.2"); + connect("_I", "m_RIN.1"); - register_subalias("_OP", m_ROUT.m_P); - register_subalias("Q", m_ROUT.m_N); - connect(m_Q, m_ROUT.m_P); + register_sub_alias("_OP", "m_ROUT.1"); + register_sub_alias("Q", "m_ROUT.2"); + connect("_Q", "m_ROUT.1"); } + private: NETLIB_RESETI() { - m_RIN.set_G_V_I(1.0 / m_p_RIN(),0,0); - m_ROUT.set_G_V_I(1.0 / m_p_ROUT(),0,0); + //printf("%s: in %f out %f\n", name().c_str(), m_p_RIN(), m_p_ROUT()); + m_RIN.set_G_V_I(plib::reciprocal(m_p_RIN()),0,0); + m_ROUT.set_G_V_I(plib::reciprocal(m_p_ROUT()),0,0); } - NETLIB_UPDATEI() + NETLIB_HANDLERI(input) { m_Q.push(m_I()); } - private: - analog::NETLIB_NAME(twoterm) m_RIN; - /* Fixme: only works if the device is time-stepped - need to rework */ - analog::NETLIB_NAME(twoterm) m_ROUT; + analog::NETLIB_NAME(two_terminal) m_RIN; + analog::NETLIB_NAME(two_terminal) m_ROUT; analog_input_t m_I; analog_output_t m_Q; - param_double_t m_p_RIN; - param_double_t m_p_ROUT; + param_fp_t m_p_RIN; + param_fp_t m_p_ROUT; }; - /* ----------------------------------------------------------------------------- - * nld_function - * - * FIXME: Currently a proof of concept to get congo bongo working - * ----------------------------------------------------------------------------- */ + // ----------------------------------------------------------------------------- + // nld_function + // ----------------------------------------------------------------------------- */ NETLIB_OBJECT(function) { NETLIB_CONSTRUCTOR(function) , m_N(*this, "N", 1) - , m_func(*this, "FUNC", "A0") + , m_function(*this, "FUNC", "A0") + , m_thresh(*this, "THRESH", nlconst::zero()) , m_Q(*this, "Q") - , m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager()) + , m_compiled(*this, "m_compiled") + , m_last(*this, "m_last") { - std::vector<pstring> inps; - for (int i=0; i < m_N(); i++) + std::vector<pstring> inputs; + + m_I.reserve(m_N()); + inputs.reserve(m_N()); + m_values.reserve(m_N()); + + for (uint64_t i=0; i < m_N(); i++) { - pstring n = plib::pfmt("A{1}")(i); - m_I.push_back(pool().make_poolptr<analog_input_t>(*this, n)); - inps.push_back(n); - m_vals.push_back(0.0); + pstring input_name = plib::pfmt("A{1}")(i); + m_I.push_back(state().make_pool_object<analog_input_t>(*this, input_name, NETLIB_DELEGATE(inputs))); + inputs.push_back(input_name); + m_values.push_back(nlconst::zero()); } - m_compiled.compile(inps, m_func()); + m_compiled->compile(m_function(), inputs); } protected: + NETLIB_RESETI() + { + //m_Q.initial(0.0); + } - NETLIB_RESETI(); - NETLIB_UPDATEI(); + NETLIB_HANDLERI(inputs) + { + for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++) + { + m_values[i] = (*m_I[i])(); + } + auto result = m_compiled->evaluate(m_values); + if (plib::abs(m_last - result) >= m_thresh) + { + m_Q.push(result); + m_last = result; + } + } private: - - param_int_t m_N; - param_str_t m_func; + using pf_type = plib::pfunction<nl_fptype>; + param_num_t<std::uint64_t> m_N; + param_str_t m_function; + param_fp_t m_thresh; analog_output_t m_Q; - std::vector<pool_owned_ptr<analog_input_t>> m_I; + std::vector<device_arena::unique_ptr<analog_input_t>> m_I; + + pf_type::values_container m_values; + state_var<pf_type> m_compiled; + state_var<nl_fptype> m_last; - std::vector<double> m_vals; - plib::pfunction m_compiled; }; // ----------------------------------------------------------------------------- - // nld_res_sw + // nld_sys_dsw1 // ----------------------------------------------------------------------------- - NETLIB_OBJECT(res_sw) + NETLIB_OBJECT(sys_dsw1) { - public: - NETLIB_CONSTRUCTOR(res_sw) + NETLIB_CONSTRUCTOR(sys_dsw1) + , m_RON(*this, "RON", nlconst::one()) + , m_ROFF(*this, "ROFF", nlconst::magic(1.0E20)) , m_R(*this, "_R") - , m_I(*this, "I") - , m_RON(*this, "RON", 1.0) - , m_ROFF(*this, "ROFF", 1.0E20) + , m_I(*this, "I", NETLIB_DELEGATE(input)) , m_last_state(*this, "m_last_state", 0) { - register_subalias("1", m_R.m_P); - register_subalias("2", m_R.m_N); + register_sub_alias("1", "_R.1"); + register_sub_alias("2", "_R.2"); + } + + NETLIB_RESETI() + { + m_last_state = 0; + m_R().set_R(m_ROFF()); } - NETLIB_RESETI(); //NETLIB_UPDATE_PARAMI(); - NETLIB_UPDATEI(); - analog::NETLIB_SUB(R_base) m_R; - logic_input_t m_I; - param_double_t m_RON; - param_double_t m_ROFF; + //FIXME: used by 74123 + + const terminal_t &P() const noexcept { return m_R().P(); } + const terminal_t &N() const noexcept { return m_R().N(); } + const logic_input_t &I() const noexcept { return m_I; } + + param_fp_t m_RON; + param_fp_t m_ROFF; private: + NETLIB_HANDLERI(input) + { + const netlist_sig_t state = m_I(); + if (state != m_last_state) + { + m_last_state = state; + const nl_fptype R = (state != 0) ? m_RON() : m_ROFF(); + + m_R().change_state([this, &R]() + { + m_R().set_R(R); + }); + } + } + + NETLIB_SUB_NS(analog, R_base) m_R; + logic_input_t m_I; state_var<netlist_sig_t> m_last_state; }; // ----------------------------------------------------------------------------- - // power pins - not a device, but a helper + // nld_sys_dsw2 // ----------------------------------------------------------------------------- - /** - * Power Pins are passive inputs. Delegate noop will silently ignore any - * updates. - */ - class nld_power_pins + NETLIB_OBJECT(sys_dsw2) { - public: - nld_power_pins(device_t &owner, const char *sVCC = "VCC", const char *sGND = "GND", bool force_analog_input = false) + NETLIB_CONSTRUCTOR(sys_dsw2) + , m_R1(*this, "_R1") + , m_R2(*this, "_R2") + , m_I(*this, "I", NETLIB_DELEGATE(input)) + , m_GON(*this, "GON", nlconst::magic(1e9)) // FIXME: all switches should have some on value + , m_GOFF(*this, "GOFF", nlconst::cgmin()) + , m_power_pins(*this) + { + // connect and register pins + register_sub_alias("1", "_R1.1"); + register_sub_alias("2", "_R1.2"); + register_sub_alias("3", "_R2.2"); + connect("_R1.2", "_R2.1"); + } + + private: + NETLIB_RESETI() + { + m_R1().set_G(m_GOFF()); + m_R2().set_G(m_GON()); + } + + //NETLIB_UPDATE_PARAMI(); + + NETLIB_HANDLERI(input) { - if (owner.setup().is_validation() || force_analog_input) + const netlist_sig_t state = m_I(); + + //printf("Here %d\n", state); + const nl_fptype G1 = (state != 0) ? m_GON() : m_GOFF(); + const nl_fptype G2 = (state != 0) ? m_GOFF() : m_GON(); + if (m_R1().solver() == m_R2().solver()) { - m_GND = plib::make_unique<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop)); - m_VCC = plib::make_unique<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop)); + m_R1().change_state([this, &G1, &G2]() + { + m_R1().set_G(G1); + m_R2().set_G(G2); + }); } else { - owner.create_and_register_subdevice(sPowerDevRes, m_RVG); - owner.register_subalias(sVCC, "_RVG.1"); - owner.register_subalias(sGND, "_RVG.2"); + m_R1().change_state([this, &G1]() + { + m_R1().set_G(G1); + }); + m_R2().change_state([this, &G2]() + { + m_R2().set_G(G2); + }); + } + } + + NETLIB_SUB_NS(analog, R_base) m_R1; + NETLIB_SUB_NS(analog, R_base) m_R2; + logic_input_t m_I; + param_fp_t m_GON; + param_fp_t m_GOFF; + + nld_power_pins m_power_pins; + }; + + + // ----------------------------------------------------------------------------- + // nld_sys_comp + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(sys_compd) + { + NETLIB_CONSTRUCTOR(sys_compd) + , m_IP(*this, "IP", NETLIB_DELEGATE(inputs)) + , m_IN(*this, "IN", NETLIB_DELEGATE(inputs)) + , m_Q(*this, "Q") + , m_QQ(*this, "QQ") + , m_power_pins(*this) + , m_last_state(*this, "m_last_state", 2) // ensure first execution + { + } + + private: + NETLIB_RESETI() + { + m_last_state = 0; + } + + //NETLIB_UPDATE_PARAMI(); + + NETLIB_HANDLERI(inputs) + { + const netlist_sig_t state = (m_IP() > m_IN()); + if (state != m_last_state) + { + m_last_state = state; + // FIXME: make timing a parameter + m_Q.push(state, NLTIME_FROM_NS(10)); + m_QQ.push(!state, NLTIME_FROM_NS(10)); } } - /* FIXME: this will seg-fault if force_analog_input = false */ - nl_double VCC() const NL_NOEXCEPT { return m_VCC->Q_Analog(); } - nl_double GND() const NL_NOEXCEPT { return m_GND->Q_Analog(); } + analog_input_t m_IP; + analog_input_t m_IN; + logic_output_t m_Q; + logic_output_t m_QQ; + nld_power_pins m_power_pins; - NETLIB_SUBXX(analog, R) m_RVG; // dummy resistor between VCC and GND + state_var<netlist_sig_t> m_last_state; + }; + + /// + /// \brief noise source + /// + /// An externally clocked noise source. The noise acts as a voltage source + /// with internal resistance RI. + /// + /// Since a new random value is used on each state change on I the effective + /// frequency is clock source frequency times two! + /// + /// Typical application: + /// + /// VCC + /// | + /// R + /// R + /// R + /// | + /// +-----> Output + /// | + /// +-------+ + /// | 1 | + /// --->| I | + /// | 2 | + /// +-------+ + /// | + /// R + /// R + /// R + /// | + /// GND + /// + // ----------------------------------------------------------------------------- + template <typename E, template<class> class D> + NETLIB_OBJECT(sys_noise) + { + public: + + using engine = E; + using distribution = D<nl_fptype>; + + NETLIB_CONSTRUCTOR(sys_noise) + , m_T(*this, "m_T") + , m_I(*this, "I", NETLIB_DELEGATE(input)) + , m_RI(*this, "RI", nlconst::magic(0.1)) + , m_sigma(*this, "SIGMA", nlconst::zero()) + , m_mt(*this, "m_mt") + , m_dis(*this, "m_dis",m_sigma()) + { + + register_sub_alias("1", "m_T.1"); + register_sub_alias("2", "m_T.2"); + } private: - void noop() { } - plib::unique_ptr<analog_input_t> m_VCC; // only used during validation or force_analog_input - plib::unique_ptr<analog_input_t> m_GND; // only used during validation or force_analog_input + NETLIB_HANDLERI(input) + { + nl_fptype val = m_dis()(m_mt()); + m_T().change_state([this, val]() + { + m_T().set_G_V_I(plib::reciprocal(m_RI()), val, nlconst::zero()); + }); + } + + NETLIB_RESETI() + { + m_T().set_G_V_I(plib::reciprocal(m_RI()), nlconst::zero(), nlconst::zero()); + } + + NETLIB_SUB_NS(analog, two_terminal) m_T; + logic_input_t m_I; + param_fp_t m_RI; + param_fp_t m_sigma; + state_var<engine> m_mt; + state_var<distribution> m_dis; }; -} //namespace devices -} // namespace netlist +} // namespace netlist::devices -#endif /* NLD_SYSTEM_H_ */ +#endif // NLD_SYSTEM_H_ diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index c62c67da3c1..072fa148d75 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -1,43 +1,232 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * nld_truthtable.c - * - */ -#include "nlid_truthtable.h" -#include "netlist/nl_setup.h" -#include "plib/palloc.h" -#include "plib/plists.h" +#include "plib/pstonum.h" +#include "plib/pstrutil.h" + +#include "nl_base.h" +#include "nl_factory.h" +#include "nlid_truthtable.h" #include <bitset> +#include <cstdint> +#include <vector> + +namespace netlist::devices { -namespace netlist -{ - namespace devices + template<std::size_t m_NI, std::size_t m_NO> + class NETLIB_NAME(truth_table_t) : public device_t { + public: + + using type_t = typename plib::fast_type_for_bits<m_NO + m_NI>::type; + + static constexpr const std::size_t m_num_bits = m_NI; + static constexpr const std::size_t m_size = (1 << (m_num_bits)); + static constexpr const type_t m_outmask = ((1 << m_NO) - 1); + + struct truth_table_t + { + truth_table_t() + : m_timing_index{0} + {} + + std::array<type_t, m_size> m_out_state; + std::array<uint_least8_t, m_size * m_NO> m_timing_index; + std::array<netlist_time, 16> m_timing_nt; + }; + + nld_truth_table_t(device_param_t data, const pstring &model, + truth_table_t &ttp, const std::vector<pstring> &desc) + : device_t(data, model) +#if NL_USE_TT_ALTERNATIVE + , m_state(*this, "m_state", 0) +#endif + , m_ign(*this, "m_ign", 0) + , m_ttp(ttp) + /* FIXME: the family should provide the names of the power-terminals! */ + , m_power_pins(*this) + { + m_activate = activate_delegate(& NETLIB_NAME(truth_table_t) :: incdec_active, this); + set_hint_deactivate(true); + init(desc); + } + + private: + void init(const std::vector<pstring> &desc); + + NETLIB_RESETI() + { + int active_outputs = 0; + m_ign = 0; +#if NL_USE_TT_ALTERNATIVE + m_state = 0; +#endif + for (std::size_t i = 0; i < m_NI; ++i) + { + m_I[i].activate(); +#if NL_USE_TT_ALTERNATIVE + m_state |= (m_I[i]() << i); +#endif + } + for (auto &q : m_Q) + if (q.has_net()) + if (!q.net().core_terms_empty()) + active_outputs++; + set_active_outputs(active_outputs); + } + + NETLIB_HANDLERI(inputs) + { +#if NL_USE_TT_ALTERNATIVE + m_state = 0; + for (std::size_t i = 0; i < m_NI; ++i) + { + m_state |= (m_I[i]() << i); + } +#endif + process<true>(); + } + +#if NL_USE_TT_ALTERNATIVE + template <std::size_t N> + void update_N() noexcept + { + m_state &= ~(1<<N); + m_state |= (m_I[N]() << N); + process<true>(); + } +#endif + + void incdec_active(bool a) noexcept + { + if (a) + { + process<false>(); + } + else + { + for (std::size_t i = 0; i< m_NI; i++) + m_I[i].inactivate(); + m_ign = (1<<m_NI)-1; + } + } + + template<bool doOUT> + void process() noexcept + { + netlist_time_ext mt(netlist_time_ext::zero()); + type_t new_state(0); + type_t ign(m_ign); + + if (doOUT) + { +#if !NL_USE_TT_ALTERNATIVE + for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I) + if (ign & 1) + I->activate(); + for (std::size_t i = 0; i < m_NI; i++) + new_state |= (m_I[i]() << i); +#else + new_state = m_state; + for (std::size_t i = 0; ign != 0; ign >>= 1, ++i) + { + if (ign & 1) + { + new_state &= ~(1 << i); + m_I[i].activate(); + new_state |= (m_I[i]() << i); + } + } +#endif + } + else + for (std::size_t i = 0; i < m_NI; i++) + { + m_I[i].activate(); + new_state |= (m_I[i]() << i); + mt = std::max(this->m_I[i].net().next_scheduled_time(), mt); + } + + const type_t output_state(m_ttp.m_out_state[new_state]); + const type_t out(output_state & m_outmask); + + m_ign = output_state >> m_NO; + + const auto *t(&m_ttp.m_timing_index[new_state * m_NO]); + + if (doOUT) + //for (std::size_t i = 0; i < m_NO; ++i) + // m_Q[i].push((out >> i) & 1, tim[t[i]]); + this->push(out, t); + else + { + const auto *tim = m_ttp.m_timing_nt.data(); + for (std::size_t i = 0; i < m_NO; ++i) + m_Q[i].set_Q_time((out >> i) & 1, mt + tim[t[i]]); + } + + ign = m_ign; + for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I) + if (ign & 1) + I->inactivate(); +#if NL_USE_TT_ALTERNATIVE + m_state = new_state; +#endif + } + + template<typename T> + void push(const T &v, const std::uint_least8_t * t) + { + if (m_NO >= 1) m_Q[0].push((v >> 0) & 1, m_ttp.m_timing_nt[t[0]]); + if (m_NO >= 2) m_Q[1].push((v >> 1) & 1, m_ttp.m_timing_nt[t[1]]); + if (m_NO >= 3) m_Q[2].push((v >> 2) & 1, m_ttp.m_timing_nt[t[2]]); + if (m_NO >= 4) m_Q[3].push((v >> 3) & 1, m_ttp.m_timing_nt[t[3]]); + if (m_NO >= 5) m_Q[4].push((v >> 4) & 1, m_ttp.m_timing_nt[t[4]]); + if (m_NO >= 6) m_Q[5].push((v >> 5) & 1, m_ttp.m_timing_nt[t[5]]); + if (m_NO >= 7) m_Q[6].push((v >> 6) & 1, m_ttp.m_timing_nt[t[6]]); + if (m_NO >= 8) m_Q[7].push((v >> 7) & 1, m_ttp.m_timing_nt[t[7]]); + for (std::size_t i = 8; i < m_NO; i++) + m_Q[i].push((v >> i) & 1, m_ttp.m_timing_nt[t[i]]); + } + + + plib::static_vector<logic_input_t, m_NI> m_I; + plib::static_vector<logic_output_t, m_NO> m_Q; + +#if NL_USE_TT_ALTERNATIVE + state_var<type_t> m_state; +#endif + state_var<type_t> m_ign; + const truth_table_t m_ttp; + /* FIXME: the family should provide the names of the power-terminals! */ + nld_power_pins m_power_pins; + }; + // ---------------------------------------------------------------------------------------- // int compatible bitset .... // ---------------------------------------------------------------------------------------- template <typename T> - struct sbitset + struct pbitset { using type = T; - sbitset() : m_bs(0) { } - /* explicit */ sbitset(T v) : m_bs(v) { } + constexpr pbitset() noexcept : m_bs(0) { } + constexpr pbitset(T v) noexcept : m_bs(v) { } - sbitset &set() { *this = all_bits(); return *this; } - sbitset &set(const std::size_t bit) { m_bs |= (static_cast<T>(1) << bit); return *this; } - sbitset &reset() { *this = no_bits(); return *this; } - sbitset &reset(const std::size_t bit) { m_bs &= ~(static_cast<T>(1) << bit); return *this; } + constexpr pbitset &set() noexcept { *this = all_bits(); return *this; } + constexpr pbitset &set(std::size_t bit) noexcept { m_bs |= (static_cast<T>(1) << bit); return *this; } + constexpr pbitset &reset() noexcept { *this = no_bits(); return *this; } + constexpr pbitset &reset(std::size_t bit) noexcept { m_bs &= ~(static_cast<T>(1) << bit); return *this; } - sbitset invert() const { return sbitset(~m_bs); } - std::size_t count() + constexpr pbitset flip() const noexcept { return pbitset(~m_bs); } + constexpr pbitset flip(std::size_t bit) const noexcept { return pbitset(m_bs ^ (static_cast<T>(1) << bit)); } + + constexpr std::size_t count() const noexcept { - std::size_t ret = 0; + std::size_t ret(0); for (T v = m_bs; v != 0; v = v >> 1) { ret += (v & 1); @@ -46,23 +235,27 @@ namespace netlist } constexpr bool test(const std::size_t bit) const { return ((m_bs >> bit) & 1) == 1; } - operator T&() { return m_bs; } - operator const T&() const { return m_bs; } - constexpr T as_uint() const { return m_bs; } - - constexpr bool all() const { return *this == all_bits(); } - - /* - * And all bits set with compressed bits from b - * - * Example: b = {b3,b2,b1,b0} - * v = {v7, 0, v5, 0, v3, v2, 0, 0} - * Returns {v7 & b3, 0, v5 & b2, 0, v3 & b1, v2 & b0, 0, 0} - */ - - sbitset expand_and(sbitset b) const + constexpr operator T&() noexcept { return m_bs; } + constexpr operator const T&() const noexcept { return m_bs; } + constexpr T as_uint() const noexcept { return m_bs; } + + constexpr bool all() const noexcept { return *this == all_bits(); } + + /// \brief And all bits set with compressed bits from b + /// + /// Example: + /// + /// \code + /// b = {b3,b2,b1,b0} + /// v = {v7, 0, v5, 0, v3, v2, 0, 0} + /// return {v7 & b3, 0, v5 & b2, 0, v3 & b1, v2 & b0, 0, 0} + /// \endcode + /// + /// \returns pbitset + /// + constexpr pbitset expand_and(pbitset b) const noexcept { - sbitset ret; + pbitset ret; T v( m_bs); for (size_t i = 0; v != 0; v = v >> 1, ++i) @@ -77,59 +270,58 @@ namespace netlist return ret; } - static constexpr const sbitset all_bits() noexcept { return sbitset(~static_cast<T>(0)); } - static constexpr const sbitset no_bits() noexcept{ return sbitset(static_cast<T>(0)); } + static constexpr pbitset all_bits() noexcept { return pbitset(~static_cast<T>(0)); } + static constexpr pbitset no_bits() noexcept{ return pbitset(static_cast<T>(0)); } private: T m_bs; }; + // ---------------------------------------------------------------------------------------- - // Truthtable parsing .... + // Truth table parsing .... // ---------------------------------------------------------------------------------------- - //static const uint_least64_t all_set = ~(static_cast<uint_least64_t>(0)); - - using tt_bitset = sbitset<uint_least64_t>; + using tt_bitset = pbitset<std::uint_least64_t>; struct packed_int { - packed_int(void *data, std::size_t bits) + constexpr packed_int(void *data, std::size_t bits) noexcept : m_data(data) , m_size(bits) {} - void set(const size_t pos, const uint_least64_t val) + constexpr void set(size_t pos, std::uint_least64_t val) noexcept { switch (m_size) { - case 8: static_cast<uint_least8_t *>(m_data)[pos] = static_cast<uint_least8_t>(val); break; - case 16: static_cast<uint_least16_t *>(m_data)[pos] = static_cast<uint_least16_t>(val); break; - case 32: static_cast<uint_least32_t *>(m_data)[pos] = static_cast<uint_least32_t>(val); break; - case 64: static_cast<uint_least64_t *>(m_data)[pos] = static_cast<uint_least64_t>(val); break; + case 8: static_cast<std::uint_least8_t *>(m_data)[pos] = static_cast<std::uint_least8_t>(val); break; + case 16: static_cast<std::uint_least16_t *>(m_data)[pos] = static_cast<std::uint_least16_t>(val); break; + case 32: static_cast<std::uint_least32_t *>(m_data)[pos] = static_cast<std::uint_least32_t>(val); break; + case 64: static_cast<std::uint_least64_t *>(m_data)[pos] = static_cast<std::uint_least64_t>(val); break; default: { } } } - uint_least64_t operator[] (size_t pos) const + constexpr std::uint_least64_t operator[] (size_t pos) const noexcept { switch (m_size) { - case 8: return static_cast<uint_least8_t *>(m_data)[pos]; - case 16: return static_cast<uint_least16_t *>(m_data)[pos]; - case 32: return static_cast<uint_least32_t *>(m_data)[pos]; - case 64: return static_cast<uint_least64_t *>(m_data)[pos]; + case 8: return static_cast<std::uint_least8_t *>(m_data)[pos]; + case 16: return static_cast<std::uint_least16_t *>(m_data)[pos]; + case 32: return static_cast<std::uint_least32_t *>(m_data)[pos]; + case 64: return static_cast<std::uint_least64_t *>(m_data)[pos]; default: return 0; //should never happen } } - uint_least64_t mask() const + constexpr std::uint_least64_t mask() const noexcept { switch (m_size) { - case 8: return static_cast<uint_least8_t>(-1); - case 16: return static_cast<uint_least16_t>(-1); - case 32: return static_cast<uint_least32_t>(-1); - case 64: return static_cast<uint_least64_t>(-1); + case 8: return static_cast<std::uint_least8_t>(-1); + case 16: return static_cast<std::uint_least16_t>(-1); + case 32: return static_cast<std::uint_least32_t>(-1); + case 64: return static_cast<std::uint_least64_t>(-1); default: return 0; //should never happen } @@ -139,71 +331,88 @@ namespace netlist size_t m_size; }; - struct truthtable_parser + struct truth_table_parser { - truthtable_parser(unsigned NO, unsigned NI, bool *initialized, + truth_table_parser(unsigned NO, unsigned NI, packed_int outs, uint_least8_t *timing, netlist_time *timing_nt) - : m_NO(NO), m_NI(NI), m_initialized(initialized), - m_out_state(outs), m_timing(timing), m_timing_nt(timing_nt), - m_num_bits(m_NI), - m_size(1 << (m_num_bits)) + : m_NO(NO) + , m_NI(NI) + , m_out_state(outs) + , m_timing(timing) + , m_timing_nt(timing_nt) + , m_num_bits(m_NI) + , m_size(1 << (m_num_bits)) { } - void parse(const std::vector<pstring> &desc); + void parse(const std::vector<pstring> &truth_table); private: - void parseline(unsigned cur, std::vector<pstring> list, - tt_bitset state, uint_least64_t val, std::vector<uint_least8_t> &timing_index); + void parse_line(unsigned cur, std::vector<pstring> list, + tt_bitset state, std::uint_least64_t val, std::vector<uint_least8_t> &timing_index); - tt_bitset calculate_ignored_inputs(tt_bitset i); + tt_bitset calculate_ignored_inputs(tt_bitset state) const; unsigned m_NO; unsigned m_NI; - bool *m_initialized; packed_int m_out_state; uint_least8_t *m_timing; netlist_time *m_timing_nt; - /* additional values */ - const std::size_t m_num_bits; const std::size_t m_size; }; // ---------------------------------------------------------------------------------------- - // Truthtable class .... + // Truth table class .... // ---------------------------------------------------------------------------------------- template<std::size_t m_NI, std::size_t m_NO> - void NETLIB_NAME(truthtable_t)<m_NI, m_NO>::init(const std::vector<pstring> &desc) + void NETLIB_NAME(truth_table_t)<m_NI, m_NO>::init(const std::vector<pstring> &desc) { - set_hint_deactivate(true); - pstring header = desc[0]; - std::vector<pstring> io(plib::psplit(header,"|")); + std::vector<pstring> io(plib::psplit(header,'|')); // checks nl_assert_always(io.size() == 2, "too many '|'"); - std::vector<pstring> inout(plib::psplit(io[0], ",")); - nl_assert_always(inout.size() == m_num_bits, "bitcount wrong"); - std::vector<pstring> outputs(plib::psplit(io[1], ",")); + std::vector<pstring> inout(plib::psplit(io[0], ',')); + nl_assert_always(inout.size() == m_num_bits, "bit count wrong"); + std::vector<pstring> outputs(plib::psplit(io[1], ',')); nl_assert_always(outputs.size() == m_NO, "output count wrong"); +#if !NL_USE_TT_ALTERNATIVE + for (std::size_t i=0; i < m_NI; i++) + { + inout[i] = plib::trim(inout[i]); + m_I.emplace_back(*this, inout[i], nl_delegate(&NETLIB_NAME(truth_table_t)<m_NI, m_NO> :: inputs, this)); + } +#else for (std::size_t i=0; i < m_NI; i++) { inout[i] = plib::trim(inout[i]); - m_I.emplace(i, *this, inout[i]); } + if (0 < m_NI) m_I.emplace_back(*this, inout[0], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<0>, this)); + if (1 < m_NI) m_I.emplace_back(*this, inout[1], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<1>, this)); + if (2 < m_NI) m_I.emplace_back(*this, inout[2], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<2>, this)); + if (3 < m_NI) m_I.emplace_back(*this, inout[3], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<3>, this)); + if (4 < m_NI) m_I.emplace_back(*this, inout[4], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<4>, this)); + if (5 < m_NI) m_I.emplace_back(*this, inout[5], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<5>, this)); + if (6 < m_NI) m_I.emplace_back(*this, inout[6], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<6>, this)); + if (7 < m_NI) m_I.emplace_back(*this, inout[7], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<7>, this)); + if (8 < m_NI) m_I.emplace_back(*this, inout[8], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<8>, this)); + if (9 < m_NI) m_I.emplace_back(*this, inout[9], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<9>, this)); + if (10 < m_NI) m_I.emplace_back(*this, inout[10], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<10>, this)); + if (11 < m_NI) m_I.emplace_back(*this, inout[11], nl_delegate(&nld_truth_table_t<m_NI, m_NO>::update_N<11>, this)); +#endif for (std::size_t i=0; i < m_NO; i++) { outputs[i] = plib::trim(outputs[i]); - m_Q.emplace(i, *this, outputs[i]); + m_Q.emplace_back(*this, outputs[i]); // Connect output "Q" to input "_Q" if this exists // This enables timed state without having explicit state .... pstring tmp = "_" + outputs[i]; - const std::size_t idx = plib::container::indexof(inout, tmp); + const std::size_t idx = plib::container::index_of(inout, tmp); if (idx != plib::container::npos) connect(m_Q[i], m_I[idx]); } @@ -211,74 +420,71 @@ namespace netlist } // ---------------------------------------------------------------------------------------- - // Truthtable factory .... + // Truth table factory .... // ---------------------------------------------------------------------------------------- template<unsigned m_NI, unsigned m_NO> - class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t + class factory_truth_table_t : public factory::truth_table_base_element_t { public: - netlist_factory_truthtable_t(const pstring &name, const pstring &classname, - const pstring &def_param, const pstring &sourcefile) - : netlist_base_factory_truthtable_t(name, classname, def_param, sourcefile) + factory_truth_table_t(const pstring &name, + factory::properties &&props) + : truth_table_base_element_t(name, std::move(props)) { } - pool_owned_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override + device_arena::unique_ptr<core_device_t> make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) override { - using tt_type = nld_truthtable_t<m_NI, m_NO>; - truthtable_parser desc_s(m_NO, m_NI, &m_ttbl.m_initialized, - packed_int(m_ttbl.m_out_state.data(), sizeof(m_ttbl.m_out_state[0]) * 8), - m_ttbl.m_timing_index.data(), m_ttbl.m_timing_nt.data()); + using tt_type = nld_truth_table_t<m_NI, m_NO>; - desc_s.parse(m_desc); - - /* update truthtable family definitions */ - if (m_family_name != "") - m_family_desc = anetlist.setup().family_from_model(m_family_name); + if (!m_table) + { + m_table = plib::make_unique<typename nld_truth_table_t<m_NI, m_NO>::truth_table_t>(pool); + truth_table_parser desc_s(m_NO, m_NI, + packed_int(m_table->m_out_state.data(), sizeof(m_table->m_out_state[0]) * 8), + m_table->m_timing_index.data(), m_table->m_timing_nt.data()); - if (m_family_desc == nullptr) - throw nl_exception("family description not found for {1}", m_family_name); + desc_s.parse(m_desc); + } - return pool().make_poolptr<tt_type>(anetlist, name, m_family_desc, m_ttbl, m_desc); + return plib::make_unique<tt_type>(pool, device_data_t{anetlist, name}, m_family_name, *m_table, m_desc); } private: - typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl; + device_arena::unique_ptr<typename nld_truth_table_t<m_NI, m_NO>::truth_table_t> m_table; }; - tt_bitset truthtable_parser::calculate_ignored_inputs(tt_bitset state) + tt_bitset truth_table_parser::calculate_ignored_inputs(tt_bitset state) const { // Determine all inputs which may be ignored ... tt_bitset ignore = 0; for (std::size_t j=0; j<m_NI; j++) { // if changing the input directly doesn't change outputs we can ignore - if (m_out_state[state] == m_out_state[tt_bitset(state).set(j)]) + if (m_out_state[state] == m_out_state[tt_bitset(state).flip(j)]) ignore.set(j); } - /* Check all permutations of ign - * We have to remove those where the ignored inputs - * may change the output - */ - + // Check all permutations of ign + // We have to remove those where the ignored inputs + // may change the output + // tt_bitset bits = tt_bitset().set(ignore.count()); std::vector<bool> t(bits); // loop over all combinations of bits set in ignore - for (uint_least64_t j=1; j < bits; j++) + for (std::uint_least64_t j = 1; j < bits; j++) { tt_bitset tign = ignore.expand_and(j); t[j] = false; - tt_bitset bitsk = tt_bitset().set(tign.count()); + tt_bitset bitsk(tt_bitset().set(tign.count())); // now loop over all combinations of the bits set currently set - for (uint_least64_t k=0; k < bitsk; k++) + for (std::uint_least64_t k=0; k < bitsk; k++) { tt_bitset b = tign.expand_and(k); // will any of the inputs ignored change the output if changed? - if (m_out_state[state] != m_out_state[(state & tign.invert()) | b]) + if (m_out_state[state] != m_out_state[state ^ b]) { t[j] = true; break; @@ -286,16 +492,16 @@ namespace netlist } } - /* find the ignore mask without potential for change with the most bits */ + // find the ignore mask without potential for change with the most bits - size_t jb=0; - tt_bitset jm=0; + size_t jb(0); + tt_bitset jm(0); - for (uint_least64_t j=1; j<bits; j++) + for (std::uint_least64_t j=1; j<bits; j++) { tt_bitset bj(j); - size_t nb = bj.count(); - if ((t[j] == false) && (nb>jb)) + size_t nb(bj.count()); + if (!t[j] && (nb > jb)) { jb = nb; jm = bj; @@ -304,195 +510,197 @@ namespace netlist return ignore.expand_and(jm); } -// ---------------------------------------------------------------------------------------- -// parseline -// ---------------------------------------------------------------------------------------- - -void truthtable_parser::parseline(unsigned cur, std::vector<pstring> list, - tt_bitset state, uint_least64_t val, std::vector<uint_least8_t> &timing_index) -{ - pstring elem = plib::trim(list[cur]); - uint_least64_t start = 0; - uint_least64_t end = 0; + // ---------------------------------------------------------------------------------------- + // parse line + // ---------------------------------------------------------------------------------------- - if (elem == "0") - { - start = 0; - end = 0; - } - else if (elem == "1") - { - start = 1; - end = 1; - } - else if (elem == "X") - { - start = 0; - end = 1; - } - else - nl_assert_always(false, "unknown input value (not 0, 1, or X)"); - for (uint_least64_t i = start; i <= end; i++) + void truth_table_parser::parse_line(unsigned cur, std::vector<pstring> list, + tt_bitset state, std::uint_least64_t val, std::vector<uint_least8_t> &timing_index) { - tt_bitset nstate = state; - if (i==1) - nstate.set(cur); + pstring elem = plib::trim(list[cur]); + std::uint_least64_t start = 0; + std::uint_least64_t end = 0; - if (cur < m_num_bits - 1) + if (elem == "0") + { + start = 0; + end = 0; + } + else if (elem == "1") + { + start = 1; + end = 1; + } + else if (elem == "X") { - parseline(cur + 1, list, nstate, val, timing_index); + start = 0; + end = 1; } else + nl_assert_always(false, "unknown input value (not 0, 1, or X)"); + for (std::uint_least64_t i = start; i <= end; i++) { - // cutoff previous inputs and outputs for ignore - if (m_out_state[nstate] != m_out_state.mask() && m_out_state[nstate] != val) - throw nl_exception(plib::pfmt("Error in truthtable: State {1:04} already set, {2} != {3}\n") - .x(nstate.as_uint())(m_out_state[nstate])(val) ); - m_out_state.set(nstate, val); - for (std::size_t j=0; j<m_NO; j++) - m_timing[nstate * m_NO + j] = timing_index[j]; + tt_bitset new_state = state; + if (i==1) + new_state.set(cur); + + if (cur < m_num_bits - 1) + { + parse_line(cur + 1, list, new_state, val, timing_index); + } + else + { + // cutoff previous inputs and outputs for ignore + if (m_out_state[new_state] != m_out_state.mask() && m_out_state[new_state] != val) + throw nl_exception(plib::pfmt("Error in truth table: State {1:04} already set, {2} != {3}\n") + .x(new_state.as_uint())(m_out_state[new_state])(val) ); + m_out_state.set(new_state, val); + for (std::size_t j=0; j<m_NO; j++) + m_timing[new_state * m_NO + j] = timing_index[j]; + } } } -} - -void truthtable_parser::parse(const std::vector<pstring> &truthtable) -{ - unsigned line = 0; - if (*m_initialized) - return; + void truth_table_parser::parse(const std::vector<pstring> &truth_table) + { + unsigned line = 0; - pstring ttline(truthtable[line]); - line++; - ttline = truthtable[line]; - line++; + pstring tt_line(truth_table[line]); + line++; + tt_line = truth_table[line]; + line++; - for (unsigned j=0; j < m_size; j++) - m_out_state.set(j, tt_bitset::all_bits()); + for (unsigned j=0; j < m_size; j++) + m_out_state.set(j, tt_bitset::all_bits()); - for (int j=0; j < 16; j++) - m_timing_nt[j] = netlist_time::zero(); + for (int j=0; j < 16; j++) + m_timing_nt[j] = netlist_time::zero(); - while (!(ttline == "")) - { - std::vector<pstring> io(plib::psplit(ttline,"|")); - // checks - nl_assert_always(io.size() == 3, "io.count mismatch"); - std::vector<pstring> inout(plib::psplit(io[0], ",")); - nl_assert_always(inout.size() == m_num_bits, "number of bits not matching"); - std::vector<pstring> out(plib::psplit(io[1], ",")); - nl_assert_always(out.size() == m_NO, "output count not matching"); - std::vector<pstring> times(plib::psplit(io[2], ",")); - nl_assert_always(times.size() == m_NO, "timing count not matching"); - - tt_bitset val = 0; - std::vector<uint_least8_t> tindex; - - /* - * FIXME: evaluation of outputs should be done in parseline to - * enable the use of inputs for output values, i.e. "I1" or "~I1" - * in addition to "0" and "1". - */ - for (unsigned j=0; j<m_NO; j++) + while (!tt_line.empty()) { - pstring outs = plib::trim(out[j]); - if (outs == "1") - val.set(j); + std::vector<pstring> io(plib::psplit(tt_line,'|')); + // checks + nl_assert_always(io.size() == 3, "io.count mismatch"); + std::vector<pstring> inout(plib::psplit(io[0], ',')); + nl_assert_always(inout.size() == m_num_bits, "number of bits not matching"); + std::vector<pstring> out(plib::psplit(io[1], ',')); + nl_assert_always(out.size() == m_NO, "output count not matching"); + std::vector<pstring> times(plib::psplit(io[2], ',')); + nl_assert_always(times.size() == m_NO, "timing count not matching"); + + tt_bitset val = 0; + std::vector<uint_least8_t> indexes; + + // + // FIXME: evaluation of outputs should be done in parse_line to + // enable the use of inputs for output values, i.e. "I1" or "~I1" + // in addition to "0" and "1". + + for (unsigned j=0; j<m_NO; j++) + { + pstring outs = plib::trim(out[j]); + if (outs == "1") + val.set(j); + else + nl_assert_always(outs == "0", "Unknown value (not 0 or 1"); + // FIXME: error handling + netlist_time t = netlist_time::from_nsec(plib::pstonum<std::int64_t>(plib::trim(times[j]))); + uint_least8_t k=0; + while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t) + k++; + m_timing_nt[k] = t; + indexes.push_back(k); //[j] = k; + } + + parse_line(0, inout, 0 , val, indexes); + if (line < truth_table.size()) + tt_line = truth_table[line]; else - nl_assert_always(outs == "0", "Unknown value (not 0 or 1"); - // FIXME: error handling - netlist_time t = netlist_time::from_nsec(plib::pstonum<std::int64_t>(plib::trim(times[j]))); - uint_least8_t k=0; - while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t) - k++; - m_timing_nt[k] = t; - tindex.push_back(k); //[j] = k; + tt_line = ""; + line++; } - parseline(0, inout, 0 , val, tindex); - if (line < truthtable.size()) - ttline = truthtable[line]; - else - ttline = ""; - line++; - } - - // determine ignore mask by looping over all input combinations - std::vector<tt_bitset> ign(m_size); - for (tt_bitset &x : ign) - x.set(); + // determine ignore mask by looping over all input combinations + std::vector<tt_bitset> ign(m_size); + for (tt_bitset &x : ign) + x.set(); - for (uint_least64_t i=0; i < m_size; i++) - { - if (ign[i].all()) // not yet visited + for (std::uint_least64_t i=0; i < m_size; i++) { - tt_bitset tign = calculate_ignored_inputs(i); - - ign[i] = tign; + if (ign[i].all()) // not yet visited + { + tt_bitset tign = calculate_ignored_inputs(i); - /* don't need to recalculate similar ones */ + ign[i] = tign; - tt_bitset bitsk; - bitsk.set(tign.count()); + // don't need to recalculate similar ones + tt_bitset bitsk; + bitsk.set(tign.count()); - for (uint_least64_t k=0; k < bitsk; k++) - { - tt_bitset b = tign.expand_and(k); - ign[(i & tign.invert()) | b] = tign; + for (std::uint_least64_t k=0; k < bitsk; k++) + { + tt_bitset b = tign.expand_and(k); + ign[(i & tign.flip()) | b] = tign; + } } } + + for (size_t i=0; i<m_size; i++) + { + if (m_out_state[i] == m_out_state.mask()) + throw nl_exception(plib::pfmt("truth table: found element not set {1}\n").x(i) ); + m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO)); + } } - for (size_t i=0; i<m_size; i++) - { - if (m_out_state[i] == m_out_state.mask()) - throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) ); - m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO)); - } - *m_initialized = true; -} +} // namespace netlist::devices -netlist_base_factory_truthtable_t::netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname, - const pstring &def_param, const pstring &sourcefile) -: factory::element_t(name, classname, def_param, sourcefile), m_family_desc(family_TTL()) -{ -} +namespace netlist::factory { -#define ENTRYY(n, m, s) case (n * 100 + m): \ - { using xtype = netlist_factory_truthtable_t<n, m>; \ - ret = plib::make_unique<xtype>(desc.name, desc.classname, desc.def_param, s); } break + truth_table_base_element_t::truth_table_base_element_t(const pstring &name, + properties &&props) + : factory::element_t(name, std::move(props)) + , m_family_name(config::DEFAULT_LOGIC_FAMILY()) + { + } -#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \ - ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \ - ENTRYY(n, 7, s); ENTRYY(n, 8, s) + #define ENTRYY(n, m, s) case (n * 100 + m): \ + { using dev_type = devices::factory_truth_table_t<n, m>; \ + auto cs=s; \ + ret = plib::make_unique<dev_type, host_arena>(desc.name, std::move(cs)); } \ + break -plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &desc, const pstring &sourcefile) -{ - plib::unique_ptr<netlist_base_factory_truthtable_t> ret; + #define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \ + ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \ + ENTRYY(n, 7, s); ENTRYY(n, 8, s); ENTRYY(n, 9, s); \ + ENTRYY(n, 10, s) - switch (desc.ni * 100 + desc.no) + host_arena::unique_ptr<truth_table_base_element_t> truth_table_create(tt_desc &desc, properties &&props) { - ENTRY(1, sourcefile); - ENTRY(2, sourcefile); - ENTRY(3, sourcefile); - ENTRY(4, sourcefile); - ENTRY(5, sourcefile); - ENTRY(6, sourcefile); - ENTRY(7, sourcefile); - ENTRY(8, sourcefile); - ENTRY(9, sourcefile); - ENTRY(10, sourcefile); - ENTRY(11, sourcefile); - ENTRY(12, sourcefile); - default: - pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no); - nl_assert_always(false, msg); - } - ret->m_desc = desc.desc; - ret->m_family_name = desc.family; + host_arena::unique_ptr<truth_table_base_element_t> ret; - return ret; -} + switch (desc.ni * 100 + desc.no) + { + ENTRY(1, props); + ENTRY(2, props); + ENTRY(3, props); + ENTRY(4, props); + ENTRY(5, props); + ENTRY(6, props); + ENTRY(7, props); + ENTRY(8, props); + ENTRY(9, props); + ENTRY(10, props); + ENTRY(11, props); + ENTRY(12, props); + default: + pstring msg = plib::pfmt("unable to create truth table<{1},{2}>")(desc.ni)(desc.no); + nl_assert_always(false, putf8string(msg).c_str()); + } + ret->m_desc = desc.desc; + ret->m_family_name = (!desc.family.empty() ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY())); + + return ret; + } - } //namespace devices -} // namespace netlist +} // namespace netlist::factory diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h index 564bb16451b..83f9679e70b 100644 --- a/src/lib/netlist/devices/nlid_truthtable.h +++ b/src/lib/netlist/devices/nlid_truthtable.h @@ -1,227 +1,31 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * nld_truthtable.h - * - * Created on: 19 Jun 2014 - * Author: andre - */ + +/// +/// \file nld_truthtable.h +/// +/// #ifndef NLID_TRUTHTABLE_H_ #define NLID_TRUTHTABLE_H_ -#include "netlist/devices/nlid_system.h" -#include "netlist/nl_base.h" -#include "netlist/nl_setup.h" -#include "plib/putil.h" - -namespace netlist -{ -namespace devices -{ - - template<unsigned bits> - struct need_bytes_for_bits - { - enum { value = - bits <= 8 ? 1 : - bits <= 16 ? 2 : - bits <= 32 ? 4 : - 8 - }; - }; - - template<unsigned bits> struct uint_for_size; - template<> struct uint_for_size<1> { using type = uint_least8_t; }; - template<> struct uint_for_size<2> { using type = uint_least16_t; }; - template<> struct uint_for_size<4> { using type = uint_least32_t; }; - template<> struct uint_for_size<8> { using type = uint_least64_t; }; - - template<std::size_t NUM, typename R> - struct aa - { - template<typename T> - R f(T &arr, const R ign) - { - R r = aa<NUM-1, R>().f(arr, ign); - if (ign & (1 << (NUM-1))) - arr[NUM-1].activate(); - return r | (arr[NUM-1]() << (NUM-1)); - } - }; - - template<typename R> - struct aa<1, R> - { - template<typename T> - R f(T &arr, const R ign) - { - if ((ign & 1)) - arr[0].activate(); - return arr[0](); - } - }; - - template<std::size_t m_NI, std::size_t m_NO> - NETLIB_OBJECT(truthtable_t) - { - private: - detail::family_setter_t m_fam; - public: - - using type_t = typename uint_for_size<need_bytes_for_bits<m_NO + m_NI>::value>::type; - - static constexpr const std::size_t m_num_bits = m_NI; - static constexpr const std::size_t m_size = (1 << (m_num_bits)); - static constexpr const type_t m_outmask = ((1 << m_NO) - 1); - - struct truthtable_t - { - truthtable_t() - : m_timing_index{0} - , m_initialized(false) - {} - - std::array<type_t, m_size> m_out_state; - std::array<uint_least8_t, m_size * m_NO> m_timing_index; - std::array<netlist_time, 16> m_timing_nt; - bool m_initialized; - }; +#include "../nl_setup.h" +#include "nl_factory.h" - template <class C> - nld_truthtable_t(C &owner, const pstring &name, - const logic_family_desc_t *fam, - truthtable_t &ttp, const std::vector<pstring> &desc) - : device_t(owner, name) - , m_fam(*this, fam) - , m_ign(*this, "m_ign", 0) - , m_ttp(ttp) - /* FIXME: the family should provide the names of the power-terminals! */ - , m_power_pins(*this) - { - init(desc); - } +namespace netlist::factory { - void init(const std::vector<pstring> &desc); - - NETLIB_RESETI() - { - int active_outputs = 0; - m_ign = 0; - for (auto &i : m_I) - i.activate(); - for (auto &q : m_Q) - if (q.has_net() && q.net().num_cons() > 0) - active_outputs++; - set_active_outputs(active_outputs); - } - - NETLIB_UPDATEI() - { - process<true>(); - } - - void inc_active() NL_NOEXCEPT override - { - process<false>(); - } - - void dec_active() NL_NOEXCEPT override - { - for (std::size_t i = 0; i< m_NI; i++) - m_I[i].inactivate(); - m_ign = (1<<m_NI)-1; - } - - plib::uninitialised_array_t<logic_input_t, m_NI> m_I; - plib::uninitialised_array_t<logic_output_t, m_NO> m_Q; - - protected: - - private: - - template<bool doOUT> - void process() - { - netlist_time mt(netlist_time::zero()); - - type_t nstate(0); - type_t ign(m_ign); -#if 1 - if (!doOUT) - for (std::size_t i = 0; i < m_NI; i++) - { - m_I[i].activate(); - //nstate |= (m_I[i]() ? (1 << i) : 0); - nstate |= (m_I[i]() << i); - mt = std::max(this->m_I[i].net().next_scheduled_time(), mt); - } - else - for (std::size_t i = 0; i < m_NI; i++) - { - if ((ign & 1)) - m_I[i].activate(); - //nstate |= (m_I[i]() ? (1 << i) : 0); - nstate |= (m_I[i]() << i); - ign >>= 1; - } -#else - if (!doOUT) - { - nstate = aa<m_NI, type_t>().f(m_I, ~0); - for (std::size_t i = 0; i < m_NI; i++) - mt = std::max(this->m_I[i].net().time(), mt); - } - else - nstate = aa<m_NI, type_t>().f(m_I, ign); -#endif - - const type_t outstate(m_ttp.m_out_state[nstate]); - type_t out(outstate & m_outmask); - - m_ign = outstate >> m_NO; - - const std::size_t timebase(nstate * m_NO); - const auto *t(&m_ttp.m_timing_index[timebase]); - const auto *tim = m_ttp.m_timing_nt.data(); - - if (doOUT) - for (std::size_t i = 0; i < m_NO; out >>= 1, ++i) - m_Q[i].push(out & 1, tim[t[i]]); - else - for (std::size_t i = 0; i < m_NO; out >>= 1, ++i) - m_Q[i].set_Q_time(out & 1, mt + tim[t[i]]); - - ign = m_ign; - for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I) - if (ign & 1) - I->inactivate(); - } - - /* FIXME: check width */ - state_var<type_t> m_ign; - const truthtable_t &m_ttp; - /* FIXME: the family should provide the names of the power-terminals! */ - nld_power_pins m_power_pins; - }; - - class netlist_base_factory_truthtable_t : public factory::element_t + class truth_table_base_element_t : public factory::element_t { public: - netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname, - const pstring &def_param, const pstring &sourcefile); + truth_table_base_element_t(const pstring &name,properties &&props); std::vector<pstring> m_desc; pstring m_family_name; - const logic_family_desc_t *m_family_desc; }; - /* the returned element is still missing a pointer to the family ... */ - plib::unique_ptr<netlist_base_factory_truthtable_t> tt_factory_create(tt_desc &desc, const pstring &sourcefile); - -} //namespace devices -} // namespace netlist - + host_arena::unique_ptr<truth_table_base_element_t> truth_table_create(tt_desc &desc, + properties &&props); +} // namespace netlist::factory -#endif /* NLID_TRUTHTABLE_H_ */ +#endif // NLID_TRUTHTABLE_H_ |