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) \ #define RES(name, p_R) \
NET_REGISTER_DEV(RES, name) \ NET_REGISTER_DEVEXT(RES, name, p_R)
NETDEV_PARAMI(name, R, p_R)
#define POT(name, p_R) \ #define POT(name, p_R) \
NET_REGISTER_DEV(POT, name) \ NET_REGISTER_DEVEXT(POT, name, p_R)
NETDEV_PARAMI(name, R, p_R)
// Does not have pin 3 connected // Does not have pin 3 connected
#define POT2(name, p_R) \ #define POT2(name, p_R) \
NET_REGISTER_DEV(POT2, name) \ NET_REGISTER_DEVEXT(POT2, name, p_R)
NETDEV_PARAMI(name, R, p_R)
#define CAP(name, p_C) \ #define CAP(name, p_C) \
NET_REGISTER_DEV(CAP, name) \ NET_REGISTER_DEVEXT(CAP, name, p_C)
NETDEV_PARAMI(name, C, p_C)
#define IND(name, p_L) \ #define IND(name, p_L) \
NET_REGISTER_DEV(IND, name) \ NET_REGISTER_DEVEXT(IND, name, p_L)
NETDEV_PARAMI(name, L, p_L)
// Generic Diode // Generic Diode
#define DIODE(name, model) \ #define DIODE(name, model) \
NET_REGISTER_DEV(DIODE, name) \ NET_REGISTER_DEVEXT(DIODE, name, model)
NETDEV_PARAMI(name, MODEL, model)
#define VS(name, pV) \ #define VS(name, pV) \
NET_REGISTER_DEV(VS, name) \ NET_REGISTER_DEVEXT(VS, name, pV)
NETDEV_PARAMI(name, V, pV)
#define CS(name, pI) \ #define CS(name, pI) \
NET_REGISTER_DEV(CS, name) \ NET_REGISTER_DEVEXT(CS, name, pI)
NETDEV_PARAMI(name, I, pI)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Generic macros // Generic macros

View File

@ -398,7 +398,7 @@ namespace analog
register_subalias("P", m_P); register_subalias("P", m_P);
register_subalias("N", m_N); register_subalias("N", m_N);
if (m_func() != "") 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() != "") NETLIB_IS_TIMESTEP(m_func() != "")
@ -447,7 +447,7 @@ namespace analog
register_subalias("P", m_P); register_subalias("P", m_P);
register_subalias("N", m_N); register_subalias("N", m_N);
if (m_func() != "") 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() != "") NETLIB_IS_TIMESTEP(m_func() != "")

View File

