diff options
Diffstat (limited to 'src/lib/netlist/plib/pfunction.cpp')
-rw-r--r-- | src/lib/netlist/plib/pfunction.cpp | 131 |
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>; |