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
This commit is contained in:
couriersud 2019-11-10 19:54:26 +01:00
parent a5f06c7695
commit b8c43342d5
23 changed files with 410 additions and 123 deletions

View File

@ -15,39 +15,30 @@
// -----------------------------------------------------------------------------
#define RES(name, p_R) \
NET_REGISTER_DEV(RES, name) \
NETDEV_PARAMI(name, R, p_R)
NET_REGISTER_DEVEXT(RES, name, p_R)
#define POT(name, p_R) \
NET_REGISTER_DEV(POT, name) \
NETDEV_PARAMI(name, R, p_R)
NET_REGISTER_DEVEXT(POT, name, p_R)
// Does not have pin 3 connected
#define POT2(name, p_R) \
NET_REGISTER_DEV(POT2, name) \
NETDEV_PARAMI(name, R, p_R)
NET_REGISTER_DEVEXT(POT2, name, p_R)
#define CAP(name, p_C) \
NET_REGISTER_DEV(CAP, name) \
NETDEV_PARAMI(name, C, p_C)
NET_REGISTER_DEVEXT(CAP, name, p_C)
#define IND(name, p_L) \
NET_REGISTER_DEV(IND, name) \
NETDEV_PARAMI(name, L, p_L)
NET_REGISTER_DEVEXT(IND, name, p_L)
// Generic Diode
#define DIODE(name, model) \
NET_REGISTER_DEV(DIODE, name) \
NETDEV_PARAMI(name, MODEL, model)
NET_REGISTER_DEVEXT(DIODE, name, model)
#define VS(name, pV) \
NET_REGISTER_DEV(VS, name) \
NETDEV_PARAMI(name, V, pV)
NET_REGISTER_DEVEXT(VS, name, pV)
#define CS(name, pI) \
NET_REGISTER_DEV(CS, name) \
NETDEV_PARAMI(name, I, pI)
NET_REGISTER_DEVEXT(CS, name, pI)
// -----------------------------------------------------------------------------
// Generic macros

View File

@ -398,7 +398,7 @@ namespace analog
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile(std::vector<pstring>({{pstring("T")}}), m_func());
m_compiled.compile(m_func(), std::vector<pstring>({{pstring("T")}}));
}
NETLIB_IS_TIMESTEP(m_func() != "")
@ -447,7 +447,7 @@ namespace analog
register_subalias("P", m_P);
register_subalias("N", m_N);
if (m_func() != "")
m_compiled.compile(std::vector<pstring>({{pstring("T")}}), m_func());
m_compiled.compile(m_func(), std::vector<pstring>({{pstring("T")}}));
}
NETLIB_IS_TIMESTEP(m_func() != "")

View File

@ -14,22 +14,38 @@
//#define NL_AUTO_DEVICES 1
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#ifdef NL_AUTO_DEVICES
#include "nld_devinc.h"
#include "macro/nlm_cd4xxx.h"
#include "macro/nlm_ttl74xx.h"
#include "macro/nlm_opamp.h"
#include "macro/nlm_other.h"
// FIXME: copied from nld_twoterm.h
#ifdef RES_R
#warning "Do not include rescap.h in a netlist environment"
#endif
#ifndef RES_R
#define RES_R(res) (res)
#define RES_K(res) ((res) * 1e3)
#define RES_M(res) ((res) * 1e6)
#define CAP_U(cap) ((cap) * 1e-6)
#define CAP_N(cap) ((cap) * 1e-9)
#define CAP_P(cap) ((cap) * 1e-12)
#define IND_U(ind) ((ind) * 1e-6)
#define IND_N(ind) ((ind) * 1e-9)
#define IND_P(ind) ((ind) * 1e-12)
#endif
#include "netlist/macro/nlm_cd4xxx.h"
#include "netlist/macro/nlm_ttl74xx.h"
#include "netlist/macro/nlm_opamp.h"
#include "netlist/macro/nlm_other.h"
#include "nld_7448.h"
#else
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#include "nld_system.h"
#include "nld_2102A.h"

View File

