mirror of
https://github.com/holub/mame
synced 2025-06-25 05:44:23 +03:00
netlist: Add parse optimization to pfunction.
* "(1 + 2)*a" now during parse step will be rewritten to "3*a".
This commit is contained in:
parent
58b4e89c0c
commit
1dcedeee9d
@ -157,6 +157,7 @@ namespace plib {
|
|||||||
}
|
}
|
||||||
if (stk != 1)
|
if (stk != 1)
|
||||||
throw pexception(plib::pfmt("pfunction: stack count {1} different to one on <{2}>")(stk, expr));
|
throw pexception(plib::pfmt("pfunction: stack count {1} different to one on <{2}>")(stk, expr));
|
||||||
|
compress();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_number(const pstring &n)
|
static bool is_number(const pstring &n)
|
||||||
@ -339,25 +340,29 @@ namespace plib {
|
|||||||
return narrow_cast<NT>(lfsr);
|
return narrow_cast<NT>(lfsr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#define ST0 stack[ptr+1]
|
#define ST0 *(ptr+1)
|
||||||
#define ST1 stack[ptr]
|
#define ST1 *ptr
|
||||||
#define ST2 stack[ptr-1]
|
#define ST2 *(ptr-1)
|
||||||
|
|
||||||
#define OP(OP, ADJ, EXPR) \
|
#define OP(OP, ADJ, EXPR) \
|
||||||
case OP: \
|
case OP: \
|
||||||
ptr-= (ADJ); \
|
ptr-= (ADJ); \
|
||||||
stack[ptr-1] = (EXPR); \
|
*(ptr-1) = (EXPR); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
#define OP0(OP, EXPR) \
|
||||||
|
case OP: \
|
||||||
|
*(ptr++) = (EXPR); \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
template <typename NT>
|
template <typename NT>
|
||||||
NT pfunction<NT>::evaluate(const values_container &values) noexcept
|
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;
|
||||||
unsigned ptr = 0;
|
value_type *ptr = stack.data();
|
||||||
constexpr auto zero = plib::constants<value_type>::zero();
|
constexpr const auto zero = plib::constants<value_type>::zero();
|
||||||
constexpr auto one = plib::constants<value_type>::one();
|
constexpr const auto one = plib::constants<value_type>::one();
|
||||||
stack[0] = plib::constants<value_type>::zero();
|
for (const auto &rc : m_precompiled)
|
||||||
for (auto &rc : m_precompiled)
|
|
||||||
{
|
{
|
||||||
switch (rc.m_cmd)
|
switch (rc.m_cmd)
|
||||||
{
|
{
|
||||||
@ -379,23 +384,92 @@ namespace plib {
|
|||||||
OP(COS, 0, plib::cos(ST2))
|
OP(COS, 0, plib::cos(ST2))
|
||||||
OP(MAX, 1, std::max(ST2, ST1))
|
OP(MAX, 1, std::max(ST2, ST1))
|
||||||
OP(MIN, 1, std::min(ST2, ST1))
|
OP(MIN, 1, std::min(ST2, ST1))
|
||||||
OP(TRUNC, 0, plib::trunc(ST2))
|
OP(TRUNC, 0, plib::trunc(ST2))
|
||||||
case RAND:
|
OP0(RAND, lfsr_random<value_type>(m_lfsr))
|
||||||
stack[ptr++] = lfsr_random<value_type>(m_lfsr);
|
OP0(PUSH_INPUT, values[rc.m_param.index])
|
||||||
break;
|
OP0(PUSH_CONST, rc.m_param.val)
|
||||||
case PUSH_INPUT:
|
|
||||||
stack[ptr++] = values[rc.m_param.index];
|
|
||||||
break;
|
|
||||||
case PUSH_CONST:
|
|
||||||
stack[ptr++] = rc.m_param.val;
|
|
||||||
break;
|
|
||||||
// please compiler
|
// please compiler
|
||||||
case LP:
|
case LP:
|
||||||
case RP:
|
case RP:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stack[ptr-1];
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("func %lld %lld\n", m_precompiled.size(), n);
|
||||||
|
m_precompiled.resize(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template class pfunction<float>;
|
template class pfunction<float>;
|
||||||
|
@ -62,6 +62,10 @@ namespace plib {
|
|||||||
{
|
{
|
||||||
m_param.val = plib::constants<NT>::zero();
|
m_param.val = plib::constants<NT>::zero();
|
||||||
}
|
}
|
||||||
|
rpn_inst(NT v) : m_cmd(PUSH_CONST)
|
||||||
|
{
|
||||||
|
m_param.val = v;
|
||||||
|
}
|
||||||
rpn_cmd m_cmd;
|
rpn_cmd m_cmd;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -138,6 +142,7 @@ namespace plib {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void compress();
|
||||||
void compile_postfix(const inputs_container &inputs,
|
void compile_postfix(const inputs_container &inputs,
|
||||||
const std::vector<pstring> &cmds, const pstring &expr);
|
const std::vector<pstring> &cmds, const pstring &expr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user