diff options
author | 2019-11-10 19:54:26 +0100 | |
---|---|---|
committer | 2019-11-10 19:54:26 +0100 | |
commit | b8c43342d531b0bd30f8db30174f7bd1cdaa19fa (patch) | |
tree | a7e6fa34b528fb0455e601f1911797b8502ca13a /src/lib/netlist/plib/pfunction.cpp | |
parent | a5f06c769538d39c8171154a798ac997a4cb3c6e (diff) |
netlist: first steps on the way to calculated parameters. [Couriersud]
This commit is a first step towards using formulas in parameters, i.e.
MAINCLOCK(clock, 20 * 30)
The intention is to improve readability and scalability.
Since device registration already provides all necessary information
about parameters, the code to create an include file for all
devices has been improved. Long term, this will remove the need for
device specific header files.
In addition going forward devices will accept either no connections or
all specified connections, i.e.
TTL_7400_NAND(name, chip1.2, chip2.3)
or
TTL_7400_NAND(name)
NET_C(...)
NET_C(...)
This will allow to remove all duplicate definitions which are currently
necessary, i.e. TTL_7400_NAND/TTL_7400_GATE
Diffstat (limited to 'src/lib/netlist/plib/pfunction.cpp')
-rw-r--r-- | src/lib/netlist/plib/pfunction.cpp | 87 |
1 files changed, 80 insertions, 7 deletions
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp index a1530a5590e..6f563ee9bbf 100644 --- a/src/lib/netlist/plib/pfunction.cpp +++ b/src/lib/netlist/plib/pfunction.cpp @@ -10,20 +10,21 @@ #include "putil.h" #include <stack> +#include <type_traits> namespace plib { template <typename NT> - void pfunction<NT>::compile(const std::vector<pstring> &inputs, const pstring &expr) + void pfunction<NT>::compile(const pstring &expr, const std::vector<pstring> &inputs) { if (plib::startsWith(expr, "rpn:")) - compile_postfix(inputs, expr.substr(4)); + compile_postfix(expr.substr(4), inputs); else - compile_infix(inputs, expr); + compile_infix(expr, inputs); } template <typename NT> - void pfunction<NT>::compile_postfix(const std::vector<pstring> &inputs, const pstring &expr) + void pfunction<NT>::compile_postfix(const pstring &expr, const std::vector<pstring> &inputs) { std::vector<pstring> cmds(plib::psplit(expr, " ")); compile_postfix(inputs, cmds, expr); @@ -113,13 +114,61 @@ namespace plib { } template <typename NT> - void pfunction<NT>::compile_infix(const std::vector<pstring> &inputs, const pstring &expr) + void pfunction<NT>::compile_infix(const pstring &expr, const std::vector<pstring> &inputs) { // Shunting-yard infix parsing std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"}; - std::vector<pstring> sexpr(plib::psplit(plib::replace_all(expr, " ", ""), sep)); + std::vector<pstring> sexpr1(plib::psplit(plib::replace_all(expr, " ", ""), sep)); std::stack<pstring> opstk; std::vector<pstring> postfix; + std::vector<pstring> sexpr; + + // FIXME: We really need to switch to ptokenizer and fix negative number + // handling in ptokenizer. + + // Fix numbers + for (std::size_t i = 0; i < sexpr1.size(); ) + { + if ((i == 0) && (sexpr1.size() > 1) && (sexpr1[0] == "-") + && (plib::left(sexpr1[1],1) >= "0") && (plib::left(sexpr1[1],1) <= "9")) + { + if (sexpr1.size() < 4) + { + sexpr.push_back(sexpr1[0] + sexpr1[1]); + i+=2; + } + else + { + auto r(plib::right(sexpr1[1], 1)); + auto ne(sexpr1[2]); + if ((r == "e" || r == "E") && (ne == "-" || ne == "+")) + { + sexpr.push_back(sexpr1[0] + sexpr1[1] + ne + sexpr1[3]); + i+=4; + } + else + { + sexpr.push_back(sexpr1[0] + sexpr1[1]); + i+=2; + } + } + } + else if (i + 2 < sexpr1.size() && sexpr1[i].length() > 1) + { + auto l(plib::left(sexpr1[i], 1)); + auto r(plib::right(sexpr1[i], 1)); + auto ne(sexpr1[i+1]); + if ((l >= "0") && (l <= "9") && (r == "e" || r == "E") && (ne == "-" || ne == "+")) + { + sexpr.push_back(sexpr1[i] + ne + sexpr1[i+2]); + i+=3; + } + else + sexpr.push_back(sexpr1[i++]); + } + else + sexpr.push_back(sexpr1[i++]); + } for (std::size_t i = 0; i < sexpr.size(); i++) { @@ -176,9 +225,33 @@ namespace plib { postfix.push_back(opstk.top()); opstk.pop(); } + //printf("e : %s\n", expr.c_str()); + //for (auto &s : postfix) + // printf("x : %s\n", s.c_str()); compile_postfix(inputs, postfix, expr); } + template <typename NT> + static inline typename std::enable_if<std::is_floating_point<NT>::value, NT>::type + lfsr_random(std::uint16_t &lfsr) noexcept + { + std::uint16_t lsb = lfsr & 1; + lfsr >>= 1; + if (lsb) + lfsr ^= 0xB400u; // taps 15, 13, 12, 10 + return static_cast<NT>(lfsr) / static_cast<NT>(0xffffu); + } + + template <typename NT> + static inline typename std::enable_if<std::is_integral<NT>::value, NT>::type + lfsr_random(std::uint16_t &lfsr) noexcept + { + std::uint16_t lsb = lfsr & 1; + lfsr >>= 1; + if (lsb) + lfsr ^= 0xB400u; // taps 15, 13, 12, 10 + return static_cast<NT>(lfsr); + } #define ST1 stack[ptr] #define ST2 stack[ptr-1] @@ -208,7 +281,7 @@ namespace plib { OP(COS, 0, plib::cos(ST2)) OP(TRUNC, 0, plib::trunc(ST2)) case RAND: - stack[ptr++] = lfsr_random(); + stack[ptr++] = lfsr_random<NT>(m_lfsr); break; case PUSH_INPUT: stack[ptr++] = values[static_cast<unsigned>(rc.m_param)]; |