mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
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:
parent
a5f06c7695
commit
b8c43342d5
@ -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
|
||||
|
@ -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() != "")
|
||||
|
@ -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"
|
||||
|
@ -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_ */
|
||||
|
@ -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")
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -1,6 +1,6 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Couriersud
|
||||
#include "nlm_opamp.h"
|
||||
|
||||
#include "netlist/devices/net_lib.h"
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
@ -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}")
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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> ¶ms_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);
|
||||
|
@ -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> ¶ms_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 ¶m, const pstring &value);
|
||||
|
@ -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)];
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
#define PSTRINGIFY_HELP(y) # y
|
||||
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user