summaryrefslogtreecommitdiffstats
path: root/src/lib/netlist/plib/pfunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/pfunction.cpp')
-rw-r--r--src/lib/netlist/plib/pfunction.cpp131
1 files changed, 101 insertions, 30 deletions
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 3ab937735cf..0cf4fc4cdc2 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -118,7 +118,7 @@ namespace plib {
auto p = pcmds().find(cmd);
if (p != pcmds().end())
{
- rc.m_cmd = p->second.cmd;
+ rc = rpn_inst(p->second.cmd);
stk -= p->second.adj;
}
else
@@ -127,23 +127,20 @@ namespace plib {
{
if (inputs[i] == cmd)
{
- rc.m_cmd = PUSH_INPUT;
- rc.m_param.index = i;
+ rc = rpn_inst(PUSH_INPUT, i);
stk += 1;
break;
}
}
- if (rc.m_cmd != PUSH_INPUT)
+ if (rc.cmd() != PUSH_INPUT)
{
- using fl_t = decltype(rc.m_param.val);
- rc.m_cmd = PUSH_CONST;
bool err(false);
auto rs(plib::right(cmd,1));
- auto r=units_si<fl_t>().find(rs);
- if (r == units_si<fl_t>().end())
- rc.m_param.val = plib::pstonum_ne<fl_t>(cmd, err);
+ auto r=units_si<NT>().find(rs);
+ if (r == units_si<NT>().end())
+ rc = rpn_inst(plib::pstonum_ne<NT>(cmd, err));
else
- rc.m_param.val = plib::pstonum_ne<fl_t>(plib::left(cmd, cmd.length()-1), err) * r->second;
+ 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));
stk += 1;
@@ -157,6 +154,7 @@ namespace plib {
}
if (stk != 1)
throw pexception(plib::pfmt("pfunction: stack count {1} different to one on <{2}>")(stk, expr));
+ compress();
}
static bool is_number(const pstring &n)
@@ -339,27 +337,105 @@ namespace plib {
return narrow_cast<NT>(lfsr);
}
#endif
- #define ST0 stack[ptr+1]
- #define ST1 stack[ptr]
- #define ST2 stack[ptr-1]
+ #define ST0 *(ptr+1)
+ #define ST1 *ptr
+ #define ST2 *(ptr-1)
#define OP(OP, ADJ, EXPR) \
case OP: \
ptr-= (ADJ); \
- stack[ptr-1] = (EXPR); \
+ *(ptr-1) = (EXPR); \
+ break;
+
+ #define OP0(OP, EXPR) \
+ case OP: \
+ *(ptr++) = (EXPR); \
break;
template <typename NT>
NT pfunction<NT>::evaluate(const values_container &values) noexcept
{
- std::array<value_type, MAX_STACK> stack = { plib::constants<value_type>::zero() };
+ std::array<value_type, MAX_STACK> stack; // NOLINT
+ value_type *ptr = stack.data();
+ constexpr const auto zero = plib::constants<value_type>::zero();
+ constexpr const auto one = plib::constants<value_type>::one();
+ for (const auto &rc : m_precompiled)
+ {
+ switch (rc.cmd())
+ {
+ OP(ADD, 1, ST2 + ST1)
+ OP(MULT, 1, ST2 * ST1)
+ OP(SUB, 1, ST2 - ST1)
+ OP(DIV, 1, ST2 / ST1)
+ OP(EQ, 1, ST2 == ST1 ? one : zero)
+ OP(NE, 1, ST2 != ST1 ? one : zero)
+ OP(GT, 1, ST2 > ST1 ? one : zero)
+ OP(LT, 1, ST2 < ST1 ? one : zero)
+ OP(LE, 1, ST2 <= ST1 ? one : zero)
+ OP(GE, 1, ST2 >= ST1 ? one : zero)
+ OP(IF, 2, (ST2 != zero) ? ST1 : ST0)
+ OP(NEG, 0, -ST2)
+ OP(POW, 1, plib::pow(ST2, ST1))
+ OP(LOG, 0, plib::log(ST2))
+ OP(SIN, 0, plib::sin(ST2))
+ OP(COS, 0, plib::cos(ST2))
+ OP(MAX, 1, std::max(ST2, ST1))
+ OP(MIN, 1, std::min(ST2, ST1))
+ OP(TRUNC, 0, plib::trunc(ST2))
+ OP0(RAND, lfsr_random<value_type>(m_lfsr))
+ OP0(PUSH_INPUT, values[rc.index()])
+ OP0(PUSH_CONST, rc.value())
+ // please compiler
+ case LP:
+ case RP:
+ break;
+ }
+ }
+ return *(ptr-1);
+ }
+
+#undef ST0
+#undef ST1
+#undef ST2
+#undef OP
+#undef OP0
+
+#define ST0 m_precompiled[ptr+0].value()
+#define ST1 m_precompiled[ptr-1].value()
+#define ST2 m_precompiled[ptr-2].value()
+
+#define OP(OP, ADJ, EXPR) \
+ case OP: \
+ if (ADJ == 2) {\
+ if (m_precompiled[ptr-3].cmd() == PUSH_CONST && m_precompiled[ptr-2].cmd() == PUSH_CONST && m_precompiled[ptr-1].cmd() == PUSH_CONST) \
+ { ptr--; m_precompiled[ptr-2] = rpn_inst(EXPR); n -= 3; ptr++; std::copy(m_precompiled.begin()+(ptr+1), m_precompiled.end(), m_precompiled.begin()+(ptr-2)); ptr-=2;} \
+ else { ptr++; } \
+ } else if (ADJ == 1) {\
+ if (m_precompiled[ptr-2].cmd() == PUSH_CONST && m_precompiled[ptr-1].cmd() == PUSH_CONST) \
+ { m_precompiled[ptr-2] = rpn_inst(EXPR); n -= 2; std::copy(m_precompiled.begin()+(ptr+1), m_precompiled.end(), m_precompiled.begin()+(ptr-1)); ptr--;} \
+ else { ptr++; } \
+ } else if (ADJ == 0) {\
+ if (m_precompiled[ptr-1].cmd() == PUSH_CONST) \
+ { ptr++; m_precompiled[ptr-2] = rpn_inst(EXPR); n -= 1; ptr--; std::copy(m_precompiled.begin()+(ptr+1), m_precompiled.end(), m_precompiled.begin()+(ptr)); } \
+ else { ptr++; } \
+ } else ptr++; \
+ break;
+
+#define OP0(OP, EXPR) \
+ case OP: \
+ ptr++; \
+ break;
+
+ template <typename NT>
+ void pfunction<NT>::compress()
+ {
+ constexpr const auto zero = plib::constants<value_type>::zero();
+ constexpr const auto one = plib::constants<value_type>::one();
unsigned ptr = 0;
- constexpr auto zero = plib::constants<value_type>::zero();
- constexpr auto one = plib::constants<value_type>::one();
- stack[0] = plib::constants<value_type>::zero();
- for (auto &rc : m_precompiled)
+ auto n = m_precompiled.size();
+ for (; ptr < n; )
{
- switch (rc.m_cmd)
+ switch (m_precompiled[ptr].cmd())
{
OP(ADD, 1, ST2 + ST1)
OP(MULT, 1, ST2 * ST1)
@@ -380,22 +456,17 @@ namespace plib {
OP(MAX, 1, std::max(ST2, ST1))
OP(MIN, 1, std::min(ST2, ST1))
OP(TRUNC, 0, plib::trunc(ST2))
- case RAND:
- stack[ptr++] = lfsr_random<value_type>(m_lfsr);
- break;
- case PUSH_INPUT:
- stack[ptr++] = values[rc.m_param.index];
- break;
- case PUSH_CONST:
- stack[ptr++] = rc.m_param.val;
- break;
+ OP0(RAND, lfsr_random<value_type>(m_lfsr))
+ OP0(PUSH_INPUT, values[rc.index()])
+ OP0(PUSH_CONST, rc.value())
// please compiler
case LP:
case RP:
break;
}
}
- return stack[ptr-1];
+ //printf("func %lld %lld\n", m_precompiled.size(), n);
+ m_precompiled.resize(n);
}
template class pfunction<float>;