summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/devices')
-rw-r--r--src/lib/netlist/devices/net_lib.cpp177
-rw-r--r--src/lib/netlist/devices/net_lib.h118
-rw-r--r--src/lib/netlist/devices/nld_2102A.cpp111
-rw-r--r--src/lib/netlist/devices/nld_2102A.h50
-rw-r--r--src/lib/netlist/devices/nld_2102a.cpp91
-rw-r--r--src/lib/netlist/devices/nld_2716.cpp105
-rw-r--r--src/lib/netlist/devices/nld_2716.h54
-rw-r--r--src/lib/netlist/devices/nld_4006.cpp114
-rw-r--r--src/lib/netlist/devices/nld_4013.cpp122
-rw-r--r--src/lib/netlist/devices/nld_4017.cpp113
-rw-r--r--src/lib/netlist/devices/nld_4020.cpp183
-rw-r--r--src/lib/netlist/devices/nld_4020.h43
-rw-r--r--src/lib/netlist/devices/nld_4029.cpp268
-rw-r--r--src/lib/netlist/devices/nld_4042.cpp116
-rw-r--r--src/lib/netlist/devices/nld_4053.cpp142
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp117
-rw-r--r--src/lib/netlist/devices/nld_4066.h34
-rw-r--r--src/lib/netlist/devices/nld_4076.cpp127
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp87
-rw-r--r--src/lib/netlist/devices/nld_4316.h33
-rw-r--r--src/lib/netlist/devices/nld_74107.cpp238
-rw-r--r--src/lib/netlist/devices/nld_74107.h87
-rw-r--r--src/lib/netlist/devices/nld_74113.cpp142
-rw-r--r--src/lib/netlist/devices/nld_74123.cpp483
-rw-r--r--src/lib/netlist/devices/nld_74123.h74
-rw-r--r--src/lib/netlist/devices/nld_74125.cpp77
-rw-r--r--src/lib/netlist/devices/nld_74153.cpp113
-rw-r--r--src/lib/netlist/devices/nld_74153.h65
-rw-r--r--src/lib/netlist/devices/nld_74161.cpp143
-rw-r--r--src/lib/netlist/devices/nld_74161.h47
-rw-r--r--src/lib/netlist/devices/nld_74163.cpp24
-rw-r--r--src/lib/netlist/devices/nld_74164.cpp158
-rw-r--r--src/lib/netlist/devices/nld_74164.h59
-rw-r--r--src/lib/netlist/devices/nld_74165.cpp142
-rw-r--r--src/lib/netlist/devices/nld_74165.h52
-rw-r--r--src/lib/netlist/devices/nld_74166.cpp176
-rw-r--r--src/lib/netlist/devices/nld_74166.h53
-rw-r--r--src/lib/netlist/devices/nld_74174.cpp155
-rw-r--r--src/lib/netlist/devices/nld_74174.h58
-rw-r--r--src/lib/netlist/devices/nld_74175.cpp173
-rw-r--r--src/lib/netlist/devices/nld_74175.h56
-rw-r--r--src/lib/netlist/devices/nld_74192.cpp204
-rw-r--r--src/lib/netlist/devices/nld_74192.h50
-rw-r--r--src/lib/netlist/devices/nld_74193.cpp205
-rw-r--r--src/lib/netlist/devices/nld_74193.h47
-rw-r--r--src/lib/netlist/devices/nld_74194.cpp173
-rw-r--r--src/lib/netlist/devices/nld_74194.h49
-rw-r--r--src/lib/netlist/devices/nld_74365.cpp93
-rw-r--r--src/lib/netlist/devices/nld_74365.h46
-rw-r--r--src/lib/netlist/devices/nld_74377.cpp101
-rw-r--r--src/lib/netlist/devices/nld_74393.cpp88
-rw-r--r--src/lib/netlist/devices/nld_7448.cpp194
-rw-r--r--src/lib/netlist/devices/nld_7448.h49
-rw-r--r--src/lib/netlist/devices/nld_7450.cpp149
-rw-r--r--src/lib/netlist/devices/nld_7450.h41
-rw-r--r--src/lib/netlist/devices/nld_7473.cpp225
-rw-r--r--src/lib/netlist/devices/nld_7473.h84
-rw-r--r--src/lib/netlist/devices/nld_7474.cpp166
-rw-r--r--src/lib/netlist/devices/nld_7474.h59
-rw-r--r--src/lib/netlist/devices/nld_7475.cpp196
-rw-r--r--src/lib/netlist/devices/nld_7475.h64
-rw-r--r--src/lib/netlist/devices/nld_7483.cpp151
-rw-r--r--src/lib/netlist/devices/nld_7483.h49
-rw-r--r--src/lib/netlist/devices/nld_7485.cpp143
-rw-r--r--src/lib/netlist/devices/nld_7485.h47
-rw-r--r--src/lib/netlist/devices/nld_7490.cpp205
-rw-r--r--src/lib/netlist/devices/nld_7490.h74
-rw-r--r--src/lib/netlist/devices/nld_7492.cpp135
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp142
-rw-r--r--src/lib/netlist/devices/nld_7493.h74
-rw-r--r--src/lib/netlist/devices/nld_7497.cpp215
-rw-r--r--src/lib/netlist/devices/nld_7497.h59
-rw-r--r--src/lib/netlist/devices/nld_74ls629.cpp282
-rw-r--r--src/lib/netlist/devices/nld_74ls629.h42
-rw-r--r--src/lib/netlist/devices/nld_8277.cpp166
-rw-r--r--src/lib/netlist/devices/nld_82S115.cpp119
-rw-r--r--src/lib/netlist/devices/nld_82S115.h53
-rw-r--r--src/lib/netlist/devices/nld_82S123.cpp88
-rw-r--r--src/lib/netlist/devices/nld_82S123.h44
-rw-r--r--src/lib/netlist/devices/nld_82S126.cpp92
-rw-r--r--src/lib/netlist/devices/nld_82S126.h47
-rw-r--r--src/lib/netlist/devices/nld_82S16.cpp143
-rw-r--r--src/lib/netlist/devices/nld_82S16.h34
-rw-r--r--src/lib/netlist/devices/nld_82s115.cpp94
-rw-r--r--src/lib/netlist/devices/nld_82s16.cpp124
-rw-r--r--src/lib/netlist/devices/nld_9310.cpp225
-rw-r--r--src/lib/netlist/devices/nld_9310.h67
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp217
-rw-r--r--src/lib/netlist/devices/nld_9316.h73
-rw-r--r--src/lib/netlist/devices/nld_9316_base.hxx155
-rw-r--r--src/lib/netlist/devices/nld_9321.cpp66
-rw-r--r--src/lib/netlist/devices/nld_9322.cpp153
-rw-r--r--src/lib/netlist/devices/nld_9322.h44
-rw-r--r--src/lib/netlist/devices/nld_am2847.cpp167
-rw-r--r--src/lib/netlist/devices/nld_am2847.h43
-rw-r--r--src/lib/netlist/devices/nld_dm9314.cpp156
-rw-r--r--src/lib/netlist/devices/nld_dm9314.h44
-rw-r--r--src/lib/netlist/devices/nld_dm9334.cpp243
-rw-r--r--src/lib/netlist/devices/nld_dm9334.h84
-rw-r--r--src/lib/netlist/devices/nld_legacy.cpp104
-rw-r--r--src/lib/netlist/devices/nld_legacy.h39
-rw-r--r--src/lib/netlist/devices/nld_log.cpp142
-rw-r--r--src/lib/netlist/devices/nld_log.h32
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp172
-rw-r--r--src/lib/netlist/devices/nld_mm5837.h27
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp286
-rw-r--r--src/lib/netlist/devices/nld_ne555.h21
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.cpp97
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.h57
-rw-r--r--src/lib/netlist/devices/nld_roms.cpp311
-rw-r--r--src/lib/netlist/devices/nld_schmitt.cpp195
-rw-r--r--src/lib/netlist/devices/nld_schmitt.h25
-rw-r--r--src/lib/netlist/devices/nld_system.cpp242
-rw-r--r--src/lib/netlist/devices/nld_system.h77
-rw-r--r--src/lib/netlist/devices/nld_tms4800.cpp133
-rw-r--r--src/lib/netlist/devices/nld_tms4800.h53
-rw-r--r--src/lib/netlist/devices/nld_tristate.cpp77
-rw-r--r--src/lib/netlist/devices/nld_tristate.h31
-rw-r--r--src/lib/netlist/devices/nlid_cmos.h41
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp263
-rw-r--r--src/lib/netlist/devices/nlid_proxy.h118
-rw-r--r--src/lib/netlist/devices/nlid_system.h718
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp762
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.h226
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_