summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/lib/netlist/devices/nld_7448.cpp2
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp27
-rw-r--r--src/lib/netlist/nl_base.cpp29
-rw-r--r--src/lib/netlist/nl_base.h73
-rw-r--r--src/lib/netlist/nl_config.h12
-rw-r--r--src/lib/netlist/nl_time.h2
6 files changed, 111 insertions, 34 deletions
diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp
index efc06d83cae..239d6b50921 100644
--- a/src/lib/netlist/devices/nld_7448.cpp
+++ b/src/lib/netlist/devices/nld_7448.cpp
@@ -188,11 +188,13 @@ namespace netlist
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))
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index 69dd1c1c6ca..d392250d8a5 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -21,7 +21,6 @@ namespace netlist
, m_CLK(*this, "CLK", NETLIB_DELEGATE(9316, clk))
, m_ENT(*this, "ENT")
, m_LOADQ(*this, "LOADQ")
- , m_cnt(*this, "m_cnt", 0)
, m_ENP(*this, "ENP")
, m_CLRQ(*this, "CLRQ")
, m_A(*this, "A", NETLIB_DELEGATE(9316, abcd))
@@ -30,7 +29,10 @@ namespace netlist
, m_D(*this, "D", NETLIB_DELEGATE(9316, abcd))
, m_Q(*this, {{ "QA", "QB", "QC", "QD" }})
, m_RC(*this, "RC")
+ , m_cnt(*this, "m_cnt", 0)
, m_abcd(*this, "m_abcd", 0)
+ , m_loadq(*this, "m_loadq", 0)
+ , m_ent(*this, "m_ent", 0)
{
}
@@ -48,8 +50,6 @@ namespace netlist
logic_input_t m_ENT;
logic_input_t m_LOADQ;
- state_var_u8 m_cnt;
-
logic_input_t m_ENP;
logic_input_t m_CLRQ;
@@ -60,7 +60,14 @@ namespace netlist
object_array_t<logic_output_t, 4> m_Q;
logic_output_t m_RC;
+
+ /* counter state */
+ state_var_u8 m_cnt;
+
+ /* cached pins */
state_var_u8 m_abcd;
+ state_var_sig m_loadq;
+ state_var_sig m_ent;
private:
void update_outputs_all(const unsigned &cnt, const netlist_time &out_delay) noexcept
@@ -106,11 +113,10 @@ namespace netlist
NETLIB_HANDLER(9316, clk)
{
auto cnt(m_cnt);
- if (m_LOADQ())
+ if (m_loadq)
{
++cnt &= MAXCNT;
//m_RC.push(m_ENT() && (cnt == MAXCNT), NLTIME_FROM_NS(27));
-
if (cnt > 0 && cnt < MAXCNT)
update_outputs_all(cnt, NLTIME_FROM_NS(20));
else if (cnt == 0)
@@ -120,14 +126,14 @@ namespace netlist
}
else
{
- m_RC.push(m_ENT(), NLTIME_FROM_NS(27));
+ m_RC.push(m_ent, NLTIME_FROM_NS(27));
update_outputs_all(MAXCNT, NLTIME_FROM_NS(20));
}
}
else
{
cnt = m_abcd;
- m_RC.push(m_ENT() && (cnt == MAXCNT), NLTIME_FROM_NS(27));
+ m_RC.push(m_ent && (cnt == MAXCNT), NLTIME_FROM_NS(27));
update_outputs_all(cnt, NLTIME_FROM_NS(22));
}
m_cnt = cnt;
@@ -136,9 +142,10 @@ namespace netlist
NETLIB_UPDATE(9316)
{
const netlist_sig_t CLRQ(m_CLRQ());
- const netlist_sig_t ENT(m_ENT());
+ m_ent = m_ENT();
+ m_loadq = m_LOADQ();
- if (((m_LOADQ() ^ 1) || (ENT && m_ENP())) && CLRQ)
+ if (((m_loadq ^ 1) || (m_ent && m_ENP())) && CLRQ)
{
m_CLK.activate_lh();
}
@@ -151,7 +158,7 @@ namespace netlist
update_outputs_all(m_cnt, NLTIME_FROM_NS(36));
}
}
- m_RC.push(ENT && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
+ m_RC.push(m_ent && (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
}
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index cc057de25f8..24cb7cc8890 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -403,9 +403,17 @@ void netlist_state_t::reset()
case 1: // brute force backward
{
log().verbose("Using brute force backward startup strategy");
+
+ for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
+ n->update_inputs();
+
std::size_t i = m_devices.size();
while (i>0)
m_devices[--i]->update();
+
+ for (auto &n : m_nets) // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
+ n->update_inputs();
+
}
break;
case 2: // brute force forward
@@ -694,7 +702,7 @@ detail::net_t::net_t(netlist_base_t &nl, const pstring &aname, core_terminal_t *
, netlist_ref(nl)
, m_new_Q(*this, "m_new_Q", 0)
, m_cur_Q (*this, "m_cur_Q", 0)
- , m_in_queue(*this, "m_in_queue", QS_DELIVERED)
+ , m_in_queue(*this, "m_in_queue", queue_status::DELIVERED)
, m_next_scheduled_time(*this, "m_time", netlist_time::zero())
, m_railterminal(mr)
{
@@ -715,14 +723,18 @@ void detail::net_t::rebuild_list()
if (term->terminal_state() != logic_t::STATE_INP_PASSIVE)
{
m_list_active.push_back(term);
+ term->set_copied_input(m_cur_Q);
}
}
-
template <typename T>
-void detail::net_t::process(const T mask)
+void detail::net_t::process(const T mask, netlist_sig_t sig)
{
+ m_cur_Q = sig;
+
for (auto & p : m_list_active)
{
+ p.set_copied_input(sig);
+
p.device().m_stat_call_count.inc();
if ((p.terminal_state() & mask))
{
@@ -743,13 +755,12 @@ void detail::net_t::update_devs() NL_NOEXCEPT
const auto mask((new_Q << core_terminal_t::INP_LH_SHIFT)
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
- m_in_queue = QS_DELIVERED; /* mark as taken ... */
+ m_in_queue = queue_status::DELIVERED; /* mark as taken ... */
switch (mask)
{
case core_terminal_t::STATE_INP_HL:
case core_terminal_t::STATE_INP_LH:
- m_cur_Q = new_Q;
- process(mask | core_terminal_t::STATE_INP_ACTIVE);
+ process(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q);
break;
default:
/* do nothing */
@@ -760,7 +771,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT
void detail::net_t::reset()
{
m_next_scheduled_time = netlist_time::zero();
- m_in_queue = QS_DELIVERED;
+ m_in_queue = queue_status::DELIVERED;
m_new_Q = 0;
m_cur_Q = 0;
@@ -778,6 +789,7 @@ void detail::net_t::reset()
ct->reset();
if (ct->terminal_state() != logic_t::STATE_INP_PASSIVE)
m_list_active.push_back(ct);
+ ct->set_copied_input(m_cur_Q);
}
}
@@ -849,6 +861,9 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam
: device_object_t(dev, dev.name() + "." + aname)
, plib::linkedlist_t<core_terminal_t>::element_t()
, m_delegate(delegate)
+#if USE_COPY_INSTEAD_OF_REFERENCE
+, m_Q(*this, "m_Q", 0)
+#endif
, m_net(nullptr)
, m_state(*this, "m_state", state)
{
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 2d8f8154ed0..507eb42d367 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -524,7 +524,6 @@ namespace netlist
void clear_net() noexcept { m_net = nullptr; }
bool has_net() const noexcept { return (m_net != nullptr); }
-
const net_t & net() const noexcept { return *m_net;}
net_t & net() noexcept { return *m_net;}
@@ -538,6 +537,16 @@ namespace netlist
void reset() noexcept { set_state(is_type(OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); }
nldelegate m_delegate;
+#if USE_COPY_INSTEAD_OF_REFERENCE
+ void set_copied_input(netlist_sig_t val)
+ {
+ m_Q = val;
+ }
+
+ state_var_sig m_Q;
+#else
+ void set_copied_input(netlist_sig_t val) const { plib::unused_var(val); }
+#endif
private:
net_t * m_net;
@@ -707,11 +716,11 @@ namespace netlist
{
public:
- enum queue_status
+ enum class queue_status
{
- QS_DELAYED_DUE_TO_INACTIVE = 0,
- QS_QUEUED,
- QS_DELIVERED
+ DELAYED_DUE_TO_INACTIVE = 0,
+ QUEUED,
+ DELIVERED
};
net_t(netlist_base_t &nl, const pstring &aname, core_terminal_t *mr = nullptr);
@@ -728,7 +737,7 @@ namespace netlist
}
void push_to_queue(netlist_time delay) NL_NOEXCEPT;
- bool is_queued() const noexcept { return m_in_queue == QS_QUEUED; }
+ bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; }
void update_devs() NL_NOEXCEPT;
@@ -755,7 +764,18 @@ namespace netlist
void move_connections(net_t &dest_net);
std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
-
+#if USE_COPY_INSTEAD_OF_REFERENCE
+ void update_inputs()
+ {
+ for (auto & term : m_core_terms)
+ term->m_Q = m_cur_Q;
+ }
+#else
+ void update_inputs() const
+ {
+ /* nothing needs to be done */
+ }
+#endif
protected:
state_var<netlist_sig_t> m_new_Q;
state_var<netlist_sig_t> m_cur_Q;
@@ -768,7 +788,7 @@ namespace netlist
core_terminal_t * m_railterminal;
template <typename T>
- void process(const T mask);
+ void process(const T mask, netlist_sig_t sig);
};
class logic_net_t : public detail::net_t
@@ -779,11 +799,15 @@ namespace netlist
virtual ~logic_net_t();
netlist_sig_t Q() const noexcept { return m_cur_Q; }
- void initial(const netlist_sig_t val) noexcept { m_cur_Q = m_new_Q = val; }
+ void initial(const netlist_sig_t val) noexcept
+ {
+ m_cur_Q = m_new_Q = val;
+ update_inputs();
+ }
void set_Q_and_push(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
{
- if (newQ != m_new_Q )
+ if (newQ != m_new_Q)
{
m_new_Q = newQ;
push_to_queue(delay);
@@ -802,10 +826,11 @@ namespace netlist
{
if (newQ != m_new_Q)
{
- m_in_queue = QS_DELAYED_DUE_TO_INACTIVE;
+ m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE;
m_next_scheduled_time = at;
}
m_cur_Q = m_new_Q = newQ;
+ update_inputs();
}
/* internal state support
@@ -1529,9 +1554,12 @@ namespace netlist
if (is_queued())
q.remove(this);
- m_in_queue = (!m_list_active.empty()) ? QS_QUEUED : QS_DELAYED_DUE_TO_INACTIVE; /* queued ? */
- if (m_in_queue == QS_QUEUED)
+ m_in_queue = (!m_list_active.empty()) ?
+ queue_status::QUEUED : queue_status::DELAYED_DUE_TO_INACTIVE; /* queued ? */
+ if (m_in_queue == queue_status::QUEUED)
q.push(queue_t::entry_t(nst, this));
+ else
+ update_inputs();
m_next_scheduled_time = nst;
}
}
@@ -1542,22 +1570,28 @@ namespace netlist
{
m_list_active.push_front(&term);
railterminal().device().do_inc_active();
- if (m_in_queue == QS_DELAYED_DUE_TO_INACTIVE)
+ if (m_in_queue == queue_status::DELAYED_DUE_TO_INACTIVE)
{
if (m_next_scheduled_time > exec().time())
{
- m_in_queue = QS_QUEUED; /* pending */
+ m_in_queue = queue_status::QUEUED; /* pending */
exec().queue().push({m_next_scheduled_time, this});
}
else
{
- m_in_queue = QS_DELIVERED;
+ m_in_queue = queue_status::DELIVERED;
m_cur_Q = m_new_Q;
}
+ update_inputs();
}
+ else
+ term.set_copied_input(m_cur_Q);
}
else
+ {
+ term.set_copied_input(m_cur_Q);
m_list_active.push_front(&term);
+ }
}
inline void detail::net_t::remove_from_active_list(core_terminal_t &term) NL_NOEXCEPT
@@ -1592,7 +1626,13 @@ namespace netlist
inline netlist_sig_t logic_input_t::Q() const NL_NOEXCEPT
{
nl_assert(terminal_state() != STATE_INP_PASSIVE);
+ //if (net().Q() != m_Q)
+ // printf("term: %s, %d %d TS %d\n", this->name().c_str(), net().Q(), m_Q, terminal_state());
+#if USE_COPY_INSTEAD_OF_REFERENCE
+ return m_Q;
+#else
return net().Q();
+#endif
}
inline nl_double analog_input_t::Q_Analog() const NL_NOEXCEPT
@@ -1624,7 +1664,6 @@ namespace netlist
return m_device.exec();
}
-
inline const netlist_t &detail::device_object_t::exec() const NL_NOEXCEPT
{
return m_device.exec();
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index dd94981d4ee..69b5fad945c 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -30,6 +30,18 @@
*/
#define USE_MEMPOOL (0)
+/*! Store input values in logic_terminal_t.
+ *
+ * Set to 1 to store values in logic_terminal_t instead of
+ * accessing them indirectly by pointer from logic_net_t.
+ * This approach is stricter and should identify bugs in
+ * the netlist core faster.
+ * By default it is disabled since it is not as fast as
+ * the default approach.
+ *
+ */
+#define USE_COPY_INSTEAD_OF_REFERENCE (0)
+
/*
* FIXME: Using truthtable is a lot slower than the explicit device
* in breakout. Performance drops by 20%. This can be fixed by
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
index d5223db3140..b8ed1bb5a33 100644
--- a/src/lib/netlist/nl_time.h
+++ b/src/lib/netlist/nl_time.h
@@ -124,6 +124,7 @@ namespace netlist
static constexpr ptime quantum() noexcept { return ptime(1, RES); }
static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), RES); }
static constexpr internal_type resolution() noexcept { return RES; }
+
private:
static constexpr const double inv_res = 1.0 / static_cast<double>(RES);
internal_type m_time;
@@ -133,6 +134,7 @@ namespace netlist
using netlist_time = ptime<UINT128, NETLIST_INTERNAL_RES>;
#else
using netlist_time = ptime<std::uint64_t, NETLIST_INTERNAL_RES>;
+ static_assert(noexcept(netlist_time::from_nsec(1)) == true, "Not evaluated as constexpr");
#endif
}