@ -14,22 +14,38 @@
//#define NL_AUTO_DEVICES 1 //#define NL_AUTO_DEVICES 1
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#ifdef NL_AUTO_DEVICES #ifdef NL_AUTO_DEVICES
#include "nld_devinc.h" #include "nld_devinc.h"
#include "macro/nlm_cd4xxx.h" // FIXME: copied from nld_twoterm.h
#include "macro/nlm_ttl74xx.h" #ifdef RES_R
#include "macro/nlm_opamp.h" #warning "Do not include rescap.h in a netlist environment"
#include "macro/nlm_other.h" #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" #include "nld_7448.h"
#else #else
#define SOLVER(name, freq) \
NET_REGISTER_DEV(SOLVER, name) \
PARAM(name.FREQ, freq)
#include "nld_system.h" #include "nld_system.h"
#include "nld_2102A.h" #include "nld_2102A.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#include "plib/pstonum.h" #include "plib/pstonum.h"
#include "plib/pstream.h" #include "plib/pstream.h"
#include "plib/ptime.h" #include "plib/ptime.h"
#include "plib/pfunction.h"
#include "nl_errstr.h" #include "nl_errstr.h"
#include "nltypes.h" #include "nltypes.h"
@ -1733,6 +1734,7 @@ namespace netlist
pstring p = this->get_initial(device, &found); pstring p = this->get_initial(device, &found);
if (found) if (found)
{ {
#if 0
bool err = false; bool err = false;
auto vald = plib::pstonum_ne<T>(p, err); auto vald = plib::pstonum_ne<T>(p, err);
if (err) if (err)
@ -1741,6 +1743,15 @@ namespace netlist
plib::pthrow<nl_exception>(MF_INVALID_NUMBER_CONVERSION_1_2(name, p)); plib::pthrow<nl_exception>(MF_INVALID_NUMBER_CONVERSION_1_2(name, p));
} }
m_param = vald; 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 else
m_param = val; 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 #ifndef NL_CONVERT_CPP
#include "devices/net_lib.h" #include "devices/net_lib.h"
#include "analog/nld_twoterm.h"
#endif #endif
@ -125,8 +123,8 @@ public:
#define CHIP_555_Mono(name, pdesc) \ #define CHIP_555_Mono(name, pdesc) \
NE555_DIP(name) \ NE555_DIP(name) \
NET_C(name.6, name.7) \ NET_C(name.6, name.7) \
RES(name ## _R, (pdesc)->r) \ RES(name ## _R, pdesc ## _R) \
CAP(name ## _C, (pdesc)->c) \ CAP(name ## _C, pdesc ## _C) \
NET_C(name.6, name ## _R.1) \ NET_C(name.6, name ## _R.1) \
NET_C(name.6, name ## _C.1) \ NET_C(name.6, name ## _C.1) \
NET_C(name ## _R.2, V5) \ NET_C(name ## _R.2, V5) \
@ -167,8 +165,8 @@ public:
NET_C(name.14, name ## _R2.2) \ NET_C(name.14, name ## _R2.2) \
NET_C(VCC, name ## _R2.1) NET_C(VCC, name ## _R2.1)
#define CHIP_SERIES_RC(name, pdesc) \ #define CHIP_SERIES_RC(name, pdesc) \
RES(name ## _R, (pdesc)->r) \ RES(name ## _R, pdesc ## _R) \
CAP(name ## _C, (pdesc)->c) \ CAP(name ## _C, pdesc ## _C) \
NET_C(name ## _R.1, name ## _C.2) \ NET_C(name ## _R.1, name ## _C.2) \
ALIAS(name.3, name ## _R.1) \ ALIAS(name.3, name ## _R.1) \
ALIAS(name.2, name ## _R.2) \ 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_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_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_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_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_NUMBER_CONVERSION_1_2, 2, "Invalid number conversion {1} : {2}")
PERRMSGV(MF_INVALID_ENUM_CONVERSION_1_2, 2, "Invalid element found {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_LINE = register_token("TT_LINE");
m_tok_TT_FAMILY = register_token("TT_FAMILY"); 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; bool in_nl = false;
while (true) while (true)
@ -347,56 +354,127 @@ void parser_t::netdev_hint()
void parser_t::device(const pstring &dev_type) 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); factory::element_t *f = m_setup.factory().factory_by_name(dev_type);
auto paramlist = plib::psplit(f->param_desc(), ","); auto paramlist = plib::psplit(f->param_desc(), ",");
std::vector<pstring> params;
pstring devname = get_identifier(); pstring devname = get_identifier();
m_setup.register_dev(dev_type, devname); m_setup.register_dev(dev_type, devname);
m_setup.log().debug("Parser: IC: {1}\n", devname); 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);
if (params.size() > 0)
{
auto ptok(params.begin());
for (const pstring &tp : paramlist) for (const pstring &tp : paramlist)
{ {
//printf("x %s %s\n", tp.c_str(), ptok->c_str());
if (plib::startsWith(tp, "+")) if (plib::startsWith(tp, "+"))
{ {
require_token(m_tok_comma); if (ptok == params.end())
pstring output_name = get_identifier(); {
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.log().debug("Link: {1} {2}\n", tp, output_name);
m_setup.register_link(devname + "." + tp.substr(1), output_name); m_setup.register_link(devname + "." + tp.substr(1), output_name);
++ptok;
} }
else if (plib::startsWith(tp, "@")) else if (plib::startsWith(tp, "@"))
{ {
pstring term = tp.substr(1); pstring term = tp.substr(1);
m_setup.log().debug("Link: {1} {2}\n", tp, term); 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); m_setup.register_link(devname + "." + term, term);
} }
else else
{ {
require_token(m_tok_comma); if (ptok == params.end())
{
error(plib::pfmt("Input count mismatch for {1} - only found {2}")(devname)(params.size()));
break;
}
pstring paramfq = devname + "." + tp; pstring paramfq = devname + "." + tp;
m_setup.log().debug("Defparam: {1}\n", paramfq); m_setup.log().debug("Defparam: {1}\n", paramfq);
token_t tok = get_token(); m_setup.register_param(paramfq, *ptok);
if (tok.is_type(STRING)) ++ptok;
}
}
if (ptok != params.end())
{ {
m_setup.register_param(paramfq, tok.str()); error(plib::pfmt("Input count exceed for {1} - found {2}")(devname)(params.size()));
}
else
{
nl_fptype val = eval_param(tok);
m_setup.register_param(paramfq, val);
} }
} }
} #endif
// error(plib::pfmt("Input count mismatch for {1} - expected {2} found {3}")(devname)(termlist.size())(cnt));
require_token(m_tok_param_right);
} }

View File

@ -33,7 +33,7 @@ namespace netlist
register_alias_nofqn(alias_fqn, out_fqn); 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,", ")); std::vector<pstring> list(plib::psplit(terms,", "));
if (list.size() == 0 || (list.size() % 2) == 1) 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) void nlparse_t::register_dev(const pstring &classname, const pstring &name)
{ {
auto f = m_factory.factory_by_name(classname); auto f = m_factory.factory_by_name(classname);

View File

@ -21,7 +21,7 @@
#include <stack> #include <stack>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <initializer_list>
//============================================================ //============================================================
// MACROS / inline netlist definitions // MACROS / inline netlist definitions
@ -36,12 +36,15 @@
setup.register_alias(# alias, # name); setup.register_alias(# alias, # name);
#define DIPPINS(pin1, ...) \ #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 // to be used to reference new library truthtable devices
#define NET_REGISTER_DEV(type, name) \ #define NET_REGISTER_DEV(type, name) \
setup.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) \ #define NET_CONNECT(name, input, output) \
setup.register_link(# 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_model(const pstring &model_in) { m_models.register_model(model_in); }
void register_alias(const pstring &alias, const pstring &out); 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);
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(const pstring &sin, const pstring &sout);
void register_link_arr(const pstring &terms); void register_link_arr(const pstring &terms);
void register_param(const pstring &param, const pstring &value); void register_param(const pstring &param, const pstring &value);

View File

@ -10,20 +10,21 @@
#include "putil.h" #include "putil.h"
#include <stack> #include <stack>
#include <type_traits>
namespace plib { namespace plib {
template <typename NT> 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:")) if (plib::startsWith(expr, "rpn:"))
compile_postfix(inputs, expr.substr(4)); compile_postfix(expr.substr(4), inputs);
else else
compile_infix(inputs, expr); compile_infix(expr, inputs);
} }
template <typename NT> 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, " ")); std::vector<pstring> cmds(plib::psplit(expr, " "));
compile_postfix(inputs, cmds, expr); compile_postfix(inputs, cmds, expr);
@ -113,13 +114,61 @@ namespace plib {
} }
template <typename NT> 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 // Shunting-yard infix parsing
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"}; 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::stack<pstring> opstk;
std::vector<pstring> postfix; 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++) for (std::size_t i = 0; i < sexpr.size(); i++)
{ {
@ -176,9 +225,33 @@ namespace plib {
postfix.push_back(opstk.top()); postfix.push_back(opstk.top());
opstk.pop(); 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); 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 ST1 stack[ptr]
#define ST2 stack[ptr-1] #define ST2 stack[ptr-1]
@ -208,7 +281,7 @@ namespace plib {
OP(COS, 0, plib::cos(ST2)) OP(COS, 0, plib::cos(ST2))
OP(TRUNC, 0, plib::trunc(ST2)) OP(TRUNC, 0, plib::trunc(ST2))
case RAND: case RAND:
stack[ptr++] = lfsr_random(); stack[ptr++] = lfsr_random<NT>(m_lfsr);
break; break;
case PUSH_INPUT: case PUSH_INPUT:
stack[ptr++] = values[static_cast<unsigned>(rc.m_param)]; stack[ptr++] = values[static_cast<unsigned>(rc.m_param)];

View File

@ -72,47 +72,38 @@ namespace plib {
/// \brief Compile an expression /// \brief Compile an expression
/// ///
/// \param inputs Vector of input variables, e.g. {"A","B"}
/// \param expr infix or postfix expression. default is infix, postrix /// \param expr infix or postfix expression. default is infix, postrix
/// to be prefixed with rpn, e.g. "rpn:A B + 1.3 /" /// 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 /// \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 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 /// \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 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 /// \brief Evaluate the expression
/// ///
/// \param values for input variables, e.g. {1.1, 2.2} /// \param values for input variables, e.g. {1.1, 2.2}
/// \return value of expression /// \return value of expression
/// ///
NT evaluate(const std::vector<NT> &values) noexcept; NT evaluate(const std::vector<NT> &values = std::vector<NT>()) noexcept;
private: private:
void compile_postfix(const std::vector<pstring> &inputs, void compile_postfix(const std::vector<pstring> &inputs,
const std::vector<pstring> &cmds, const pstring &expr); 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::vector<rpn_inst> m_precompiled; //!< precompiled expression
std::uint16_t m_lfsr; //!< lfsr used for generating random numbers 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(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 { return !is(tok_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: private:
token_type m_type; token_type m_type;

View File

@ -14,6 +14,7 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <initializer_list>
#define PSTRINGIFY_HELP(y) # y #define PSTRINGIFY_HELP(y) # y
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x) #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, "@")) if (!plib::startsWith(s, "@"))
vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"); vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_");
mac_out("#define " + e->name() + "(name" + vs + ")"); mac_out("#define " + e->name() + "(name" + vs + ")");
mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)");
vs = "";
for (const auto &s : v) for (const auto &s : v)
{ {
pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@","")); pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@",""));
if (plib::startsWith(s, "+")) if (plib::startsWith(s, "+"))
mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")"); vs += ", p" + r;
else if (plib::startsWith(s, "@")) else if (plib::startsWith(s, "@"))
mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")"); {
else // automatically connected
mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")"); //mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")");
} }
else
vs += ", p" + r;
}
mac_out("\tNET_REGISTER_DEVEXT(" + e->name() +", name" + vs + ")", false);
mac_out("", false); mac_out("", false);
} }
@ -730,7 +736,6 @@ void tool_app_t::create_header()
pout("#ifndef NLD_DEVINC_H\n"); pout("#ifndef NLD_DEVINC_H\n");
pout("#define NLD_DEVINC_H\n"); pout("#define NLD_DEVINC_H\n");
pout("\n"); pout("\n");
pout("#include \"nl_setup.h\"\n");
pout("#ifndef __PLIB_PREPROCESSOR__\n"); pout("#ifndef __PLIB_PREPROCESSOR__\n");
pout("\n"); pout("\n");
pout("// ----------------------------------------------------------------------------\n"); pout("// ----------------------------------------------------------------------------\n");