@ -30,6 +30,7 @@
#include "netlist/nl_setup.h"
#if 0
#define SN74LS629(name, p_cap) \
NET_REGISTER_DEV(SN74LS629, name) \
NETDEV_PARAMI(name, CAP, p_cap)
@ -38,5 +39,11 @@
NET_REGISTER_DEV(SN74LS629_DIP, name) \
NETDEV_PARAMI(name, 1.CAP, p_cap1) \
NETDEV_PARAMI(name, 2.CAP, p_cap2)
#else
#define SN74LS629(name, p_cap) \
NET_REGISTER_DEVEXT(SN74LS629, name, p_cap)
#define SN74LS629_DIP(name, p_cap1, p_cap2) \
NET_REGISTER_DEVEXT(SN74LS629_DIP, name, p_cap1, p_cap2)
#endif
#endif /* NLD_74LS629_H_ */

View File

@ -70,7 +70,7 @@ namespace devices
NETLIB_DEVICE_IMPL(extclock, "EXTCLOCK", "FREQ,PATTERN")
NETLIB_DEVICE_IMPL(res_sw, "RES_SWITCH", "+I,+1,+2")
NETLIB_DEVICE_IMPL(mainclock, "MAINCLOCK", "FREQ")
NETLIB_DEVICE_IMPL(gnd, "GND", "")
NETLIB_DEVICE_IMPL(gnd, "GNDA", "")
NETLIB_DEVICE_IMPL(netlistparams, "PARAMETER", "")
NETLIB_DEVICE_IMPL(logic_input, "LOGIC_INPUT", "IN,FAMILY")

View File

@ -28,9 +28,14 @@
NET_REGISTER_DEV(ANALOG_INPUT, name) \
PARAM(name.IN, v)
#if 0
#define MAINCLOCK(name, freq) \
NET_REGISTER_DEV(MAINCLOCK, name) \
PARAM(name.FREQ, freq)
#else
#define MAINCLOCK(name, freq) \
NET_REGISTER_DEVEXT(MAINCLOCK, name, freq)
#endif
#define CLOCK(name, freq) \
NET_REGISTER_DEV(CLOCK, name) \

View File

@ -128,7 +128,7 @@ namespace devices
, m_funcparam({nlconst::zero()})
{
if (m_func() != "")
m_compiled.compile(std::vector<pstring>({{pstring("T")}}), m_func());
m_compiled.compile(m_func(), std::vector<pstring>({{pstring("T")}}));
connect(m_feedback, m_Q);
}
//NETLIB_RESETI();
@ -370,7 +370,7 @@ namespace devices
inps.push_back(n);
m_vals.push_back(nlconst::zero());
}
m_compiled.compile(inps, m_func());
m_compiled.compile(m_func(), inps);
}
protected:

View File

@ -91,7 +91,7 @@ NETLIST_END()
NETLIST_START(base)
TTL_INPUT(ttlhigh, 1)
TTL_INPUT(ttllow, 0)
NET_REGISTER_DEV(GND, GND)
NET_REGISTER_DEV(GNDA, GND)
NET_REGISTER_DEV(PARAMETER, NETLIST)
LOCAL_SOURCE(diode_models)

View File

