summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-05-17 15:17:20 +0200
committer couriersud <couriersud@gmx.org>2020-05-17 19:52:09 +0200
commit22fb995337f7f1d666f411c15873c7fe858e022f (patch)
tree23d551612dcec40d44de58bd9fca7436143518f8 /src
parent7d8384419f05006e8971aaf7727bbadf03a0cd32 (diff)
netlist: Add working 74125 and 74126 implementations. [Couriersud]
These tristate buffers natively support tristate outputs. For use cases with fixed enable inputs the devices support a parameter FORCE_TRISTATE_LOGIC which if being set to 1 makes the device behave like a logic output. Added additional syntax and consistency checks for tristate outputs. Updated the example and added dip implementations including documentation.
Diffstat (limited to 'src')
-rw-r--r--src/lib/netlist/devices/net_lib.h1
-rw-r--r--src/lib/netlist/devices/nld_74125.cpp90
-rw-r--r--src/lib/netlist/devices/nld_74125.h81
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp40
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp25
-rw-r--r--src/lib/netlist/devices/nld_roms.cpp36
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp2
-rw-r--r--src/lib/netlist/examples/74125.cpp8
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.cpp97
-rw-r--r--src/lib/netlist/nl_base.cpp13
-rw-r--r--src/lib/netlist/nl_base.h154
-rw-r--r--src/lib/netlist/nl_errstr.h9
-rwxr-xr-xsrc/lib/netlist/nl_setup.cpp22
-rw-r--r--src/lib/netlist/nltypes.h50
14 files changed, 321 insertions, 307 deletions
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index 9d36c9a48ad..decca40aac7 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -54,6 +54,7 @@
#include "nld_4316.h"
#include "nld_74107.h"
#include "nld_74123.h"
+#include "nld_74125.h"
#include "nld_74153.h"
#include "nld_74161.h"
#include "nld_74164.h"
diff --git a/src/lib/netlist/devices/nld_74125.cpp b/src/lib/netlist/devices/nld_74125.cpp
index bac94c18d22..92a800d7038 100644
--- a/src/lib/netlist/devices/nld_74125.cpp
+++ b/src/lib/netlist/devices/nld_74125.cpp
@@ -1,13 +1,15 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
- * nld_74125.c
+ * nld_74125.cpp
*
*/
#include "nld_74125.h"
#include "nl_base.h"
+#include <type_traits>
+
namespace netlist
{
template <typename T>
@@ -17,16 +19,9 @@ namespace netlist
using base_type = unique_pool_ptr<T>;
- template<typename O, typename... Args, class = typename std::enable_if<
- std::is_base_of<core_device_t, O>::value>::type>
- uptr(O &owner, const pstring &name, Args&&... args)
- : unique_pool_ptr<T>(static_cast<core_device_t &>(owner).state().make_object<T>(owner, name, std::forward<Args>(args)...))
- { }
-
template<typename O, typename... Args>
- uptr(typename std::enable_if<
- std::is_base_of<netlist_state_t, O>::value, O>::type &owner, const pstring &name, Args&&... args)
- : unique_pool_ptr<T>(static_cast<netlist_state_t>(owner).make_object<T>(owner, name, std::forward<Args>(args)...))
+ uptr(O &owner, const pstring &name, Args&&... args)
+ : unique_pool_ptr<T>(owner.template make_object<T>(owner, name, std::forward<Args>(args)...))
{ }
C14CONSTEXPR auto operator ()() noexcept -> decltype((*unique_pool_ptr<T>::get())()) { return (*this->get())(); }
@@ -36,13 +31,15 @@ namespace netlist
namespace devices
{
- template <netlist_sig_t INVERT_G>
+ template <typename D>
NETLIB_OBJECT(74125_base)
{
NETLIB_CONSTRUCTOR(74125_base)
+ , m_TE(*this, "FORCE_TRISTATE_LOGIC", 0)
, m_A(*this, "A", NETLIB_DELEGATE(74125_base, A))
- , m_G(*this, "G", NETLIB_DELEGATE(74125_base, G))
- , m_Y(*this, "Y", NLTIME_FROM_NS(11), NLTIME_FROM_NS(13))
+ , m_G(*this, pstring(D::invert_g::value ? "GQ" : "G"), NETLIB_DELEGATE(74125_base, G))
+ , m_Y(*this, "Y", m_TE())
+ //, m_Y(*this, "Y")
, m_power_pins(*this)
{
}
@@ -56,67 +53,48 @@ namespace netlist
{
// this one is only called during startup. Ensure all outputs
// are in a consistent state.
- m_Y.set_tristate(m_G() ^ INVERT_G);
- m_Y.push(m_A(), m_A() ? NLTIME_FROM_NS(8) : NLTIME_FROM_NS(12));
+ 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() ? NLTIME_FROM_NS(8) : NLTIME_FROM_NS(12));
+ 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() ^ INVERT_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;
uptr<logic_input_t> m_G;
tristate_output_t m_Y;
nld_power_pins m_power_pins;
};
-#if 0
- template <bool ASYNC>
- NETLIB_OBJECT(74125_dip_base)
+ struct desc_74125
{
- NETLIB_CONSTRUCTOR(74125_dip_base)
- , A(*this, "A")
- {
- this->register_subalias("1", "A.CLRQ");
- this->register_subalias("2", "A.CLK");
- this->register_subalias("3", "A.A");
- this->register_subalias("4", "A.B");
- this->register_subalias("5", "A.C");
- this->register_subalias("6", "A.D");
- this->register_subalias("7", "A.ENP");
- this->register_subalias("8", "A.GND");
-
- this->register_subalias("9", "A.LOADQ");
- this->register_subalias("10", "A.ENT");
- this->register_subalias("11", "A.QD");
- this->register_subalias("12", "A.QC");
- this->register_subalias("13", "A.QB");
- this->register_subalias("14", "A.QA");
- this->register_subalias("15", "A.RC");
- this->register_subalias("16", "A.VCC");
- }
- private:
- NETLIB_SUB(74125_base)<ASYNC> A;
+ using invert_g = desc_const<1>;
+ 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<0>;
};
- using NETLIB_NAME(74163) = NETLIB_NAME(74125_base)<false>;
- using NETLIB_NAME(74125_dip) = NETLIB_NAME(74125_dip_base)<true>;
- using NETLIB_NAME(74163_dip) = NETLIB_NAME(74125_dip_base)<false>;
- NETLIB_DEVICE_IMPL(74125_dip, "TTL_74125_DIP", "")
-
- NETLIB_DEVICE_IMPL(74163, "TTL_74163", "+CLK,+ENP,+ENT,+CLRQ,+LOADQ,+A,+B,+C,+D,@VCC,@GND")
- NETLIB_DEVICE_IMPL(74163_dip, "TTL_74163_DIP", "")
-#endif
- using NETLIB_NAME(74125) = NETLIB_NAME(74125_base)<1>;
- using NETLIB_NAME(74126) = NETLIB_NAME(74125_base)<0>;
-
- NETLIB_DEVICE_IMPL(74125, "TTL_74125", "")
- NETLIB_DEVICE_IMPL(74126, "TTL_74126", "")
+
+ 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 devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74125.h b/src/lib/netlist/devices/nld_74125.h
index 38f9f245a9a..d192d776977 100644
--- a/src/lib/netlist/devices/nld_74125.h
+++ b/src/lib/netlist/devices/nld_74125.h
@@ -3,49 +3,6 @@
/*
* nld_74125.h
*
- * DM74125: Synchronous 4-Bit Counters
- *
- * +--------------+
- * /CLEAR |1 ++ 16| VCC
- * CLOCK |2 15| RC (Ripple Carry)
- * A |3 14| QA
- * B |4 74125 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 DM74125 (both asynchronous clear)
- * DM74163 has asynchronous clear (on L to H transition of clock)
*/
#ifndef NLD_74125_H_
@@ -53,40 +10,10 @@
#include "netlist/nl_setup.h"
-#if 0
-#define TTL_74125(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \
- NET_REGISTER_DEV(TTL_74125, 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_74163(name, cCLK, cENP, cENT, cCLRQ, cLOADQ, cA, cB, cC, cD) \
- NET_REGISTER_DEV(TTL_74163, 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_74125_DIP(name) \
- NET_REGISTER_DEV(TTL_74125_DIP, name)
+#define TTL_74125_GATE(...) \
+ NET_REGISTER_DEV(TTL_74125_GATE, __VA_ARGS__)
-#define TTL_74163_DIP(name) \
- NET_REGISTER_DEV(TTL_74163_DIP, name)
-#endif
+#define TTL_74126_GATE(...) \
+ NET_REGISTER_DEV(TTL_74126_GATE, __VA_ARGS__)
#endif /* NLD_74125_H_ */
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index a6879ff6f47..7404370205c 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -31,9 +31,7 @@ namespace netlist
, m_ABCD(*this, {"A", "B", "C", "D"}, NETLIB_DELEGATE(9316_base, 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_abcd(*this, "m_abcd", 0)
, m_power_pins(*this)
{
}
@@ -43,16 +41,14 @@ namespace netlist
{
m_CLK.set_state(logic_t::STATE_INP_LH);
m_cnt = 0;
- m_abcd = 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())) && (!ASYNC || CLRQ))
+ if (((m_LOADQ() ^ 1) || (m_ENT() && m_ENP())) && (!ASYNC || CLRQ))
{
m_CLK.activate_lh();
}
@@ -61,11 +57,11 @@ namespace netlist
m_CLK.inactivate();
if (ASYNC && !CLRQ && (m_cnt>0))
{
- update_outputs_all(0, NLTIME_FROM_NS(36));
m_cnt = 0;
+ m_Q.push(m_cnt, NLTIME_FROM_NS(36));
}
}
- m_RC.push(m_ent && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ m_RC.push(m_ENT() && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
}
@@ -73,21 +69,22 @@ namespace netlist
{
if (!ASYNC && !m_CLRQ())
{
- update_outputs_all(0, NLTIME_FROM_NS(36));
- m_cnt = 0;
+ m_cnt = 0;
+ m_Q.push(m_cnt, NLTIME_FROM_NS(36));
}
else
{
- 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;
+ //const auto cnt = (m_LOADQ() ? (m_cnt + 1) & MAXCNT: m_abcd);
+ const auto cnt = (m_LOADQ() ? (m_cnt + 1) & MAXCNT: m_ABCD());
+ m_RC.push(m_ENT() && (cnt == MAXCNT), NLTIME_FROM_NS(27));
+ m_Q.push(cnt, NLTIME_FROM_NS(20));
+ m_cnt = static_cast<unsigned>(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));
+ //m_abcd = static_cast<unsigned>(m_ABCD());
}
logic_input_t m_CLK;
@@ -106,18 +103,9 @@ namespace netlist
/* counter state */
state_var<unsigned> m_cnt;
/* cached pins */
- state_var<unsigned> m_abcd;
- state_var_sig m_loadq;
- state_var_sig m_ent;
+ //state_var<unsigned> m_abcd;
nld_power_pins m_power_pins;
- 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);
- }
};
template <bool ASYNC>
diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp
index ae8cb1b0d52..f77d2302955 100644
--- a/src/lib/netlist/devices/nld_ne555.cpp
+++ b/src/lib/netlist/devices/nld_ne555.cpp
@@ -115,7 +115,7 @@ namespace netlist
return ret;
}
};
-#if 1
+
NETLIB_OBJECT(NE555_dip)
{
NETLIB_CONSTRUCTOR(NE555_dip)
@@ -138,32 +138,9 @@ namespace netlist
private:
NETLIB_SUB(NE555) A;
};
-#else
- NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
- {
- NETLIB_CONSTRUCTOR_DERIVED(NE555_dip)
- {
- 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
- }
- };
-#endif
NETLIB_RESET(NE555)
{
-#if 0
- m_R1.reset();
- m_R2.reset();
- m_R3.reset();
- m_ROUT.reset();
- m_RDIS.reset();
-#endif
/* FIXME make resistances a parameter, properly model other variants */
m_R1.set_R(nlconst::magic(5000));
m_R2.set_R(nlconst::magic(5000));
diff --git a/src/lib/netlist/devices/nld_roms.cpp b/src/lib/netlist/devices/nld_roms.cpp
index 5a7bc9fa59b..47adbc9d9fa 100644
--- a/src/lib/netlist/devices/nld_roms.cpp
+++ b/src/lib/netlist/devices/nld_roms.cpp
@@ -25,42 +25,6 @@ namespace netlist
namespace devices
{
- template<netlist_time::internal_type value0>
- struct times_ns1
- {
- static constexpr netlist_time value(std::size_t N = 0)
- {
- plib::unused_var(N);
- return NLTIME_FROM_NS(value0);
- }
- };
-
- template <netlist_time::internal_type value0>
- using time_ns = times_ns1<value0>;
-
- template<netlist_time::internal_type value0,
- netlist_time::internal_type value1>
- struct times_ns2
- {
- static constexpr netlist_time value(std::size_t N)
- {
- return NLTIME_FROM_NS(N == 0 ? value0 : value1);
- }
- };
-
- template<netlist_time::internal_type value0,
- netlist_time::internal_type value1,
- netlist_time::internal_type value2>
- struct times_ns3
- {
- static constexpr netlist_time value(std::size_t N)
- {
- return NLTIME_FROM_NS(N == 0 ? value0 :
- N == 1 ? value1 :
- value2);
- }
- };
-
template <typename D>
NETLIB_OBJECT(generic_prom)
{
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index fb0ba84c5a8..74ba40f5fe3 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -187,7 +187,7 @@ namespace netlist
nlconst::zero());
break;
default:
- printf("this should never happen!");
+ throw nl_exception("unknown state for proxy: this should never happen! %d\n", static_cast<int>(state));
}
});
m_last_state = state;
diff --git a/src/lib/netlist/examples/74125.cpp b/src/lib/netlist/examples/74125.cpp
index 807d8bf27c8..640e2bd8b86 100644
--- a/src/lib/netlist/examples/74125.cpp
+++ b/src/lib/netlist/examples/74125.cpp
@@ -18,8 +18,9 @@ NETLIST_START(main)
ANALOG_INPUT(VCC, 5.0)
- TTL_74125(X1)
- TTL_74126(X2)
+ TTL_74125_GATE(X1)
+ TTL_74126_GATE(X2)
+ PARAM(X2.FORCE_TRISTATE_LOGIC, 0)
CLOCK(C1, 100)
CLOCK(C2, 300)
@@ -29,9 +30,10 @@ NETLIST_START(main)
NET_C(C1.Q, X1.A)
NET_C(C2.Q, X2.A)
- NET_C(C3.Q, X1.G, X2.G)
+ NET_C(C3.Q, X1.GQ, X2.G)
NET_C(X1.Y, X2.Y, RL.1)
+ //NET_C(X1.Y, RL.1)
NET_C(GND, RL.2, C1.GND, C2.GND, C3.GND, X1.GND, X2.GND)
NET_C(VCC, C1.VCC, C2.VCC, C3.VCC, X1.VCC, X2.VCC)
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index 8485ce86c86..28c8daf6fe8 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -694,6 +694,101 @@ NETLIST_END()
*
*/
+//- Identifier: TTL_74125_DIP
+//- Title: SN74125 QUADRUPLE BUS BUFFERS WITH 3-STATE OUTPUTS
+//- Description: These bus buffers feature three-state outputs
+//- that, when enabled, have the low impedance characteristics of a
+//- TTL output with additional drive capability at high logic levels
+//- to permit driving heavily loaded bus lines without external
+//- pullup resistors. When disabled, both output transistors are turned
+//- off, presenting a high-impedance state to the bus so the output will
+//- act neither as a significant load nor as a driver. The ’125 and
+//- ’LS125A devices’ outputs are disabled when G is high.
+//- The ’126 and ’LS126A devices’ outputs are disabled when G is low
+//-
+//- Pinalias: 1GQ,1A,1Y,2GQ,2A,2Y,GND,3Y,3A,3GQ,4Y,4A,4GQ,VCC
+//- Package: DIP
+//- NamingConvention: Naming conventions follow Texas instruments datasheet
+//- Limitations:
+//- No limitations
+//-
+//- Example: 74125.cpp,74125_example
+//-
+//- FunctionTable:
+//-
+//- | GQ | A | Y |
+//- |:---:|:--:|:--:|
+//- | L | L | L |
+//- | L | H | H |
+//- | H | X | Z |
+//-
+
+static NETLIST_START(TTL_74125_DIP)
+
+ TTL_74125_GATE(A1)
+ TTL_74125_GATE(A2)
+ TTL_74125_GATE(A3)
+ TTL_74125_GATE(A4)
+
+ DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
+ PARAM(A1.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A2.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A3.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A4.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+
+ ALIAS(1, A1.GQ)
+ ALIAS(2, A1.A)
+ ALIAS(3, A1.Y)
+ ALIAS(4, A2.GQ)
+ ALIAS(5, A2.A)
+ ALIAS(6, A2.Y)
+ ALIAS(7, A1.GND)
+
+ ALIAS(8, A3.Y)
+ ALIAS(9, A3.A)
+ ALIAS(10, A3.GQ)
+ ALIAS(11, A4.Y)
+ ALIAS(12, A4.A)
+ ALIAS(13, A4.GQ)
+ ALIAS(14, A1.VCC)
+
+ NET_C(A1.VCC, A2.VCC, A3.VCC, A4.VCC)
+ NET_C(A1.GND, A2.GND, A3.GND, A4.GND)
+NETLIST_END()
+
+static NETLIST_START(TTL_74126_DIP)
+
+ TTL_74126_GATE(A1)
+ TTL_74126_GATE(A2)
+ TTL_74126_GATE(A3)
+ TTL_74126_GATE(A4)
+
+ DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
+ PARAM(A1.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A2.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A3.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+ PARAM(A4.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
+
+ ALIAS(1, A1.G)
+ ALIAS(2, A1.A)
+ ALIAS(3, A1.Y)
+ ALIAS(4, A2.G)
+ ALIAS(5, A2.A)
+ ALIAS(6, A2.Y)
+ ALIAS(7, A1.GND)
+
+ ALIAS(8, A3.Y)
+ ALIAS(9, A3.A)
+ ALIAS(10, A3.G)
+ ALIAS(11, A4.Y)
+ ALIAS(12, A4.A)
+ ALIAS(13, A4.G)
+ ALIAS(14, A1.VCC)
+
+ NET_C(A1.VCC, A2.VCC, A3.VCC, A4.VCC)
+ NET_C(A1.GND, A2.GND, A3.GND, A4.GND)
+NETLIST_END()
+
static NETLIST_START(TTL_74155_DIP)
NET_REGISTER_DEV(TTL_74155A_GATE, A)
NET_REGISTER_DEV(TTL_74155B_GATE, B)
@@ -1514,6 +1609,8 @@ NETLIST_START(TTL74XX_lib)
LOCAL_LIB_ENTRY(TTL_7448_DIP)
#endif
LOCAL_LIB_ENTRY(TTL_7486_DIP)
+ LOCAL_LIB_ENTRY(TTL_74125_DIP)
+ LOCAL_LIB_ENTRY(TTL_74126_DIP)
#if (NL_USE_TRUTHTABLE_74107)
LOCAL_LIB_ENTRY(TTL_74107_DIP)
#endif
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 3da7fa70ba9..f0e3516ea68 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -77,14 +77,6 @@ namespace netlist
}
}
-#if 0
- // ----------------------------------------------------------------------------------------
- // netlist_ref_t
- // ----------------------------------------------------------------------------------------
-
- detail::netlist_ref::netlist_ref(netlist_t &nl)
- : m_netlist(nl) { }
-#endif
// ----------------------------------------------------------------------------------------
// device_object_t
// ----------------------------------------------------------------------------------------
@@ -907,6 +899,11 @@ namespace netlist
return dynamic_cast<const logic_output_t *>(this) != nullptr;
}
+ bool detail::core_terminal_t::is_tristate_output() const noexcept
+ {
+ return dynamic_cast<const tristate_output_t *>(this) != nullptr;
+ }
+
bool detail::core_terminal_t::is_analog() const noexcept
{
return dynamic_cast<const analog_t *>(this) != nullptr;
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 6d52fed38ea..5f4a576207d 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -565,6 +565,10 @@ namespace netlist
netlist_t & exec() noexcept { return m_netlist; }
const netlist_t & exec() const noexcept { return m_netlist; }
+ // to ease template design
+ template<typename T, typename... Args>
+ unique_pool_ptr<T> make_object(Args&&... args);
+
private:
netlist_t & m_netlist;
@@ -672,6 +676,7 @@ namespace netlist
bool is_logic() const noexcept;
bool is_logic_input() const noexcept;
bool is_logic_output() const noexcept;
+ bool is_tristate_output() const noexcept;
bool is_analog() const noexcept;
bool is_analog_input() const noexcept;
bool is_analog_output() const noexcept;
@@ -1024,17 +1029,28 @@ namespace netlist
// tristate_output_t
// -----------------------------------------------------------------------------
+ /// \brief Tristate output
+ ///
+ /// In a lot of applications tristate enable inputs are just connected to
+ /// VCC/GND to permanently enable the outputs. In this case a pure
+ /// implementation using analog outputs would not perform well.
+ ///
+ /// For this object during creation it can be decided if a logic output or
+ /// a tristate output is used. Generally the owning device uses parameter
+ /// FORCE_TRISTATE_LOGIC to determine this.
+ ///
+ /// This is the preferred way to implement tristate outputs.
+ ///
+
class tristate_output_t : public logic_output_t
{
public:
- tristate_output_t(device_t &dev, const pstring &aname,
- netlist_time ts_off_on, netlist_time ts_on_off)
+ tristate_output_t(device_t &dev, const pstring &aname, bool force_logic)
: logic_output_t(dev, aname)
- , m_last_logic(dev, name() + "." + "m_last_logic", 2) // force change
+ , m_last_logic(dev, name() + "." + "m_last_logic", 1) // force change
, m_tristate(dev, name() + "." + "m_tristate", 2) // force change
- , m_ts_off_on(ts_off_on)
- , m_ts_on_off(ts_on_off)
+ , m_force_logic(force_logic)
{}
void push(netlist_sig_t newQ, netlist_time delay) noexcept
@@ -1044,13 +1060,21 @@ namespace netlist
m_last_logic = newQ;
}
- void set_tristate(bool v) noexcept
+ void set_tristate(bool v,
+ netlist_time ts_off_on, netlist_time ts_on_off) noexcept
{
- if (v != m_tristate)
- {
- logic_output_t::push(v ? OUT_TRISTATE() : m_last_logic, v ? m_ts_off_on : m_ts_on_off);
- m_tristate = v;
- }
+ //printf("%s %d\n", this->name().c_str(), (int) m_force_logic);
+ if (!m_force_logic)
+ if (v != m_tristate)
+ {
+ logic_output_t::push(v ? OUT_TRISTATE() : m_last_logic, v ? ts_off_on : ts_on_off);
+ m_tristate = v;
+ }
+ }
+
+ bool is_force_logic() const noexcept
+ {
+ return m_force_logic;
}
private:
@@ -1058,9 +1082,10 @@ namespace netlist
using logic_output_t::set_Q_time;
state_var<netlist_sig_t> m_last_logic;
state_var<netlist_sig_t> m_tristate;
- const netlist_time m_ts_off_on;
- const netlist_time m_ts_on_off;
+ bool m_force_logic;
};
+
+
// -----------------------------------------------------------------------------
// analog_output_t
// -----------------------------------------------------------------------------
@@ -1893,33 +1918,6 @@ namespace netlist
this->emplace(i++, dev, pstring(n), std::forward<Args>(args)...);
}
-#if 0
- template<class D, typename... Args>
- object_array_base_t(D &dev, const pstring &fmt, Args&&... args)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, formatted(fmt, i), std::forward<Args>(args)...);
- }
-
- template<class D, typename... Args>
- object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, Args&&... args)
- {
- for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, formatted(fmt, i+offset), std::forward<Args>(args)...);
- }
-
- template<class D, typename... Args>
- object_array_base_t(D &dev, std::size_t offset, std::size_t qmask, const pstring &fmt, Args&&... args)
- {
- for (std::size_t i = 0; i<N; i++)
- {
- pstring name(formatted(fmt, i+offset));
- if ((qmask >> i) & 1)
- name += "Q";
- this->emplace(i, dev, name, std::forward<Args>(args)...);
- }
- }
-#else
template<class D>
object_array_base_t(D &dev, const pstring &fmt)
{
@@ -1954,7 +1952,6 @@ namespace netlist
}
protected:
object_array_base_t() = default;
-#endif
protected:
static pstring formatted(const pstring &fmt, std::size_t n)
@@ -2002,27 +1999,33 @@ namespace netlist
}
- using value_type = typename plib::least_type_for_bits<N>::type;
+ //using value_type = typename plib::least_type_for_bits<N>::type;
+ using value_type = std::uint_fast32_t;
value_type operator ()()
{
- if (N <= 8)
- return tobits(N, *this);
- else
- {
- value_type r(0);
- for (std::size_t i = 0; i < N; i++)
- r = static_cast<value_type>((*this)[i]() << (N-1)) | (r >> 1);
- return r;
- }
+ if (N == 1) return e<0>();
+ if (N == 2) return e<0>() | (e<1>() << 1);
+ if (N == 3) return e<0>() | (e<1>() << 1) | (e<2>() << 2);
+ if (N == 4) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3);
+ if (N == 5) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4);
+ if (N == 6) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5);
+ if (N == 7) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6);
+ if (N == 8) return e<0>() | (e<1>() << 1) | (e<2>() << 2) | (e<3>() << 3)
+ | (e<4>() << 4) | (e<5>() << 5) | (e<6>() << 6) | (e<7>() << 7);
+
+ value_type r(0);
+ for (std::size_t i = 0; i < N; i++)
+ r = static_cast<value_type>((*this)[i]() << (N-1)) | (r >> 1);
+ return r;
}
private:
- template <typename T>
- static constexpr value_type tobits(std::size_t n, T &a)
- {
- return (n == 0 ? 0 : (tobits(n-1, a) | static_cast<value_type>(a[n-1]() << (n-1))));
- }
+ template <std::size_t P>
+ inline constexpr value_type e() const { return (*this)[P](); }
};
template<std::size_t N>
@@ -2032,30 +2035,22 @@ namespace netlist
using base_type = object_array_base_t<logic_output_t, N>;
using base_type::base_type;
- using value_type = typename plib::least_type_for_bits<N>::type;
+ using value_type = std::uint_fast32_t;
+ //using value_type = typename plib::least_type_for_bits<N>::type;
void push(value_type v, netlist_time t)
{
- if (N <= 8)
- rpush(N, *this, v, t);
- else
- {
- for (std::size_t i = 0; i < N; v = v >> 1, i++)
- (*this)[i].push(v & 1, t);
- }
- }
+ if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
+ if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
+ if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
+ if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
+ if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
+ if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
+ if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
+ if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
- private:
- template <typename A, typename V, typename X>
- static V rpush(std::size_t n, A &a, V value, X time)
- {
- if (n > 0)
- {
- value = rpush(n-1, a, value, time);
- a[n-1].push((value & 1), time);
- return value >> 1;
- }
- return value;
+ for (std::size_t i = 8; i < N; i++)
+ (*this)[i].push((v >> i) & 1, t);
}
};
@@ -2107,6 +2102,13 @@ namespace netlist
return m_netlist.nlstate();
}
+ template<typename T, typename... Args>
+ inline unique_pool_ptr<T> detail::netlist_object_t::make_object(Args&&... args)
+ {
+ return state().make_object<T>(std::forward<Args>(args)...);
+ }
+
+
inline void param_t::update_param() noexcept
{
device().update_param();
diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h
index 243b7c0812f..49fc786ee56 100644
--- a/src/lib/netlist/nl_errstr.h
+++ b/src/lib/netlist/nl_errstr.h
@@ -98,6 +98,15 @@ namespace netlist
PERRMSGV(ME_TERMINAL_1_WITHOUT_NET, 1, "Found terminal {1} without a net")
PERRMSGV(MF_TERMINALS_WITHOUT_NET, 0, "Found terminals without a net")
+ PERRMSGV(ME_TRISTATE_NO_PROXY_FOUND_2, 2,
+ "Tristate output {1} on device {2} is not connected to a proxy. You "
+ "need to set parameter FORCE_TRISTATE_LOGIC for device {2} if "
+ "tristate enable inputs are all connected to fixed inputs. If this "
+ "is not the case: Review your netlist. Something is wrong.")
+ PERRMSGV(ME_TRISTATE_PROXY_FOUND_2, 2,
+ "The tristate output {1} on device {2} is connected to an analog net "
+ "but has been forced to act as a logic output. Parameter "
+ " FORCE_TRISTATE_LOGIC for device {2} needs to be disabled!.")
PERRMSGV(MI_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3, 3, "Found device {1} connected only to railterminals {2}/{3}. Will be removed")
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 1fb515f346a..202bbc33f49 100755
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -1084,6 +1084,28 @@ void setup_t::resolve_inputs()
log().warning(MW_TERMINAL_1_WITHOUT_CONNECTIONS(term->name()));
}
}
+ log().verbose("checking tristate consistency ...");
+ for (auto & i : m_terminals)
+ {
+ detail::core_terminal_t *term = i.second;
+ if (term->is_tristate_output())
+ {
+ const auto *tri(static_cast<tristate_output_t *>(term));
+ // check if we are connected to a proxy
+ const auto iter_proxy(m_proxies.find(tri));
+
+ if (iter_proxy == m_proxies.end() && !tri->is_force_logic())
+ {
+ log().error(ME_TRISTATE_NO_PROXY_FOUND_2(term->name(), term->device().name()));
+ err = true;
+ }
+ else if (iter_proxy != m_proxies.end() && tri->is_force_logic())
+ {
+ log().error(ME_TRISTATE_PROXY_FOUND_2(term->name(), term->device().name()));
+ err = true;
+ }
+ }
+ }
if (err)
{
log().fatal(MF_TERMINALS_WITHOUT_NET());
diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h
index 03bb7e30fc0..2e1a4227177 100644
--- a/src/lib/netlist/nltypes.h
+++ b/src/lib/netlist/nltypes.h
@@ -162,6 +162,56 @@ namespace netlist
template <typename T> inline constexpr netlist_time NLTIME_FROM_US(T &&t) noexcept { return netlist_time::from_usec(t); }
template <typename T> inline constexpr netlist_time NLTIME_FROM_MS(T &&t) noexcept { return netlist_time::from_msec(t); }
+ /// \brief: used to hold one static netlist_time value
+ ///
+ template<netlist_time::internal_type value0>
+ struct times_ns1
+ {
+ static constexpr netlist_time value(std::size_t N = 0)
+ {
+ plib::unused_var(N);
+ return NLTIME_FROM_NS(value0);
+ }
+ };
+
+ template <netlist_time::internal_type value0>
+ using time_ns = times_ns1<value0>;
+
+ /// \brief: used to hold two static netlist_time values
+ ///
+ template<netlist_time::internal_type value0,
+ netlist_time::internal_type value1>
+ struct times_ns2
+ {
+ static constexpr netlist_time value(std::size_t N)
+ {
+ return NLTIME_FROM_NS(N == 0 ? value0 : value1);
+ }
+ };
+
+ /// \brief: used to hold two static netlist_time values
+ ///
+ template<netlist_time::internal_type value0,
+ netlist_time::internal_type value1,
+ netlist_time::internal_type value2>
+ struct times_ns3
+ {
+ static constexpr netlist_time value(std::size_t N)
+ {
+ return NLTIME_FROM_NS(N == 0 ? value0 :
+ N == 1 ? value1 :
+ value2);
+ }
+ };
+
+ /// \brief: used define a constant in device description struct
+ ///
+ /// See the 74125 implementation
+ ///
+ template <std::size_t V>
+ using desc_const = std::integral_constant<std::size_t, V>;
+
+
} // namespace netlist