View File

@ -57,18 +57,29 @@
#include "netlist/nl_dice_compat.h" #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 #define a10_555_desc_R K_OHM(70.0) // 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_C U_FARAD(0.1)
static Mono555Desc b9a_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
static Mono555Desc b9b_555_desc(K_OHM(70.0), U_FARAD(0.1)); // 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)); #define b9a_555_desc_R K_OHM(70.0) // actually 56k + 50k trimmer
static Mono555Desc g5_555_desc(K_OHM(220.0), U_FARAD(1.0)); #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 #if 0
static Paddle1VerticalDesc pad1_desc(17000.0, 145000.0, &a10_555_desc); static Paddle1VerticalDesc pad1_desc(17000.0, 145000.0, &a10_555_desc);
@ -126,7 +137,7 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("D4", 7430) CHIP("D4", 7430)
//CHIP("B10", 555_Mono, &b10_555_desc) //CHIP("B10", 555_Mono, &b10_555_desc)
CHIP_555_Mono(B10, &b10_555_desc) CHIP_555_Mono(B10, b10_555_desc)
// NETLIST - analog start // NETLIST - analog start
POT(B10_POT, RES_K(1)) // This is a guess!! POT(B10_POT, RES_K(1)) // This is a guess!!
@ -146,7 +157,7 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("A8", 7420) CHIP("A8", 7420)
//CHIP("A10", 555_Mono, &a10_555_desc) //CHIP("A10", 555_Mono, &a10_555_desc)
CHIP_555_Mono(A10, &a10_555_desc) CHIP_555_Mono(A10, a10_555_desc)
// NETLIST - analog start // NETLIST - analog start
POT(A10_POT, RES_K(1)) // This is a guess!! POT(A10_POT, RES_K(1)) // This is a guess!!
@ -180,10 +191,10 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("H5", 7400) CHIP("H5", 7400)
CHIP("E7", 7400) CHIP("E7", 7400)
//CHIP("F5", 555_Mono, &f5_555_desc) //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("G5", 555_Mono, &g5_555_desc)
CHIP_555_Mono(G5, &g5_555_desc) CHIP_555_Mono(G5, g5_555_desc)
CHIP("C3", 7474) CHIP("C3", 7474)
CHIP("C2", 7400) CHIP("C2", 7400)
@ -219,10 +230,10 @@ CIRCUIT_LAYOUT( pongdoubles )
CHIP("H10", 7474) CHIP("H10", 7474)
CHIP("G10", 7474) CHIP("G10", 7474)
//CHIP("A3", 555_Mono, &a3_555_desc) //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("B9A", 555_Mono, &b9a_555_desc)
CHIP_555_Mono(B9A, &b9a_555_desc) CHIP_555_Mono(B9A, b9a_555_desc)
// NETLIST - analog start // NETLIST - analog start
POT(B9A_POT, RES_K(1)) // This is a guess!! POT(B9A_POT, RES_K(1)) // This is a guess!!
@ -236,7 +247,7 @@ CIRCUIT_LAYOUT( pongdoubles )
// NETLIST - analog end // NETLIST - analog end
//CHIP("B9B", 555_Mono, &b9b_555_desc) //CHIP("B9B", 555_Mono, &b9b_555_desc)
CHIP_555_Mono(B9B, &b9b_555_desc) CHIP_555_Mono(B9B, b9b_555_desc)
// NETLIST - analog start // NETLIST - analog start
POT(B9B_POT, RES_K(1)) // This is a guess!! POT(B9B_POT, RES_K(1)) // This is a guess!!
@ -249,7 +260,7 @@ CIRCUIT_LAYOUT( pongdoubles )
NET_C(B9B_RPRE.2, B9B.5) NET_C(B9B_RPRE.2, B9B.5)
// NETLIST - analog end // NETLIST - analog end
CHIP_SERIES_RC(C33, &c33_desc) CHIP_SERIES_RC(C33, c33_desc)
#if 0 #if 0
CHIP("PAD1", PADDLE1_VERTICAL_INPUT, &pad1_desc) CHIP("PAD1", PADDLE1_VERTICAL_INPUT, &pad1_desc)