summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2020-10-02 19:33:22 +0200
committer couriersud <couriersud@gmx.org>2020-10-02 19:58:29 +0200
commit1dcedeee9dffdad500c8a85ffe8878a762261e4d (patch)
tree256142695ccd56bf994c300e54072d9e1cc55120
parent58b4e89c0c724fba2bea87e32054059bd8b17f66 (diff)
netlist: Add parse optimization to pfunction.
* "(1 + 2)*a" now during parse step will be rewritten to "3*a".
-rw-r--r--src/lib/netlist/plib/pfunction.cpp114
-rw-r--r--src/lib/netlist/plib/pfunction.h5
2 files changed, 99 insertions, 20 deletions
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 3ab937735cf..c424c483449 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -157,6 +157,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,25 +340,29 @@ 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() };
- 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)
+ std::array<value_type, MAX_STACK> stack;
+ 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.m_cmd)
{
@@ -379,23 +384,92 @@ namespace plib {
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))
- 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;
+ OP(TRUNC, 0, plib::trunc(ST2))
+ OP0(RAND, lfsr_random<value_type>(m_lfsr))
+ OP0(PUSH_INPUT, values[rc.m_param.index])
+ OP0(PUSH_CONST, rc.m_param.val)
+ // 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].m_param.val
+#define ST1 m_precompiled[ptr-1].m_param.val
+#define ST2 m_precompiled[ptr-2].m_param.val
+
+#define OP(OP, ADJ, EXPR) \
+ case OP: \
+ if (ADJ == 2) {\
+ if (m_precompiled[ptr-3].m_cmd == PUSH_CONST && m_precompiled[ptr-2].m_cmd == PUSH_CONST && m_precompiled[ptr-1].m_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].m_cmd == PUSH_CONST && m_precompiled[ptr-1].m_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].m_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;
+ auto n = m_precompiled.size();
+ for (; ptr < n; )
+ {
+ switch (m_precompiled[ptr].m_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.m_param.index])
+ OP0(PUSH_CONST, rc.m_param.val)
// 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>;
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index 0178e81c04e..d694cbe6a89 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -62,6 +62,10 @@ namespace plib {
{
m_param.val = plib::constants<NT>::zero();
}
+ rpn_inst(NT v) : m_cmd(PUSH_CONST)
+ {
+ m_param.val = v;
+ }
rpn_cmd m_cmd;
union
{
@@ -138,6 +142,7 @@ namespace plib {
private:
+ void compress();
void compile_postfix(const inputs_container &inputs,
const std::vector<pstring> &cmds, const pstring &expr);