mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
netlist: Compile with float/double floating point. [Couriersud]
Added ability to compile using float instead of double. Specifically the the solver as well as the infrastructure now can have their own floating point type. Currently this is only an academic exercise since numerically demanding circuits like kidniki only work with double/double support. Using float here is pushing numerical stability over the limits. The long term design goal is too have the matrix type (double/float) being a parameter.
This commit is contained in:
parent
6c075e602c
commit
c6b281685d
@ -1266,13 +1266,12 @@ void netlist_mame_cpu_device::device_start()
|
||||
{
|
||||
if (n->is_logic())
|
||||
{
|
||||
state_add(index, n->name().c_str(), *(downcast<netlist::logic_net_t &>(*n).Q_state_ptr()));
|
||||
state_add(index++, n->name().c_str(), *(downcast<netlist::logic_net_t &>(*n).Q_state_ptr()));
|
||||
}
|
||||
else
|
||||
{
|
||||
state_add(index, n->name().c_str(), *(downcast<netlist::analog_net_t &>(*n).Q_Analog_state_ptr()));
|
||||
//state_add(index++, n->name().c_str(), *(downcast<netlist::analog_net_t &>(*n).Q_Analog_state_ptr()));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// set our instruction counter
|
||||
|
@ -319,7 +319,7 @@ protected:
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
private:
|
||||
netlist::param_num_t<double> *m_param;
|
||||
netlist::param_num_t<nl_fptype> *m_param;
|
||||
bool m_auto_port;
|
||||
const char *m_param_name;
|
||||
double m_value_for_device_timer;
|
||||
|
@ -158,12 +158,12 @@ namespace analog
|
||||
//printf("%s: %g %g\n", m_name.c_str(), nVd, (nl_fptype) m_Vd);
|
||||
if (nVd > m_Vcrit)
|
||||
{
|
||||
const nl_fptype d = std::min(1e100, nVd - m_Vd);
|
||||
const nl_fptype d = std::min(fp_constants<nl_fptype>::DIODE_MAXDIFF, nVd - m_Vd);
|
||||
const nl_fptype a = std::abs(d) * m_VtInv;
|
||||
m_Vd = m_Vd + (d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt;
|
||||
}
|
||||
else
|
||||
m_Vd = std::max(-1e100, nVd);
|
||||
m_Vd = std::max(-fp_constants<nl_fptype>::DIODE_MAXDIFF, nVd);
|
||||
//m_Vd = nVd;
|
||||
|
||||
if (m_Vd < m_Vmin)
|
||||
@ -189,7 +189,7 @@ namespace analog
|
||||
else /* log stepping should already be done in mosfet */
|
||||
{
|
||||
m_Vd = nVd;
|
||||
IseVDVt = std::exp(std::min(300.0, m_logIs + m_Vd * m_VtInv));
|
||||
IseVDVt = std::exp(std::min(fp_constants<nl_fptype>::DIODE_MAXVOLT, m_logIs + m_Vd * m_VtInv));
|
||||
m_Id = IseVDVt - m_Is;
|
||||
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||
}
|
||||
|
@ -430,7 +430,7 @@ namespace analog
|
||||
param_fp_t m_R;
|
||||
param_fp_t m_V;
|
||||
param_str_t m_func;
|
||||
plib::pfunction m_compiled;
|
||||
plib::pfunction<nl_fptype> m_compiled;
|
||||
std::vector<nl_fptype> m_funcparam;
|
||||
};
|
||||
|
||||
@ -486,7 +486,7 @@ namespace analog
|
||||
state_var<nl_fptype> m_t;
|
||||
param_fp_t m_I;
|
||||
param_str_t m_func;
|
||||
plib::pfunction m_compiled;
|
||||
plib::pfunction<nl_fptype> m_compiled;
|
||||
std::vector<nl_fptype> m_funcparam;
|
||||
};
|
||||
|
||||
|
@ -149,7 +149,7 @@ namespace devices
|
||||
logic_output_t m_Q;
|
||||
|
||||
param_str_t m_func;
|
||||
plib::pfunction m_compiled;
|
||||
plib::pfunction<nl_fptype> m_compiled;
|
||||
std::vector<nl_fptype> m_funcparam;
|
||||
};
|
||||
|
||||
@ -389,7 +389,7 @@ namespace devices
|
||||
std::vector<unique_pool_ptr<analog_input_t>> m_I;
|
||||
|
||||
std::vector<nl_fptype> m_vals;
|
||||
plib::pfunction m_compiled;
|
||||
plib::pfunction<nl_fptype> m_compiled;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -96,7 +96,52 @@
|
||||
static constexpr const auto NETLIST_INTERNAL_RES = 1000000000;
|
||||
static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES;
|
||||
|
||||
//#define nl_fptype float
|
||||
//============================================================
|
||||
// Floating point types used
|
||||
//
|
||||
// Don't change this. Simple analog circuits like pong
|
||||
// work with float. Kidniki just doesn't work at all
|
||||
// due to numeric issues
|
||||
//============================================================
|
||||
|
||||
using nl_fptype = double;
|
||||
//using nl_fptype = float;
|
||||
|
||||
using nl_mat_fptype = nl_fptype;
|
||||
|
||||
namespace netlist
|
||||
{
|
||||
/*! Specific constants depending on floating type
|
||||
*
|
||||
* @tparam FT floating point type: double/float
|
||||
*/
|
||||
template <typename FT>
|
||||
struct fp_constants
|
||||
{ };
|
||||
|
||||
/*! Specific constants for double floating point type
|
||||
*/
|
||||
template <>
|
||||
struct fp_constants<double>
|
||||
{
|
||||
static constexpr const double DIODE_MAXDIFF = 1e100;
|
||||
static constexpr const double DIODE_MAXVOLT = 300.0;
|
||||
|
||||
static constexpr const double TIMESTEP_MAXDIFF = 1e100;
|
||||
static constexpr const double TIMESTEP_MINDIV = 1e-60;
|
||||
};
|
||||
|
||||
/*! Specific constants for float floating point type
|
||||
*/
|
||||
template <>
|
||||
struct fp_constants<float>
|
||||
{
|
||||
static constexpr const float DIODE_MAXDIFF = 1e5;
|
||||
static constexpr const float DIODE_MAXVOLT = 30.0;
|
||||
|
||||
static constexpr const float TIMESTEP_MAXDIFF = 1e30;
|
||||
static constexpr const float TIMESTEP_MINDIV = 1e-8;
|
||||
};
|
||||
} // namespace netlist
|
||||
|
||||
#endif /* NLCONFIG_H_ */
|
||||
|
@ -16,207 +16,215 @@
|
||||
|
||||
namespace plib {
|
||||
|
||||
void pfunction::compile(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
if (plib::startsWith(expr, "rpn:"))
|
||||
compile_postfix(inputs, expr.substr(4));
|
||||
else
|
||||
compile_infix(inputs, expr);
|
||||
}
|
||||
|
||||
void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
std::vector<pstring> cmds(plib::psplit(expr, " "));
|
||||
compile_postfix(inputs, cmds, expr);
|
||||
}
|
||||
|
||||
void pfunction::compile_postfix(const std::vector<pstring> &inputs,
|
||||
const std::vector<pstring> &cmds, const pstring &expr)
|
||||
{
|
||||
m_precompiled.clear();
|
||||
int stk = 0;
|
||||
|
||||
for (const pstring &cmd : cmds)
|
||||
template <typename NT>
|
||||
void pfunction<NT>::compile(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
rpn_inst rc;
|
||||
if (cmd == "+")
|
||||
{ rc.m_cmd = ADD; stk -= 1; }
|
||||
else if (cmd == "-")
|
||||
{ rc.m_cmd = SUB; stk -= 1; }
|
||||
else if (cmd == "*")
|
||||
{ rc.m_cmd = MULT; stk -= 1; }
|
||||
else if (cmd == "/")
|
||||
{ rc.m_cmd = DIV; stk -= 1; }
|
||||
else if (cmd == "pow")
|
||||
{ rc.m_cmd = POW; stk -= 1; }
|
||||
else if (cmd == "sin")
|
||||
{ rc.m_cmd = SIN; stk -= 0; }
|
||||
else if (cmd == "cos")
|
||||
{ rc.m_cmd = COS; stk -= 0; }
|
||||
else if (cmd == "trunc")
|
||||
{ rc.m_cmd = TRUNC; stk -= 0; }
|
||||
else if (cmd == "rand")
|
||||
{ rc.m_cmd = RAND; stk += 1; }
|
||||
if (plib::startsWith(expr, "rpn:"))
|
||||
compile_postfix(inputs, expr.substr(4));
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
if (inputs[i] == cmd)
|
||||
{
|
||||
rc.m_cmd = PUSH_INPUT;
|
||||
rc.m_param = static_cast<double>(i);
|
||||
stk += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rc.m_cmd != PUSH_INPUT)
|
||||
{
|
||||
rc.m_cmd = PUSH_CONST;
|
||||
bool err(false);
|
||||
rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
|
||||
if (err)
|
||||
throw plib::pexception(plib::pfmt("pfunction: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
|
||||
stk += 1;
|
||||
}
|
||||
}
|
||||
if (stk < 1)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr));
|
||||
m_precompiled.push_back(rc);
|
||||
compile_infix(inputs, expr);
|
||||
}
|
||||
if (stk != 1)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack count different to one on <{2}>")(expr));
|
||||
}
|
||||
|
||||
static int get_prio(const pstring &v)
|
||||
{
|
||||
if (v == "(" || v == ")")
|
||||
return 1;
|
||||
else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z")
|
||||
return 0;
|
||||
else if (v == "*" || v == "/")
|
||||
return 20;
|
||||
else if (v == "+" || v == "-")
|
||||
return 10;
|
||||
else if (v == "^")
|
||||
return 30;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
|
||||
{
|
||||
if (stk.size() == 0)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack underflow during infix parsing of: <{1}>")(expr));
|
||||
pstring res = stk.top();
|
||||
stk.pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
// Shunting-yard infix parsing
|
||||
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
|
||||
std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, " ", ""), sep));
|
||||
std::stack<pstring> opstk;
|
||||
std::vector<pstring> postfix;
|
||||
|
||||
for (std::size_t i = 0; i < sexpr.size(); i++)
|
||||
template <typename NT>
|
||||
void pfunction<NT>::compile_postfix(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
pstring &s = sexpr[i];
|
||||
if (s=="(")
|
||||
opstk.push(s);
|
||||
else if (s==")")
|
||||
std::vector<pstring> cmds(plib::psplit(expr, " "));
|
||||
compile_postfix(inputs, cmds, expr);
|
||||
}
|
||||
|
||||
template <typename NT>
|
||||
void pfunction<NT>::compile_postfix(const std::vector<pstring> &inputs,
|
||||
const std::vector<pstring> &cmds, const pstring &expr)
|
||||
{
|
||||
m_precompiled.clear();
|
||||
int stk = 0;
|
||||
|
||||
for (const pstring &cmd : cmds)
|
||||
{
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
rpn_inst rc;
|
||||
if (cmd == "+")
|
||||
{ rc.m_cmd = ADD; stk -= 1; }
|
||||
else if (cmd == "-")
|
||||
{ rc.m_cmd = SUB; stk -= 1; }
|
||||
else if (cmd == "*")
|
||||
{ rc.m_cmd = MULT; stk -= 1; }
|
||||
else if (cmd == "/")
|
||||
{ rc.m_cmd = DIV; stk -= 1; }
|
||||
else if (cmd == "pow")
|
||||
{ rc.m_cmd = POW; stk -= 1; }
|
||||
else if (cmd == "sin")
|
||||
{ rc.m_cmd = SIN; stk -= 0; }
|
||||
else if (cmd == "cos")
|
||||
{ rc.m_cmd = COS; stk -= 0; }
|
||||
else if (cmd == "trunc")
|
||||
{ rc.m_cmd = TRUNC; stk -= 0; }
|
||||
else if (cmd == "rand")
|
||||
{ rc.m_cmd = RAND; stk += 1; }
|
||||
else
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
}
|
||||
else if (s==",")
|
||||
{
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
opstk.push(x);
|
||||
}
|
||||
else {
|
||||
int p = get_prio(s);
|
||||
if (p>0)
|
||||
{
|
||||
if (opstk.size() == 0)
|
||||
opstk.push(s);
|
||||
else
|
||||
for (std::size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
if (get_prio(opstk.top()) >= get_prio(s))
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
opstk.push(s);
|
||||
if (inputs[i] == cmd)
|
||||
{
|
||||
rc.m_cmd = PUSH_INPUT;
|
||||
rc.m_param = static_cast<double>(i);
|
||||
stk += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rc.m_cmd != PUSH_INPUT)
|
||||
{
|
||||
rc.m_cmd = PUSH_CONST;
|
||||
bool err(false);
|
||||
rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
|
||||
if (err)
|
||||
throw plib::pexception(plib::pfmt("pfunction: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
|
||||
stk += 1;
|
||||
}
|
||||
}
|
||||
else if (p == 0) // Function or variable
|
||||
if (stk < 1)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr));
|
||||
m_precompiled.push_back(rc);
|
||||
}
|
||||
if (stk != 1)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack count different to one on <{2}>")(expr));
|
||||
}
|
||||
|
||||
static int get_prio(const pstring &v)
|
||||
{
|
||||
if (v == "(" || v == ")")
|
||||
return 1;
|
||||
else if (plib::left(v, 1) >= "a" && plib::left(v, 1) <= "z")
|
||||
return 0;
|
||||
else if (v == "*" || v == "/")
|
||||
return 20;
|
||||
else if (v == "+" || v == "-")
|
||||
return 10;
|
||||
else if (v == "^")
|
||||
return 30;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
|
||||
{
|
||||
if (stk.size() == 0)
|
||||
throw plib::pexception(plib::pfmt("pfunction: stack underflow during infix parsing of: <{1}>")(expr));
|
||||
pstring res = stk.top();
|
||||
stk.pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename NT>
|
||||
void pfunction<NT>::compile_infix(const std::vector<pstring> &inputs, const pstring &expr)
|
||||
{
|
||||
// Shunting-yard infix parsing
|
||||
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
|
||||
std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, " ", ""), sep));
|
||||
std::stack<pstring> opstk;
|
||||
std::vector<pstring> postfix;
|
||||
|
||||
for (std::size_t i = 0; i < sexpr.size(); i++)
|
||||
{
|
||||
pstring &s = sexpr[i];
|
||||
if (s=="(")
|
||||
opstk.push(s);
|
||||
else if (s==")")
|
||||
{
|
||||
if (sexpr[i+1] == "(")
|
||||
opstk.push(s);
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
}
|
||||
else if (s==",")
|
||||
{
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
opstk.push(x);
|
||||
}
|
||||
else {
|
||||
int p = get_prio(s);
|
||||
if (p>0)
|
||||
{
|
||||
if (opstk.size() == 0)
|
||||
opstk.push(s);
|
||||
else
|
||||
{
|
||||
if (get_prio(opstk.top()) >= get_prio(s))
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
opstk.push(s);
|
||||
}
|
||||
}
|
||||
else if (p == 0) // Function or variable
|
||||
{
|
||||
if (sexpr[i+1] == "(")
|
||||
opstk.push(s);
|
||||
else
|
||||
postfix.push_back(s);
|
||||
}
|
||||
else
|
||||
postfix.push_back(s);
|
||||
}
|
||||
else
|
||||
postfix.push_back(s);
|
||||
}
|
||||
}
|
||||
while (opstk.size() > 0)
|
||||
{
|
||||
postfix.push_back(opstk.top());
|
||||
opstk.pop();
|
||||
}
|
||||
compile_postfix(inputs, postfix, expr);
|
||||
}
|
||||
|
||||
|
||||
#define ST1 stack[ptr]
|
||||
#define ST2 stack[ptr-1]
|
||||
|
||||
#define OP(OP, ADJ, EXPR) \
|
||||
case OP: \
|
||||
ptr-= (ADJ); \
|
||||
stack[ptr-1] = (EXPR); \
|
||||
break;
|
||||
|
||||
double pfunction::evaluate(const std::vector<double> &values) noexcept
|
||||
{
|
||||
std::array<double, 20> stack = { 0 };
|
||||
unsigned ptr = 0;
|
||||
stack[0] = 0.0;
|
||||
for (auto &rc : m_precompiled)
|
||||
{
|
||||
switch (rc.m_cmd)
|
||||
while (opstk.size() > 0)
|
||||
{
|
||||
OP(ADD, 1, ST2 + ST1)
|
||||
OP(MULT, 1, ST2 * ST1)
|
||||
OP(SUB, 1, ST2 - ST1)
|
||||
OP(DIV, 1, ST2 / ST1)
|
||||
OP(POW, 1, std::pow(ST2, ST1))
|
||||
OP(SIN, 0, std::sin(ST2))
|
||||
OP(COS, 0, std::cos(ST2))
|
||||
OP(TRUNC, 0, std::trunc(ST2))
|
||||
case RAND:
|
||||
stack[ptr++] = lfsr_random();
|
||||
break;
|
||||
case PUSH_INPUT:
|
||||
stack[ptr++] = values[static_cast<unsigned>(rc.m_param)];
|
||||
break;
|
||||
case PUSH_CONST:
|
||||
stack[ptr++] = rc.m_param;
|
||||
break;
|
||||
postfix.push_back(opstk.top());
|
||||
opstk.pop();
|
||||
}
|
||||
compile_postfix(inputs, postfix, expr);
|
||||
}
|
||||
return stack[ptr-1];
|
||||
}
|
||||
|
||||
|
||||
#define ST1 stack[ptr]
|
||||
#define ST2 stack[ptr-1]
|
||||
|
||||
#define OP(OP, ADJ, EXPR) \
|
||||
case OP: \
|
||||
ptr-= (ADJ); \
|
||||
stack[ptr-1] = (EXPR); \
|
||||
break;
|
||||
|
||||
template <typename NT>
|
||||
NT pfunction<NT>::evaluate(const std::vector<NT> &values) noexcept
|
||||
{
|
||||
std::array<NT, 20> stack = { 0 };
|
||||
unsigned ptr = 0;
|
||||
stack[0] = 0.0;
|
||||
for (auto &rc : m_precompiled)
|
||||
{
|
||||
switch (rc.m_cmd)
|
||||
{
|
||||
OP(ADD, 1, ST2 + ST1)
|
||||
OP(MULT, 1, ST2 * ST1)
|
||||
OP(SUB, 1, ST2 - ST1)
|
||||
OP(DIV, 1, ST2 / ST1)
|
||||
OP(POW, 1, std::pow(ST2, ST1))
|
||||
OP(SIN, 0, std::sin(ST2))
|
||||
OP(COS, 0, std::cos(ST2))
|
||||
OP(TRUNC, 0, std::trunc(ST2))
|
||||
case RAND:
|
||||
stack[ptr++] = lfsr_random();
|
||||
break;
|
||||
case PUSH_INPUT:
|
||||
stack[ptr++] = values[static_cast<unsigned>(rc.m_param)];
|
||||
break;
|
||||
case PUSH_CONST:
|
||||
stack[ptr++] = rc.m_param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stack[ptr-1];
|
||||
}
|
||||
|
||||
template struct pfunction<float>;
|
||||
template struct pfunction<double>;
|
||||
|
||||
} // namespace plib
|
||||
|
@ -21,7 +21,9 @@ namespace plib {
|
||||
|
||||
/*! Class providing support for evaluating expressions
|
||||
*
|
||||
* @tparam NT Number type, should be float or double
|
||||
*/
|
||||
template <typename NT>
|
||||
class pfunction
|
||||
{
|
||||
enum rpn_cmd
|
||||
@ -42,7 +44,7 @@ namespace plib {
|
||||
{
|
||||
rpn_inst() : m_cmd(ADD), m_param(0.0) { }
|
||||
rpn_cmd m_cmd;
|
||||
double m_param;
|
||||
NT m_param;
|
||||
};
|
||||
public:
|
||||
/*! Constructor with state saving support
|
||||
@ -91,20 +93,20 @@ namespace plib {
|
||||
* @param values for input variables, e.g. {1.1, 2.2}
|
||||
* @return value of expression
|
||||
*/
|
||||
double evaluate(const std::vector<double> &values) noexcept;
|
||||
NT evaluate(const std::vector<NT> &values) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
void compile_postfix(const std::vector<pstring> &inputs,
|
||||
const std::vector<pstring> &cmds, const pstring &expr);
|
||||
|
||||
double lfsr_random() noexcept
|
||||
NT lfsr_random() noexcept
|
||||
{
|
||||
std::uint16_t lsb = m_lfsr & 1;
|
||||
m_lfsr >>= 1;
|
||||
if (lsb)
|
||||
m_lfsr ^= 0xB400u; // taps 15, 13, 12, 10
|
||||
return static_cast<double>(m_lfsr) / static_cast<double>(0xffffu);
|
||||
return static_cast<NT>(m_lfsr) / static_cast<NT>(0xffffu);
|
||||
}
|
||||
|
||||
std::vector<rpn_inst> m_precompiled; //!< precompiled expression
|
||||
@ -112,6 +114,8 @@ namespace plib {
|
||||
std::uint16_t m_lfsr; //!< lfsr used for generating random numbers
|
||||
};
|
||||
|
||||
extern template struct pfunction<float>;
|
||||
extern template struct pfunction<double>;
|
||||
|
||||
} // namespace plib
|
||||
|
||||
|
@ -311,11 +311,14 @@ struct input_t
|
||||
: m_value(0.0)
|
||||
{
|
||||
std::array<char, 400> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
nl_fptype t(0);
|
||||
double t(0);
|
||||
double val(0);
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
||||
int e = std::sscanf(line.c_str(), "%lf,%[^,],%lf", &t, buf.data(), &m_value);
|
||||
int e = std::sscanf(line.c_str(), "%lf,%[^,],%lf", &t, buf.data(), &val);
|
||||
if (e != 3)
|
||||
throw netlist::nl_exception(plib::pfmt("error {1} scanning line {2}\n")(e)(line));
|
||||
m_value = static_cast<nl_fptype>(val);
|
||||
m_time = netlist::netlist_time::from_double(t);
|
||||
m_param = setup.find_param(pstring(buf.data()), true);
|
||||
}
|
||||
|
@ -565,7 +565,7 @@ namespace solver
|
||||
//const nl_fptype DD_n = (n->Q_Analog() - t->m_last_V);
|
||||
// avoid floating point exceptions
|
||||
|
||||
const nl_fptype DD_n = std::max(-1e100, std::min(1e100,(t.getV() - m_last_V[k])));
|
||||
const nl_fptype DD_n = std::max(-fp_constants<nl_fptype>::TIMESTEP_MAXDIFF, std::min(fp_constants<nl_fptype>::TIMESTEP_MAXDIFF,(t.getV() - m_last_V[k])));
|
||||
const nl_fptype hn = cur_ts;
|
||||
|
||||
//printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1);
|
||||
@ -574,7 +574,7 @@ namespace solver
|
||||
|
||||
m_h_n_m_1[k] = hn;
|
||||
m_DD_n_m_1[k] = DD_n;
|
||||
if (std::fabs(DD2) > plib::constants<nl_fptype>::cast(1e-60)) // avoid div-by-zero
|
||||
if (std::fabs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV) // avoid div-by-zero
|
||||
new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(plib::constants<nl_fptype>::cast(0.5)*DD2));
|
||||
else
|
||||
new_net_timestep = m_params.m_max_timestep;
|
||||
|
@ -383,7 +383,7 @@ namespace solver
|
||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gonn;
|
||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gtn;
|
||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn;
|
||||
plib::pmatrix2d<nl_fptype *, aligned_alloc<nl_fptype *>> m_mat_ptr;
|
||||
plib::pmatrix2d<nl_mat_fptype *, aligned_alloc<nl_mat_fptype *>> m_mat_ptr;
|
||||
plib::pmatrix2d<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn;
|
||||
|
||||
plib::aligned_vector<terms_for_net_t> m_terms;
|
||||
@ -439,9 +439,10 @@ namespace solver
|
||||
*/
|
||||
|
||||
const std::size_t iN = this->m_terms.size();
|
||||
typename std::decay<decltype(V[0])>::type cerr = 0;
|
||||
using vtype = typename std::decay<decltype(V[0])>::type;
|
||||
vtype cerr = 0;
|
||||
for (std::size_t i = 0; i < iN; i++)
|
||||
cerr = std::max(cerr, std::abs(V[i] - this->m_terms[i].getV()));
|
||||
cerr = std::max(cerr, std::abs(V[i] - static_cast<vtype>(this->m_terms[i].getV())));
|
||||
return cerr;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ namespace solver
|
||||
|
||||
mat_type mat;
|
||||
|
||||
plib::dynproc<void, nl_fptype * , nl_fptype * , nl_fptype * > m_proc;
|
||||
plib::dynproc<void, FT * , FT * , FT * > m_proc;
|
||||
|
||||
};
|
||||
|
||||
|
@ -79,9 +79,9 @@ namespace solver
|
||||
float_type RHS_t = 0.0;
|
||||
|
||||
const std::size_t term_count = this->m_terms[k].count();
|
||||
const float_type * const gt = this->m_gtn[k];
|
||||
const float_type * const go = this->m_gonn[k];
|
||||
const float_type * const Idr = this->m_Idrn[k];
|
||||
const nl_fptype * const gt = this->m_gtn[k];
|
||||
const nl_fptype * const go = this->m_gonn[k];
|
||||
const nl_fptype * const Idr = this->m_Idrn[k];
|
||||
auto other_cur_analog = this->m_connected_net_Vn[k];
|
||||
|
||||
this->m_new_V[k] = this->m_terms[k].getV();
|
||||
@ -130,7 +130,7 @@ namespace solver
|
||||
{
|
||||
const int * net_other = this->m_terms[k].m_connected_net_idx.data();
|
||||
const std::size_t railstart = this->m_terms[k].railstart();
|
||||
const float_type * go = this->m_gonn[k];
|
||||
const nl_fptype * go = this->m_gonn[k];
|
||||
|
||||
float_type Idrive = 0.0;
|
||||
for (std::size_t i = 0; i < railstart; i++)
|
||||
|
@ -231,62 +231,62 @@ namespace devices
|
||||
switch (net_count)
|
||||
{
|
||||
case 1:
|
||||
ms = plib::make_unique<solver::matrix_solver_direct1_t<nl_fptype>>(state(), sname, grp, &m_params);
|
||||
ms = plib::make_unique<solver::matrix_solver_direct1_t<nl_mat_fptype>>(state(), sname, grp, &m_params);
|
||||
break;
|
||||
case 2:
|
||||
ms = plib::make_unique<solver::matrix_solver_direct2_t<nl_fptype>>(state(), sname, grp, &m_params);
|
||||
ms = plib::make_unique<solver::matrix_solver_direct2_t<nl_mat_fptype>>(state(), sname, grp, &m_params);
|
||||
break;
|
||||
#if 0
|
||||
case 3:
|
||||
ms = create_solver<nl_fptype, 3>(3, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 3>(3, sname, grp);
|
||||
break;
|
||||
case 4:
|
||||
ms = create_solver<nl_fptype, 4>(4, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 4>(4, sname, grp);
|
||||
break;
|
||||
case 5:
|
||||
ms = create_solver<nl_fptype, 5>(5, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 5>(5, sname, grp);
|
||||
break;
|
||||
case 6:
|
||||
ms = create_solver<nl_fptype, 6>(6, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 6>(6, sname, grp);
|
||||
break;
|
||||
case 7:
|
||||
ms = create_solver<nl_fptype, 7>(7, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 7>(7, sname, grp);
|
||||
break;
|
||||
case 8:
|
||||
ms = create_solver<nl_fptype, 8>(8, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 8>(8, sname, grp);
|
||||
break;
|
||||
case 9:
|
||||
ms = create_solver<nl_fptype, 9>(9, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 9>(9, sname, grp);
|
||||
break;
|
||||
case 10:
|
||||
ms = create_solver<nl_fptype, 10>(10, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 10>(10, sname, grp);
|
||||
break;
|
||||
#if 0
|
||||
case 11:
|
||||
ms = create_solver<nl_fptype, 11>(11, sname);
|
||||
ms = create_solver<nl_mat_fptype, 11>(11, sname);
|
||||
break;
|
||||
case 12:
|
||||
ms = create_solver<nl_fptype, 12>(12, sname);
|
||||
ms = create_solver<nl_mat_fptype, 12>(12, sname);
|
||||
break;
|
||||
case 15:
|
||||
ms = create_solver<nl_fptype, 15>(15, sname);
|
||||
ms = create_solver<nl_mat_fptype, 15>(15, sname);
|
||||
break;
|
||||
case 31:
|
||||
ms = create_solver<nl_fptype, 31>(31, sname);
|
||||
ms = create_solver<nl_mat_fptype, 31>(31, sname);
|
||||
break;
|
||||
case 35:
|
||||
ms = create_solver<nl_fptype, 35>(35, sname);
|
||||
ms = create_solver<nl_mat_fptype, 35>(35, sname);
|
||||
break;
|
||||
case 43:
|
||||
ms = create_solver<nl_fptype, 43>(43, sname);
|
||||
ms = create_solver<nl_mat_fptype, 43>(43, sname);
|
||||
break;
|
||||
case 49:
|
||||
ms = create_solver<nl_fptype, 49>(49, sname);
|
||||
ms = create_solver<nl_mat_fptype, 49>(49, sname);
|
||||
break;
|
||||
#endif
|
||||
#if 1
|
||||
case 87:
|
||||
ms = create_solver<nl_fptype,86>(86, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype,86>(86, sname, grp);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
@ -294,35 +294,35 @@ namespace devices
|
||||
log().info(MI_NO_SPECIFIC_SOLVER(net_count));
|
||||
if (net_count <= 8)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -8>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -8>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 16)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -16>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -16>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 32)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -32>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -32>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 64)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -64>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -64>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 128)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -128>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -128>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 256)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -256>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -256>(net_count, sname, grp);
|
||||
}
|
||||
else if (net_count <= 512)
|
||||
{
|
||||
ms = create_solver<nl_fptype, -512>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, -512>(net_count, sname, grp);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms = create_solver<nl_fptype, 0>(net_count, sname, grp);
|
||||
ms = create_solver<nl_mat_fptype, 0>(net_count, sname, grp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user