Improved kidniki sound quality while maintaining speed by adding more

frontiers. Added LOGIC_INPUT to netlist which allows to specify a logic
family, i.e. output characterics. Used this for improved AY8910 port
modeling. [Couriersud]
This commit is contained in:
couriersud 2015-06-27 11:42:47 +02:00
parent 6790076cc3
commit b4d3ecac8b
9 changed files with 86 additions and 48 deletions

View File

@ -57,7 +57,8 @@ void initialize_factory(factory_list_t &factory)
ENTRY(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly
ENTRY(QBJT_EB, QBJT_EB, "model")
ENTRY(QBJT_switch, QBJT_SW, "model")
ENTRY(ttl_input, TTL_INPUT, "IN")
ENTRY(logic_input, TTL_INPUT, "IN")
ENTRY(logic_input, LOGIC_INPUT, "IN,FAMILY")
ENTRY(analog_input, ANALOG_INPUT, "IN")
ENTRY(log, LOG, "+I")
ENTRY(logD, LOGD, "+I,I2")

View File

@ -131,22 +131,34 @@ NETLIB_UPDATE(extclock)
// logic_input
// ----------------------------------------------------------------------------------------
NETLIB_START(ttl_input)
NETLIB_START(logic_input)
{
/* make sure we get the family first */
register_param("FAMILY", m_FAMILY, ".model FAMILY(TYPE=TTL)");
set_logic_family(logic_family_desc_t::from_model(m_FAMILY.Value()));
register_output("Q", m_Q);
register_param("IN", m_IN, 0);
}
NETLIB_RESET(ttl_input)
NETLIB_RESET(logic_input)
{
}
NETLIB_UPDATE(ttl_input)
NETLIB_STOP(logic_input)
{
if (logic_family() != NULL)
if (!logic_family()->m_is_static)
pfree(logic_family());
}
NETLIB_UPDATE(logic_input)
{
OUTLOGIC(m_Q, m_IN.Value() & 1, netlist_time::from_nsec(1));
}
NETLIB_UPDATE_PARAM(ttl_input)
NETLIB_UPDATE_PARAM(logic_input)
{
update();
}

View File

@ -18,9 +18,14 @@
// -----------------------------------------------------------------------------
#define TTL_INPUT(_name, _v) \
NET_REGISTER_DEV(ttl_input, _name) \
NET_REGISTER_DEV(logic_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)
@ -123,10 +128,13 @@ NETLIB_DEVICE_WITH_PARAMS(extclock,
// Special support devices ...
// -----------------------------------------------------------------------------
NETLIB_DEVICE_WITH_PARAMS(ttl_input,
NETLIB_DEVICE_WITH_PARAMS(logic_input,
virtual void stop();
logic_output_t m_Q;
param_logic_t m_IN;
param_model_t m_FAMILY;
);
NETLIB_DEVICE_WITH_PARAMS(analog_input,

View File

@ -333,6 +333,7 @@ namespace netlist
public:
logic_family_t() : m_logic_family(NULL) {}
~logic_family_t() { }
ATTR_HOT const logic_family_desc_t *logic_family() const { return m_logic_family; }
ATTR_COLD void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }

View File

@ -860,6 +860,8 @@ const pstring setup_t::model_value_str(const pstring &model_str, const pstring &
int pblank = tmp.find(" ", p);
if (pblank < 0) pblank = tmp.len() + 1;
tmp = tmp.substr(p, pblank - p);
if (tmp.right(1) == ")")
tmp = tmp.left(tmp.len()-1);
int pequal = tmp.find("=", 0);
if (pequal < 0)
fatalerror_e("parameter %s misformat in model %s temp %s\n", entity.cstr(), model_str.cstr(), tmp.cstr());
@ -883,6 +885,7 @@ nl_double setup_t::model_value(const pstring &model_str, const pstring &entity,
char numfac = *(tmp.right(1).cstr());
switch (numfac)
{
case 'k': factor = 1e3; break;
case 'm': factor = 1e-3; break;
case 'u': factor = 1e-6; break;
case 'n': factor = 1e-9; break;

View File

@ -279,7 +279,8 @@ ATTR_HOT nl_double matrix_solver_t::solve()
// We are already up to date. Avoid oscillations.
// FIXME: Make this a parameter!
if (delta < netlist_time::from_nsec(1)) // 20000
//if (delta < netlist_time::from_nsec(1)) // 20000
if (delta < netlist_time::from_nsec(20000)) // 20000
return -1.0;
/* update all terminals for new time step */
@ -382,8 +383,8 @@ NETLIB_UPDATE(solver)
#if HAS_OPENMP && USE_OPENMP
if (m_parallel.Value())
{
omp_set_num_threads(4);
omp_set_dynamic(0);
omp_set_num_threads(3);
//omp_set_dynamic(0);
#pragma omp parallel
{
#pragma omp for

View File

@ -30,27 +30,26 @@ private:
};
#endif
inline void vec_set (const unsigned n, const double &scalar, double * RESTRICT result)
inline void vec_set (const std::size_t n, const double &scalar, double * RESTRICT result)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
result[i] = scalar;
}
inline double vecmult (const unsigned n, const double * RESTRICT a1, const double * RESTRICT a2 )
#include "omp.h"
inline double vecmult (const std::size_t n, const double * RESTRICT a1, const double * RESTRICT a2 )
{
double value = 0.0;
for ( unsigned i = 0; i < n; i++ )
double value = 0.0;
for ( std::size_t i = 0; i < n; i++ )
value = value + a1[i] * a2[i];
return value;
}
inline double vecmult2 (const unsigned n, const double *a1)
inline double vecmult2 (const std::size_t n, const double *a1)
{
double value = 0.0;
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
{
const double temp = a1[i];
value = value + temp * temp;
@ -58,9 +57,9 @@ inline double vecmult2 (const unsigned n, const double *a1)
return value;
}
inline void vec_mult_scalar (const int n, const double * RESTRICT v, const double scalar, double * RESTRICT result)
inline void vec_mult_scalar (const std::size_t n, const double * RESTRICT v, const double scalar, double * RESTRICT result)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
{
result[i] = scalar * v[i];
}
@ -70,37 +69,37 @@ inline void vec_mult_scalar (const int n, const double * RESTRICT v, const doubl
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
inline void vec_add_mult_scalar (const int n, const double * RESTRICT v, const double scalar, double * RESTRICT result)
inline void vec_add_mult_scalar (const std::size_t n, const double * RESTRICT v, const double scalar, double * RESTRICT result)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
result[i] += scalar * v[i];
}
inline void vec_add_ip(const int n, const double * RESTRICT v, double * RESTRICT result)
inline void vec_add_ip(const std::size_t n, const double * RESTRICT v, double * RESTRICT result)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
result[i] += v[i];
}
inline void vec_sub(const int n, const double * RESTRICT v1, const double * RESTRICT v2, double * RESTRICT result)
inline void vec_sub(const std::size_t n, const double * RESTRICT v1, const double * RESTRICT v2, double * RESTRICT result)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
result[i] = v1[i] - v2[i];
}
#ifndef __clang__
#pragma GCC diagnostic pop
#endif
inline void vec_scale (const int n, double * RESTRICT v, const double scalar)
inline void vec_scale (const std::size_t n, double * RESTRICT v, const double scalar)
{
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
v[i] = scalar * v[i];
}
inline double vec_maxabs(const int n, const double * RESTRICT v)
inline double vec_maxabs(const std::size_t n, const double * RESTRICT v)
{
double ret = 0.0;
for ( unsigned i = 0; i < n; i++ )
for ( std::size_t i = 0; i < n; i++ )
ret = std::max(ret, std::abs(v[i]));
return ret;

View File

@ -389,30 +389,35 @@ ADDRESS_MAP_END
* https://www.youtube.com/watch?v=aarl0xfBQf0
*
*/
#define USE_FRONTIERS 1
#define USE_FIXED_STV 1
#include "nl_kidniki.c"
NETLIST_START(kidniki_interface)
#if 0
SOLVER(Solver, 12000)
PARAM(Solver.ACCURACY, 1e-8)
PARAM(Solver.NR_LOOPS, 300)
PARAM(Solver.GS_LOOPS, 2)
#else
SOLVER(Solver, 12000)
PARAM(Solver.ACCURACY, 1e-9)
#if (USE_FRONTIERS)
SOLVER(Solver, 18000)
PARAM(Solver.ACCURACY, 1e-7)
PARAM(Solver.NR_LOOPS, 300)
PARAM(Solver.GS_LOOPS, 1)
PARAM(Solver.GS_THRESHOLD, 99)
PARAM(Solver.ITERATIVE, "SOR")
#endif
//PARAM(Solver.GS_THRESHOLD, 99) // Force Gaussian elimination here
PARAM(Solver.PARALLEL, 1)
PARAM(Solver.SOR_FACTOR, 1.00)
//FIXME proper models!
NET_MODEL(".model 2SC945 NPN(Is=2.04f Xti=3 Eg=1.11 Vaf=6 Bf=400 Ikf=20m Xtb=1.5 Br=3.377 Rc=1 Cjc=1p Mjc=.3333 Vjc=.75 Fc=.5 Cje=25p Mje=.3333 Vje=.75 Tr=450n Tf=20n Itf=0 Vtf=0 Xtf=0 VCEO=45V ICrating=150M MFG=Toshiba)")
NET_MODEL(".model 1S1588 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
#else
SOLVER(Solver, 12000)
PARAM(Solver.ACCURACY, 1e-8)
PARAM(Solver.NR_LOOPS, 300)
PARAM(Solver.GS_LOOPS, 20)
PARAM(Solver.ITERATIVE, "GMRES")
PARAM(Solver.PARALLEL, 0)
#endif
NET_MODEL(".model 2SC945 NPN(IS=3.577E-14 BF=2.382E+02 NF=1.01 VAF=1.206E+02 IKF=3.332E-01 ISE=3.038E-16 NE=1.205 BR=1.289E+01 NR=1.015 VAR=1.533E+01 IKR=2.037E-01 ISC=3.972E-14 NC=1.115 RB=3.680E+01 IRB=1.004E-04 RBM=1 RE=8.338E-01 RC=1.557E+00 CJE=1.877E-11 VJE=7.211E-01 MJE=3.486E-01 TF=4.149E-10 XTF=1.000E+02 VTF=9.956 ITF=5.118E-01 PTF=0 CJC=6.876p VJC=3.645E-01 MJC=3.074E-01 TR=5.145E-08 XTB=1.5 EG=1.11 XTI=3 FC=0.5 Vceo=50 Icrating=100m MFG=NEC)")
// Equivalent to 1N914
NET_MODEL(".model 1S1588 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75)")
LOCAL_SOURCE(kidniki_schematics)
@ -461,13 +466,15 @@ NETLIST_START(kidniki_interface)
ALIAS(I_SINH0, SINH_DUMMY.2)
#endif
TTL_INPUT(I_SD0, 1)
NET_MODEL(".model AY8910PORT FAMILY(OVL=0.05 OVH=4.95 ORL=100.0 ORH=0.5k)")
LOGIC_INPUT(I_SD0, 1, "AY8910PORT")
//CLOCK(I_SD0, 5)
TTL_INPUT(I_BD0, 1)
LOGIC_INPUT(I_BD0, 1, "AY8910PORT")
//CLOCK(I_BD0, 5)
TTL_INPUT(I_CH0, 1)
LOGIC_INPUT(I_CH0, 1, "AY8910PORT")
//CLOCK(I_CH0, 2.2 )
TTL_INPUT(I_OH0, 1)
LOGIC_INPUT(I_OH0, 1, "AY8910PORT")
//CLOCK(I_OH0, 1.0)
ANALOG_INPUT(I_MSM2K0, 0)
ANALOG_INPUT(I_MSM3K0, 0)
@ -489,6 +496,11 @@ NETLIST_START(kidniki_interface)
OPTIMIZE_FRONTIER(R31.2, RES_K(5.1), 50)
OPTIMIZE_FRONTIER(R29.2, RES_K(2.7), 50)
OPTIMIZE_FRONTIER(R87.2, RES_K(68), 50)
OPTIMIZE_FRONTIER(R50.1, RES_K(2.2), 50)
OPTIMIZE_FRONTIER(R55.1, RES_K(510), 50)
OPTIMIZE_FRONTIER(R84.2, RES_K(50), RES_K(5))
#endif
NETLIST_END()

View File

@ -140,6 +140,7 @@ NETLIST_START(kidniki_schematics)
RES(R29, RES_K(2.7))
RES(R30, RES_K(10))
RES(R31, RES_K(5.1))
//RES(R32, RES_K(1))
RES(R32, RES_K(4.7))
RES(R34, RES_K(100))
RES(R35, RES_K(100))