summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@users.noreply.github.com>2022-05-05 17:37:22 +0200
committer GitHub <noreply@github.com>2022-05-06 01:37:22 +1000
commitd20a1982da6a87642dd96973ea7f94d3ca37a5c4 (patch)
tree8a0959779fec66197a4b1edd1510715dd9e2fad1
parent0818eafc2fe968900a973471a59b2ab3a945f13c (diff)
Netlist lint, first version of a FAQ and small code changes. (#9684)
- Added a first version of a FAQ. - Use better error messages in pfunction. - Made member functions static where appropriate in nld_solver.
-rw-r--r--src/lib/netlist/FAQ.md151
-rw-r--r--src/lib/netlist/devices/nld_9321.cpp4
-rw-r--r--src/lib/netlist/plib/pfunction.cpp19
-rw-r--r--src/lib/netlist/plib/ptokenizer.cpp2
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h38
-rw-r--r--src/lib/netlist/solver/nld_ms_w.h2
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp1
7 files changed, 188 insertions, 29 deletions
diff --git a/src/lib/netlist/FAQ.md b/src/lib/netlist/FAQ.md
new file mode 100644
index 00000000000..44bcf7c924b
--- /dev/null
+++ b/src/lib/netlist/FAQ.md
@@ -0,0 +1,151 @@
+# The netlist FAQ
+
+## Glossary
+
+BTANB: Bugs That Aren't Bugs. Bugs in the hardware (or software) that are
+faithfully emulated, therefore not a bug in the emulator.
+
+## General
+
+### Have you considered maybe supporting part randomization in the netlist core?
+
+Yes I did. And decided against it. Which features? Forced randomness - will this
+be different at every restart? And it would require another parameter per device
+(specification, e.g. for resistors 5%, 10%, 20%). This would cause more cache
+usage.
+
+And I am convinced we would see more BTANBs.
+
+### How do frontiers work?
+
+Frontiers divides a netlist into sub netlists, i.e. a number of smaller netlists.
+Frontiers work best if you have a low impedance to high impedance transition.
+This is best illustrated by an example. Consider the following mixing stage
+
+ R1
+ S1 >-----1RRRR2---------+
+ |
+ R2 |
+ S2 >-----1RRRR2---------+----------> Out
+ |
+ R
+ R3 R
+ R
+ |
+ GND
+
+With `OPTIMIZE_FRONTIER(R2.2, R3, R2)` this becomes:
+
+ R1
+ S1 >-----1RRRR2--------------------------------+
+ |
+ ########################## |
+ R2 # R2 # |
+ S2 >-----1RRRR2-----+-->AnIn AnOut>--RRRR------+----------> Out
+ # | # |
+ # R # R
+ # R R3 # 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 S1 will be smaller.
+The size of the solver for S2 and the rest of the circuit will be smaller
+as well.
+
+Frontiers assume that there is little to no feedback from the "out" terminal to the "in"
+terminal. This is a safe assumption if the "in" terminal e.g. is connected to an
+op-amp output (typically < 500 Ohm) and R2 in the example above is in the 10 KOhm range.
+
+## MAME specific
+
+### Is there an example of a netlist that takes input from an AY-8910/2 and handles it?
+
+There are quite a few:
+
+- nl_kidniki.cpp
+- nl_konami.cpp
+- 1942.cpp
+
+Basically the AY8910 driver has to be configured to push resistor values to the
+input stream. The konami drivers (scramble, frogger and friends) do that and
+should be used as a reference. 1942 connects outputs and may be an even better example.
+
+## Models
+
+### Is there are JFET model?
+
+No, there is currently no JFET model in netlist. They are close to depletion
+mode MOSFETs with very low gate capacitance so you may try a generic n-mosfet
+with a negative trigger voltage. Example:
+
+ MOSFET(Q21, "NMOS(VTO=-1.0)")
+
+Writing an analog model is a very time-consuming task. The simplified model above should
+deliver reasonable results.
+
+## Operational Amplifiers
+
+### What's UGF? Would like to understand this black magic a little better. :)
+
+UGF = Unity Gain Frequency, usually identical to gain-bandwidth product for
+op-amps. The idea is that the an op-amp's open-loop gain (its amplification
+factor when used without any negative feedback) is proportional to the
+frequency of its input signal. For slowly-varying, near-DC signals, this gain
+will be extremely high (in this case, a gain of 10000 at 1 Hz), which is part
+of what makes an op-amp effective. In practice the op-amp's actual gain will
+be limited by whatever negative feedback is applied, but its open-loop gain
+is a key quantity in computing its actual response. Because the op-amp is
+limited in how fast it can respond to its input, its open-loop gain will
+drop as the frequency of the input signal rises, eventually falling to a
+gain of 1 (output = input) at the unity gain frequency. In this case
+couriersud set the unity gain frequency is 10 kHz, which is much lower than
+reality, in order to make the op-amp response in the oscillators slower and
+easier for the netlist solver to handle without using very small time steps.
+According to Texas Instruments, the TL084's actual gain-bandwidth product
+(remember, this is the same as the UGF) is typically 3 MHz.
+
+## Documentation
+
+### What is the preferred documentation format?
+
+The preferred documentation for devices is to use the netlist documentation format.
+This will ensure that the devices are properly documented in the Doxygen
+documentation created by `make doc`
+
+An example entry is given here:
+
+ //- Identifier: SN74LS629_DIP
+ //- Title: SN74LS629 VOLTAGE-CONTROLLED OSCILLATORS
+ //- Description: Please add a detailed description
+ //- FIXME: Missing description
+ //-
+ //- Pinalias: 2FC,1FC,1RNG,1CX1,1CX2,1ENQ,1Y,OSC_GND,GND,2Y,2ENQ,2CX2,2CX1,2RNG,OSC_VCC,VCC
+ //- Package: DIP
+ //- Param: A.CAP
+ //- Capacitor value of capacitor connected to 1CX1 and 1CX2 pins
+ //- Param: B.CAP
+ //- Capacitor value of capacitor connected to 2CX1 and 2CX2 pins
+ //- Limitations:
+ //- The capacitor inputs are NC. Capacitor values need to be specified as
+ //- ```
+ //- SN74LS629_DIP(X)
+ //- PARAM(X.A.CAP, CAP_U(1))
+ //- PARAM(X.B.CAP, CAP_U(2))
+ //- ```
+ //-
+ //- Example: 74ls629.cpp,74ls629_example
+ //-
+ //- FunctionTable:
+ //- http://pdf.datasheetcatalog.com/datasheets/400/335051_DS.pdf
+ //-
+ static NETLIST_START(SN74LS629_DIP)
+
+If you add an example in the examples folder this will be included in the
+documentation as well.
+
diff --git a/src/lib/netlist/devices/nld_9321.cpp b/src/lib/netlist/devices/nld_9321.cpp
index 8adaaad0f6b..479b83d497e 100644
--- a/src/lib/netlist/devices/nld_9321.cpp
+++ b/src/lib/netlist/devices/nld_9321.cpp
@@ -39,7 +39,7 @@ namespace netlist::devices {
private:
NETLIB_HANDLERI(in)
{
- m_enable = m_E() ? false : true;
+ 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));
@@ -47,7 +47,7 @@ namespace netlist::devices {
NETLIB_HANDLERI(e)
{
- m_enable = m_E() ? false : true;
+ 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));
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 362615468e5..6d295f48a73 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -17,6 +17,13 @@
namespace plib {
+ PERRMSGV(MF_FUNCTION_UNKNOWN_TOKEN, 2, "pfunction: unknown/misformatted token <{1}> in <{2}>")
+ PERRMSGV(MF_FUNCTION_STACK_UNDERFLOW, 2, "pfunction: stack underflow on token <{1}> in <{2}>")
+ PERRMSGV(MF_FUNCTION_STACK_OVERFLOW, 2, "pfunction: stack overflow on token <{1}> in <{2}>")
+ PERRMSGV(MF_FUNCTION_PARENTHESIS_INEQUALITY, 2, "pfunction: parenthesis inequality on token <{1}> in <{2}>")
+ PERRMSGV(MF_FUNCTION_STACK_UNEQUAL_ONE, 2, "pfunction: stack count {1} different to one on <{2}>")
+ PERRMSGV(MF_FUNCTION_STACK_UNDERFLOW_INFIX, 1, "pfunction: stack underflow during infix parsing of: <{1}>")
+
static constexpr const std::size_t MAX_STACK = 32;
struct pcmd_t
@@ -141,20 +148,20 @@ namespace plib {
else
rc = rpn_inst(plib::pstonum_ne<NT>(plib::left(cmd, cmd.length()-1), err) * r->second);
if (err)
- throw pexception(plib::pfmt("pfunction: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
+ throw pexception(MF_FUNCTION_UNKNOWN_TOKEN(cmd, expr));
stk += 1;
}
}
if (stk < 1)
- throw pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr));
+ throw pexception(MF_FUNCTION_STACK_UNDERFLOW(cmd, expr));
if (stk >= narrow_cast<int>(MAX_STACK))
- throw pexception(plib::pfmt("pfunction: stack overflow on token <{1}> in <{2}>")(cmd)(expr));
+ throw pexception(MF_FUNCTION_STACK_OVERFLOW(cmd, expr));
if (rc.cmd() == LP || rc.cmd() == RP)
- throw pexception(plib::pfmt("pfunction: parenthesis inequality on token <{1}> in <{2}>")(cmd)(expr));
+ throw pexception(MF_FUNCTION_PARENTHESIS_INEQUALITY(cmd, expr));
m_precompiled.push_back(rc);
}
if (stk != 1)
- throw pexception(plib::pfmt("pfunction: stack count {1} different to one on <{2}>")(stk, expr));
+ throw pexception(MF_FUNCTION_STACK_UNEQUAL_ONE(stk, expr));
compress();
}
@@ -187,7 +194,7 @@ namespace plib {
static pstring pop_check(std::stack<pstring> &stk, const pstring &expr) noexcept(false)
{
if (stk.empty())
- throw pexception(plib::pfmt("pfunction: stack underflow during infix parsing of: <{1}>")(expr));
+ throw pexception(MF_FUNCTION_STACK_UNDERFLOW_INFIX(expr));
pstring res = stk.top();
stk.pop();
return res;
diff --git a/src/lib/netlist/plib/ptokenizer.cpp b/src/lib/netlist/plib/ptokenizer.cpp
index fed0e2add31..80db2d0663a 100644
--- a/src/lib/netlist/plib/ptokenizer.cpp
+++ b/src/lib/netlist/plib/ptokenizer.cpp
@@ -13,7 +13,7 @@ namespace plib {
PERRMSGV(MF_EXPECTED_IDENTIFIER_GOT_1, 1, "Expected an identifier, got <{1}>")
PERRMSGV(MF_EXPECTED_ID_OR_NUM_GOT_1, 1, "Expected an identifier or number, got <{1}>")
PERRMSGV(MF_EXPECTED_NUMBER_GOT_1, 1, "Expected a number, got <{1}>")
- PERRMSGV(MF_EXPECTED_LONGINT_GOT_1, 1, "Expected a logn int, got <{1}>")
+ PERRMSGV(MF_EXPECTED_LONGINT_GOT_1, 1, "Expected a long int, got <{1}>")
PERRMSGV(MF_EXPECTED_LINENUM_GOT_1, 1, "Expected line number after line marker but got <{1}>")
PERRMSGV(MF_EXPECTED_FILENAME_GOT_1, 1, "Expected file name after line marker but got <{1}>")
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 2c0057a11b9..57d56880a90 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -64,35 +64,35 @@ namespace solver
struct solver_parameter_defaults
{
- constexpr nl_fptype m_freq() { return nlconst::magic(48000.0); }
+ static constexpr nl_fptype m_freq() { return nlconst::magic(48000.0); }
// iteration parameters
- constexpr nl_fptype m_gs_sor() { return nlconst::magic(1.059); }
- constexpr matrix_type_e m_method() { return matrix_type_e::MAT_CR; }
- constexpr matrix_fp_type_e m_fp_type() { return matrix_fp_type_e::DOUBLE; }
- constexpr nl_fptype m_reltol() { return nlconst::magic(1e-3); }
- constexpr nl_fptype m_vntol() { return nlconst::magic(1e-7); }
- constexpr nl_fptype m_accuracy() { return nlconst::magic(1e-7); }
- constexpr std::size_t m_nr_loops() { return 250; }
- constexpr std::size_t m_gs_loops() { return 50; }
+ static constexpr nl_fptype m_gs_sor() { return nlconst::magic(1.059); }
+ static constexpr matrix_type_e m_method() { return matrix_type_e::MAT_CR; }
+ static constexpr matrix_fp_type_e m_fp_type() { return matrix_fp_type_e::DOUBLE; }
+ static constexpr nl_fptype m_reltol() { return nlconst::magic(1e-3); }
+ static constexpr nl_fptype m_vntol() { return nlconst::magic(1e-7); }
+ static constexpr nl_fptype m_accuracy() { return nlconst::magic(1e-7); }
+ static constexpr std::size_t m_nr_loops() { return 250; }
+ static constexpr std::size_t m_gs_loops() { return 50; }
// general parameters
- constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); }
- constexpr bool m_pivot() { return false; }
- constexpr nl_fptype m_nr_recalc_delay(){ return netlist_time::quantum().as_fp<nl_fptype>(); }
- constexpr int m_parallel() { return 0; }
+ static constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); }
+ static constexpr bool m_pivot() { return false; }
+ static constexpr nl_fptype m_nr_recalc_delay(){ return netlist_time::quantum().as_fp<nl_fptype>(); }
+ static constexpr int m_parallel() { return 0; }
- constexpr nl_fptype m_min_ts_ts() { return nlconst::magic(1e-9); }
+ static constexpr nl_fptype m_min_ts_ts() { return nlconst::magic(1e-9); }
// automatic time step
- constexpr bool m_dynamic_ts() { return false; }
- constexpr nl_fptype m_dynamic_lte() { return nlconst::magic(1e-5); }
- constexpr nl_fptype m_dynamic_min_ts() { return nlconst::magic(1e-6); }
+ static constexpr bool m_dynamic_ts() { return false; }
+ static constexpr nl_fptype m_dynamic_lte() { return nlconst::magic(1e-5); }
+ static constexpr nl_fptype m_dynamic_min_ts() { return nlconst::magic(1e-6); }
// matrix sorting
- constexpr matrix_sort_type_e m_sort_type() { return matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT; }
+ static constexpr matrix_sort_type_e m_sort_type() { return matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT; }
// special
- constexpr bool m_use_gabs() { return true; }
+ static constexpr bool m_use_gabs() { return true; }
static solver_parameter_defaults &get_instance()
{
diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h
index da7a2c75a7a..49cb9dfa097 100644
--- a/src/lib/netlist/solver/nld_ms_w.h
+++ b/src/lib/netlist/solver/nld_ms_w.h
@@ -328,7 +328,7 @@ namespace solver
}
m_cnt++;
- if (false)
+ if (false) // NOLINT
for (unsigned i=0; i<iN; i++)
{
float_type tmp = plib::constants<FT>::zero();
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 9dee5a37f8b..89c2aa82c19 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -362,6 +362,7 @@ namespace devices
auto &pt = dynamic_cast<terminal_t &>(*term);
// check the connected terminal
const auto *const connected_terminals = nlstate.setup().get_connected_terminals(pt);
+ // NOLINTNEXTLINE proposal does not work for VS
for (auto ct = connected_terminals->begin(); *ct != nullptr; ct++)
{
analog_net_t &connected_net = (*ct)->net();