@ -1,6 +1,6 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#include "nlm_opamp.h"
#include "netlist/devices/net_lib.h"
/*

View File

@ -33,7 +33,7 @@
#define LM3900(name) \
NET_REGISTER_DEV(LM3900, name)
#endif
#endif // NL_AUTO_DEVICES
/* ----------------------------------------------------------------------------
* External declarations
@ -41,6 +41,6 @@
NETLIST_EXTERNAL(OPAMP_lib)
#endif
#endif // __PLIB_PREPROCESSOR__
#endif

View File

@ -305,7 +305,7 @@
#define DM9312_DIP(name) \
NET_REGISTER_DEV(DM9312_DIP, name)
#endif
#endif // NL_AUTO_DEVICES
/* ----------------------------------------------------------------------------
* External declarations
@ -313,6 +313,7 @@
NETLIST_EXTERNAL(TTL74XX_lib)
#endif // NL_AUTO_DEVICES
#endif // __PLIB_PREPROCESSOR__
#endif // NLM_TTL74XX

View File

@ -22,6 +22,7 @@
#include "plib/pstonum.h"
#include "plib/pstream.h"
#include "plib/ptime.h"
#include "plib/pfunction.h"
#include "nl_errstr.h"
#include "nltypes.h"
@ -1733,6 +1734,7 @@ namespace netlist
pstring p = this->get_initial(device, &found);
if (found)
{
#if 0
bool err = false;
auto vald = plib::pstonum_ne<T>(p, err);
if (err)
@ -1741,6 +1743,15 @@ namespace netlist
plib::pthrow<nl_exception>(MF_INVALID_NUMBER_CONVERSION_1_2(name, p));
}
m_param = vald;
#else
plib::pfunction<nl_fptype> func;
func.compile_infix(p, {});
auto valx = func.evaluate();
if (std::is_integral<T>::value)
if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6))
plib::pthrow<nl_exception>(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p));
m_param = static_cast<T>(valx);
#endif
}
else
m_param = val;

View File

@ -26,8 +26,6 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
#ifndef NL_CONVERT_CPP
#include "devices/net_lib.h"
#include "analog/nld_twoterm.h"
#endif
@ -125,8 +123,8 @@ public:
#define CHIP_555_Mono(name, pdesc) \
NE555_DIP(name) \
NET_C(name.6, name.7) \
RES(name ## _R, (pdesc)->r) \
CAP(name ## _C, (pdesc)->c) \
RES(name ## _R, pdesc ## _R) \
CAP(name ## _C, pdesc ## _C) \
NET_C(name.6, name ## _R.1) \
NET_C(name.6, name ## _C.1) \
NET_C(name ## _R.2, V5) \
@ -167,8 +165,8 @@ public:
NET_C(name.14, name ## _R2.2) \
NET_C(VCC, name ## _R2.1)
#define CHIP_SERIES_RC(name, pdesc) \
RES(name ## _R, (pdesc)->r) \
CAP(name ## _C, (pdesc)->c) \
RES(name ## _R, pdesc ## _R) \
CAP(name ## _C, pdesc ## _C) \
NET_C(name ## _R.1, name ## _C.2) \
ALIAS(name.3, name ## _R.1) \
ALIAS(name.2, name ## _R.2) \

View File

@ -68,6 +68,8 @@ namespace netlist
PERRMSGV(MF_DEVICE_ALREADY_EXISTS_1, 1, "Device already exists: {1}")
PERRMSGV(MF_ADDING_ALI1_TO_ALIAS_LIST, 1, "Error adding alias {1} to alias list")
PERRMSGV(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1, 1,"You must pass an equal number of pins to DIPPINS {1}")
PERRMSGV(MF_PARAM_COUNT_MISMATCH_2, 2, "Parameter count mismatch for {1} - only found {2}")
PERRMSGV(MF_PARAM_COUNT_EXCEEDED_2, 2, "Parameter count exceed for {1} - found {2}")
PERRMSGV(MF_UNKNOWN_OBJECT_TYPE_1, 1, "Unknown object type {1}")
PERRMSGV(MF_INVALID_NUMBER_CONVERSION_1_2, 2, "Invalid number conversion {1} : {2}")
PERRMSGV(MF_INVALID_ENUM_CONVERSION_1_2, 2, "Invalid element found {1} : {2}")

View File

@ -47,6 +47,13 @@ bool parser_t::parse(const pstring &nlname)
m_tok_TT_LINE = register_token("TT_LINE");
m_tok_TT_FAMILY = register_token("TT_FAMILY");
register_token("RES_R");
register_token("RES_K");
register_token("RES_M");
register_token("CAP_U");
register_token("CAP_N");
register_token("CAP_P");
bool in_nl = false;
while (true)
@ -347,56 +354,127 @@ void parser_t::netdev_hint()
void parser_t::device(const pstring &dev_type)
{
#if 1
std::vector<pstring> params;
pstring devname = get_identifier();
m_setup.log().debug("Parser: IC: {1}\n", devname);
auto tok(get_token());
//printf("enter\n");
while (tok.is(m_tok_comma))
{
tok = get_token();
//printf("%d %s\n", tok.type(), tok.str().c_str());
if (tok.is_type(IDENTIFIER))
params.push_back(tok.str());
else if (tok.is_type(STRING))
{
params.push_back(tok.str());
}
else
{
// FIXME: Do we really need this?
nl_fptype value = eval_param(tok);
if (plib::abs(value - plib::floor(value)) > nlconst::magic(1e-30)
|| plib::abs(value) > nlconst::magic(1e9))
params.push_back(plib::pfmt("{1:.9}").e(value));
else
params.push_back(plib::pfmt("{1}")(static_cast<long>(value)));
}
tok = get_token();
}
require_token(tok, m_tok_param_right);
m_setup.register_dev(dev_type, devname, params);
#else
factory::element_t *f = m_setup.factory().factory_by_name(dev_type);
auto paramlist = plib::psplit(f->param_desc(), ",");
std::vector<pstring> params;
pstring devname = get_identifier();
m_setup.register_dev(dev_type, devname);
m_setup.log().debug("Parser: IC: {1}\n", devname);
for (const pstring &tp : paramlist)
auto tok(get_token());
//printf("enter\n");
while (tok.is(m_tok_comma))
{
if (plib::startsWith(tp, "+"))
tok = get_token();
//printf("%d %s\n", tok.type(), tok.str().c_str());
if (tok.is_type(IDENTIFIER))
params.push_back(tok.str());
else if (tok.is_type(STRING))
{
require_token(m_tok_comma);
pstring output_name = get_identifier();
m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
m_setup.register_link(devname + "." + tp.substr(1), output_name);
}
else if (plib::startsWith(tp, "@"))
{
pstring term = tp.substr(1);
m_setup.log().debug("Link: {1} {2}\n", tp, term);
//FIXME
if (term == "VCC")
m_setup.register_link(devname + "." + term, "V5");
else
m_setup.register_link(devname + "." + term, term);
params.push_back(tok.str());
}
else
{
require_token(m_tok_comma);
pstring paramfq = devname + "." + tp;
// FIXME: Do we really need this?
nl_fptype value = eval_param(tok);
if (plib::abs(value - plib::floor(value)) > nlconst::magic(1e-30)
|| plib::abs(value) > nlconst::magic(1e9))
params.push_back(plib::pfmt("{1:.9}").e(value));
else
params.push_back(plib::pfmt("{1}")(static_cast<long>(value)));
}
tok = get_token();
}
m_setup.log().debug("Defparam: {1}\n", paramfq);
token_t tok = get_token();
if (tok.is_type(STRING))
require_token(tok, m_tok_param_right);
if (params.size() > 0)
{
auto ptok(params.begin());
for (const pstring &tp : paramlist)
{
//printf("x %s %s\n", tp.c_str(), ptok->c_str());
if (plib::startsWith(tp, "+"))
{
m_setup.register_param(paramfq, tok.str());
if (ptok == params.end())
{
error(plib::pfmt("Input count mismatch for {1} - only found {2}")(devname)(params.size()));
break;
}
pstring output_name = *ptok;
m_setup.log().debug("Link: {1} {2}\n", tp, output_name);
m_setup.register_link(devname + "." + tp.substr(1), output_name);
++ptok;
}
else if (plib::startsWith(tp, "@"))
{
pstring term = tp.substr(1);
m_setup.log().debug("Link: {1} {2}\n", tp, term);
m_setup.register_link(devname + "." + term, term);
}
else
{
nl_fptype val = eval_param(tok);
m_setup.register_param(paramfq, val);
if (ptok == params.end())
{
error(plib::pfmt("Input count mismatch for {1} - only found {2}")(devname)(params.size()));
break;
}
pstring paramfq = devname + "." + tp;
m_setup.log().debug("Defparam: {1}\n", paramfq);
m_setup.register_param(paramfq, *ptok);
++ptok;
}
}
if (ptok != params.end())
{
error(plib::pfmt("Input count exceed for {1} - found {2}")(devname)(params.size()));
}
}
// error(plib::pfmt("Input count mismatch for {1} - expected {2} found {3}")(devname)(termlist.size())(cnt));
require_token(m_tok_param_right);
#endif
}

View File

@ -33,7 +33,7 @@ namespace netlist
register_alias_nofqn(alias_fqn, out_fqn);
}
void nlparse_t::register_dippins_arr(const pstring &terms)
void nlparse_t::register_dip_alias_arr(const pstring &terms)
{
std::vector<pstring> list(plib::psplit(terms,", "));
if (list.size() == 0 || (list.size() % 2) == 1)
@ -49,6 +49,90 @@ namespace netlist
}
}
void nlparse_t::register_dev(const pstring &classname, const pstring &name,
const char * params_and_connections)
{
auto params(plib::psplit(pstring(params_and_connections), ",", false));
for (auto &i : params)
i = plib::trim(i);
register_dev(classname, name, params);
}
void nlparse_t::register_dev(const pstring &classname, const pstring &name,
std::initializer_list<const char *> params_and_connections)
{
std::vector<pstring> params;
for (auto &i : params_and_connections)
params.push_back(pstring(i));
register_dev(classname, name, params);
}
void nlparse_t::register_dev(const pstring &classname, const pstring &name,
const std::vector<pstring> &params_and_connections)
{
factory::element_t *f = m_setup.factory().factory_by_name(classname);
auto paramlist = plib::psplit(f->param_desc(), ",");
register_dev(classname, name);
if (params_and_connections.size() > 0)
{
auto ptok(params_and_connections.begin());
auto ptok_end(params_and_connections.end());
for (const pstring &tp : paramlist)
{
//printf("x %s %s\n", tp.c_str(), ptok->c_str());
if (plib::startsWith(tp, "+"))
{
if (ptok == ptok_end)
{
auto err(MF_PARAM_COUNT_MISMATCH_2(name, params_and_connections.size()));
log().fatal(err);
plib::pthrow<nl_exception>(err);
//break;
}
pstring output_name = *ptok;
log().debug("Link: {1} {2}\n", tp, output_name);
register_link(name + "." + tp.substr(1), output_name);
++ptok;
}
else if (plib::startsWith(tp, "@"))
{
pstring term = tp.substr(1);
m_setup.log().debug("Link: {1} {2}\n", tp, term);
register_link(name + "." + term, term);
}
else
{
if (ptok == params_and_connections.end())
{
auto err(MF_PARAM_COUNT_MISMATCH_2(name, params_and_connections.size()));
log().fatal(err);
plib::pthrow<nl_exception>(err);
}
pstring paramfq = name + "." + tp;
log().debug("Defparam: {1}\n", paramfq);
// remove quotes
if (plib::startsWith(*ptok, "\"") && plib::endsWith(*ptok, "\""))
register_param(paramfq, ptok->substr(1, ptok->length() - 2));
else
register_param(paramfq, *ptok);
++ptok;
}
}
if (ptok != params_and_connections.end())
{
auto err(MF_PARAM_COUNT_EXCEEDED_2(name, params_and_connections.size()));
log().fatal(err);
plib::pthrow<nl_exception>(err);
}
}
}
void nlparse_t::register_dev(const pstring &classname, const pstring &name)
{
auto f = m_factory.factory_by_name(classname);

View File

@ -21,7 +21,7 @@
#include <stack>
#include <unordered_map>
#include <vector>
#include <initializer_list>
//============================================================
// MACROS / inline netlist definitions
@ -36,12 +36,15 @@
setup.register_alias(# alias, # name);
#define DIPPINS(pin1, ...) \
setup.register_dippins_arr( # pin1 ", " # __VA_ARGS__);
setup.register_dip_alias_arr( # pin1 ", " # __VA_ARGS__);
// to be used to reference new library truthtable devices
#define NET_REGISTER_DEV(type, name) \
setup.register_dev(# type, # name);
#define NET_REGISTER_DEVEXT(type, name, ...) \
setup.register_dev(# type, # name, # __VA_ARGS__);
#define NET_CONNECT(name, input, output) \
setup.register_link(# name "." # input, # output);
@ -239,8 +242,16 @@ namespace netlist
void register_model(const pstring &model_in) { m_models.register_model(model_in); }
void register_alias(const pstring &alias, const pstring &out);
void register_dippins_arr(const pstring &terms);
void register_dip_alias_arr(const pstring &terms);
void register_dev(const pstring &classname, const pstring &name);
void register_dev(const pstring &classname, const pstring &name,
const std::vector<pstring> &params_and_connections);
void register_dev(const pstring &classname, const pstring &name,
std::initializer_list<const char *> params_and_connections);
void register_dev(const pstring &classname, const pstring &name,
const char *params_and_connections);
void register_link(const pstring &sin, const pstring &sout);
void register_link_arr(const pstring &terms);
void register_param(const pstring &param, const pstring &value);

View File

@ -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)];

View File

@ -72,47 +72,38 @@ namespace plib {
/// \brief Compile an expression
///
/// \param inputs Vector of input variables, e.g. {"A","B"}
/// \param expr infix or postfix expression. default is infix, postrix
/// to be prefixed with rpn, e.g. "rpn:A B + 1.3 /"
/// \param inputs Vector of input variables, e.g. {"A","B"}
///
void compile(const std::vector<pstring> &inputs, const pstring &expr);
void compile(const pstring &expr, const std::vector<pstring> &inputs);
/// \brief Compile a rpn expression
///
/// \param inputs Vector of input variables, e.g. {"A","B"}
/// \param expr Reverse polish notation expression, e.g. "A B + 1.3 /"
/// \param inputs Vector of input variables, e.g. {"A","B"}
///
void compile_postfix(const std::vector<pstring> &inputs, const pstring &expr);
void compile_postfix(const pstring &expr, const std::vector<pstring> &inputs);
/// \brief Compile an infix expression
///
/// \param inputs Vector of input variables, e.g. {"A","B"}
/// \param expr Infix expression, e.g. "(A+B)/1.3"
/// \param inputs Vector of input variables, e.g. {"A","B"}
///
void compile_infix(const std::vector<pstring> &inputs, const pstring &expr);
void compile_infix(const pstring &expr, const std::vector<pstring> &inputs);
/// \brief Evaluate the expression
///
/// \param values for input variables, e.g. {1.1, 2.2}
/// \return value of expression
///
NT evaluate(const std::vector<NT> &values) noexcept;
NT evaluate(const std::vector<NT> &values = std::vector<NT>()) noexcept;
private:
void compile_postfix(const std::vector<pstring> &inputs,
const std::vector<pstring> &cmds, const pstring &expr);
NT lfsr_random() noexcept
{
std::uint16_t lsb = m_lfsr & 1;
m_lfsr >>= 1;
if (lsb)
m_lfsr ^= 0xB400u; // taps 15, 13, 12, 10
return static_cast<NT>(m_lfsr) / static_cast<NT>(0xffffu);
}
std::vector<rpn_inst> m_precompiled; //!< precompiled expression
std::uint16_t m_lfsr; //!< lfsr used for generating random numbers

View File

@ -79,12 +79,14 @@ namespace plib {
{
}
bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
bool is(const token_id_t &tok_id) const noexcept { return m_id.id() == tok_id.id(); }
bool is_not(const token_id_t &tok_id) const noexcept { return !is(tok_id); }
bool is_type(const token_type type) const { return m_type == type; }
bool is_type(const token_type type) const noexcept { return m_type == type; }
pstring str() const { return m_token; }
token_type type() const noexcept { return m_type; }
pstring str() const noexcept { return m_token; }
private:
token_type m_type;

View File

@ -14,6 +14,7 @@
#include <algorithm>
#include <vector>
#include <initializer_list>
#define PSTRINGIFY_HELP(y) # y
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)

View File

@ -674,18 +674,24 @@ void tool_app_t::header_entry(const netlist::factory::element_t *e)
if (!plib::startsWith(s, "@"))
vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
mac_out("#define " + e->name() + "(name" + vs + ")");
mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)");
vs = "";
for (const auto &s : v)
{
pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@",""));
if (plib::startsWith(s, "+"))
mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")");
vs += ", p" + r;
else if (plib::startsWith(s, "@"))
mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")");
{
// automatically connected
//mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")");
}
else
mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")");
vs += ", p" + r;
}
mac_out("\tNET_REGISTER_DEVEXT(" + e->name() +", name" + vs + ")", false);
mac_out("", false);
}
@ -730,7 +736,6 @@ void tool_app_t::create_header()
pout("#ifndef NLD_DEVINC_H\n");
pout("#define NLD_DEVINC_H\n");
pout("\n");
pout("#include \"nl_setup.h\"\n");
pout("#ifndef __PLIB_PREPROCESSOR__\n");
pout("\n");
pout("// ----------------------------------------------------------------------------\n");

View File

@ -57,18 +57,29 @@
#include "netlist/nl_dice_compat.h"
static Mono555Desc a3_555_desc(K_OHM(100.0), U_FARAD(0.1));
#define a3_555_desc_R K_OHM(100.0)
#define a3_555_desc_C U_FARAD(0.1)
static Mono555Desc a10_555_desc(K_OHM(70.0), U_FARAD(0.1)); // actually 56k + 50k trimmer
static Mono555Desc b10_555_desc(K_OHM(70.0), U_FARAD(0.1)); // actually 56k + 50k trimmer
#define a10_555_desc_R K_OHM(70.0) // actually 56k + 50k trimmer
#define a10_555_desc_C U_FARAD(0.1)
static Mono555Desc b9a_555_desc(K_OHM(70.0), U_FARAD(0.1)); // actually 56k + 50k trimmer
static Mono555Desc b9b_555_desc(K_OHM(70.0), U_FARAD(0.1)); // actually 56k + 50k trimmer
#define b10_555_desc_R K_OHM(70.0) // actually 56k + 50k trimmer
#define b10_555_desc_C U_FARAD(0.1)
static Mono555Desc f5_555_desc(K_OHM(330.0), U_FARAD(4.7));
static Mono555Desc g5_555_desc(K_OHM(220.0), U_FARAD(1.0));
#define b9a_555_desc_R K_OHM(70.0) // actually 56k + 50k trimmer
#define b9a_555_desc_C U_FARAD(0.1)
static SeriesRCDesc c33_desc(K_OHM(1.0), U_FARAD(0.1)); // Capacitor C33, Resistor R30
#define b9b_555_desc_R K_OHM(70.0) // actually 56k + 50k trimmer
#define b9b_555_desc_C U_FARAD(0.1)
#define f5_555_desc_R K_OHM(330.0)
#define f5_555_desc_C U_FARAD(4.7)
#define g5_555_desc_R K_OHM(220.0)
#define g5_555_desc_C U_FARAD(1.0)
#define c33_desc_R K_OHM(1.0)
#define c33_desc_C U_FARAD(0.1) // Capacitor C33, Resistor R30
#if 0
static Paddle1VerticalDesc pad1_desc(17000.0, 145000.0, &a10_555_desc);
@ -126,7 +137,7 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("D4", 7430)
//CHIP("B10", 555_Mono, &b10_555_desc)
CHIP_555_Mono(B10, &b10_555_desc)
CHIP_555_Mono(B10, b10_555_desc)
// NETLIST - analog start
POT(B10_POT, RES_K(1)) // This is a guess!!
@ -146,7 +157,7 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("A8", 7420)
//CHIP("A10", 555_Mono, &a10_555_desc)
CHIP_555_Mono(A10, &a10_555_desc)
CHIP_555_Mono(A10, a10_555_desc)
// NETLIST - analog start
POT(A10_POT, RES_K(1)) // This is a guess!!
@ -180,10 +191,10 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("H5", 7400)
CHIP("E7", 7400)
//CHIP("F5", 555_Mono, &f5_555_desc)
CHIP_555_Mono(F5, &f5_555_desc)
CHIP_555_Mono(F5, f5_555_desc)
//CHIP("G5", 555_Mono, &g5_555_desc)
CHIP_555_Mono(G5, &g5_555_desc)
CHIP_555_Mono(G5, g5_555_desc)
CHIP("C3", 7474)
CHIP("C2", 7400)
@ -219,10 +230,10 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("H10", 7474)
CHIP("G10", 7474)
//CHIP("A3", 555_Mono, &a3_555_desc)
CHIP_555_Mono(A3, &a3_555_desc)
CHIP_555_Mono(A3, a3_555_desc)
//CHIP("B9A", 555_Mono, &b9a_555_desc)
CHIP_555_Mono(B9A, &b9a_555_desc)
CHIP_555_Mono(B9A, b9a_555_desc)
// NETLIST - analog start
POT(B9A_POT, RES_K(1)) // This is a guess!!
@ -236,7 +247,7 @@ CIRCUIT_LAYOUT( pongdoubles )
// NETLIST - analog end
//CHIP("B9B", 555_Mono, &b9b_555_desc)
CHIP_555_Mono(B9B, &b9b_555_desc)
CHIP_555_Mono(B9B, b9b_555_desc)
// NETLIST - analog start
POT(B9B_POT, RES_K(1)) // This is a guess!!
@ -249,7 +260,7 @@ CIRCUIT_LAYOUT( pongdoubles )
NET_C(B9B_RPRE.2, B9B.5)
// NETLIST - analog end
CHIP_SERIES_RC(C33, &c33_desc)
CHIP_SERIES_RC(C33, c33_desc)
#if 0
CHIP("PAD1", PADDLE1_VERTICAL_INPUT, &pad1_desc)