From b8c43342d531b0bd30f8db30174f7bd1cdaa19fa Mon Sep 17 00:00:00 2001 From: couriersud Date: Sun, 10 Nov 2019 19:54:26 +0100 Subject: 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 --- src/lib/netlist/plib/pfunction.cpp | 87 +++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 7 deletions(-) (limited to 'src/lib/netlist/plib/pfunction.cpp') 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 +#include namespace plib { template - void pfunction::compile(const std::vector &inputs, const pstring &expr) + void pfunction::compile(const pstring &expr, const std::vector &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 - void pfunction::compile_postfix(const std::vector &inputs, const pstring &expr) + void pfunction::compile_postfix(const pstring &expr, const std::vector &inputs) { std::vector cmds(plib::psplit(expr, " ")); compile_postfix(inputs, cmds, expr); @@ -113,13 +114,61 @@ namespace plib { } template - void pfunction::compile_infix(const std::vector &inputs, const pstring &expr) + void pfunction::compile_infix(const pstring &expr, const std::vector &inputs) { // Shunting-yard infix parsing std::vector sep = {"(", ")", ",", "*", "/", "+", "-", "^"}; - std::vector sexpr(plib::psplit(plib::replace_all(expr, " ", ""), sep)); + std::vector sexpr1(plib::psplit(plib::replace_all(expr, " ", ""), sep)); std::stack opstk; std::vector postfix; + std::vector 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 + static inline typename std::enable_if::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(lfsr) / static_cast(0xffffu); + } + + template + static inline typename std::enable_if::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(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(m_lfsr); break; case PUSH_INPUT: stack[ptr++] = values[static_cast(rc.m_param)]; -- cgit v1.2.3-70-g09d2