mirror of
https://github.com/holub/mame
synced 2025-07-03 09:06:08 +03:00
Made it more convenient to add frontiers (impedance barriers). These
- at the right place - enable netlist to split a netlist into multiple smaller netlists. Side mark: The "old" discrete system assumed such a device in every node. (nw)
This commit is contained in:
parent
3cf2f2444f
commit
7cd0008654
@ -52,7 +52,7 @@ void nl_initialize_factory(netlist_factory_list_t &factory)
|
||||
ENTRY(VCCS, VCCS, "-")
|
||||
ENTRY(CCCS, CCCS, "-")
|
||||
ENTRY(dummy_input, DUMMY_INPUT, "-")
|
||||
ENTRY(frontier, FRONTIER, "+I,Q")
|
||||
ENTRY(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly
|
||||
ENTRY(QBJT_EB, QBJT_EB, "model")
|
||||
ENTRY(QBJT_switch, QBJT_SW, "model")
|
||||
ENTRY(ttl_input, TTL_INPUT, "IN")
|
||||
|
@ -44,19 +44,26 @@
|
||||
#define DUMMY_INPUT(_name) \
|
||||
NET_REGISTER_DEV(dummy_input, _name)
|
||||
|
||||
#define FRONTIER(_name, _IN, _OUT) \
|
||||
//FIXME: Usage discouraged, use OPTIMIZE_FRONTIER instead
|
||||
#define FRONTIER_DEV(_name, _IN, _G, _OUT) \
|
||||
NET_REGISTER_DEV(frontier, _name) \
|
||||
NET_C(_IN, _name.I) \
|
||||
NET_C(_G, _name.G) \
|
||||
NET_C(_OUT, _name.Q)
|
||||
|
||||
#define OPTIMIZE_FRONTIER(_attach, _r_in, _r_out) \
|
||||
setup.register_frontier(# _attach, _r_in, _r_out);
|
||||
|
||||
#define RES_SWITCH(_name, _IN, _P1, _P2) \
|
||||
NET_REGISTER_DEV(res_sw, _name) \
|
||||
NET_C(_IN, _name.I) \
|
||||
NET_C(_P1, _name.1) \
|
||||
NET_C(_P2, _name.2)
|
||||
|
||||
/* Default device to hold netlist parameters */
|
||||
#define PARAMETERS(_name) \
|
||||
NET_REGISTER_DEV(netlistparams, _name)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// mainclock
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -207,12 +214,24 @@ protected:
|
||||
|
||||
void start()
|
||||
{
|
||||
register_input("I", m_I);
|
||||
register_output("Q", m_Q);
|
||||
register_param("RIN", m_p_RIN, 1.0e6);
|
||||
register_param("ROUT", m_p_ROUT, 50.0);
|
||||
|
||||
register_input("_I", m_I);
|
||||
register_terminal("I",m_RIN.m_P);
|
||||
register_terminal("G",m_RIN.m_N);
|
||||
connect(m_I, m_RIN.m_P);
|
||||
|
||||
register_output("_Q", m_Q);
|
||||
register_terminal("_OP",m_ROUT.m_P);
|
||||
register_terminal("Q",m_ROUT.m_N);
|
||||
connect(m_Q, m_ROUT.m_P);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_RIN.set(1.0 / m_p_RIN.Value(),0,0);
|
||||
m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0);
|
||||
}
|
||||
|
||||
void update()
|
||||
@ -221,9 +240,13 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
NETLIB_NAME(twoterm) m_RIN;
|
||||
NETLIB_NAME(twoterm) m_ROUT;
|
||||
netlist_analog_input_t m_I;
|
||||
netlist_analog_output_t m_Q;
|
||||
|
||||
netlist_param_double_t m_p_RIN;
|
||||
netlist_param_double_t m_p_ROUT;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -49,6 +49,7 @@ bool netlist_parser::parse(const char *buf, const pstring nlname)
|
||||
|
||||
m_tok_ALIAS = register_token("ALIAS");
|
||||
m_tok_NET_C = register_token("NET_C");
|
||||
m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
|
||||
m_tok_PARAM = register_token("PARAM");
|
||||
m_tok_NET_MODEL = register_token("NET_MODEL");
|
||||
m_tok_INCLUDE = register_token("INCLUDE");
|
||||
@ -117,6 +118,8 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname)
|
||||
net_alias();
|
||||
else if (token.is(m_tok_NET_C))
|
||||
net_c();
|
||||
else if (token.is(m_tok_FRONTIER))
|
||||
frontier();
|
||||
else if (token.is(m_tok_PARAM))
|
||||
netdev_param();
|
||||
else if (token.is(m_tok_NET_MODEL))
|
||||
@ -217,6 +220,19 @@ void netlist_parser::net_submodel()
|
||||
m_setup.namespace_pop();
|
||||
}
|
||||
|
||||
void netlist_parser::frontier()
|
||||
{
|
||||
// don't do much
|
||||
pstring attachat = get_identifier();
|
||||
require_token(m_tok_comma);
|
||||
double r_IN = eval_param(get_token());
|
||||
require_token(m_tok_comma);
|
||||
double r_OUT = eval_param(get_token());
|
||||
require_token(m_tok_param_right);
|
||||
|
||||
m_setup.register_frontier(attachat, r_IN, r_OUT);
|
||||
}
|
||||
|
||||
void netlist_parser::net_include()
|
||||
{
|
||||
// don't do much
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
void net_alias();
|
||||
void netdev_param();
|
||||
void net_c();
|
||||
void frontier();
|
||||
void device(const pstring &dev_type);
|
||||
void netdev_netlist_start();
|
||||
void netdev_netlist_end();
|
||||
@ -48,6 +49,7 @@ private:
|
||||
token_id_t m_tok_comma;
|
||||
token_id_t m_tok_ALIAS;
|
||||
token_id_t m_tok_NET_C;
|
||||
token_id_t m_tok_FRONTIER;
|
||||
token_id_t m_tok_PARAM;
|
||||
token_id_t m_tok_NET_MODEL;
|
||||
token_id_t m_tok_NETLIST_START;
|
||||
|
@ -295,6 +295,36 @@ void netlist_setup_t::register_link(const pstring &sin, const pstring &sout)
|
||||
// fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr());
|
||||
}
|
||||
|
||||
void netlist_setup_t::register_frontier(const pstring attach, const double r_IN, const double r_OUT)
|
||||
{
|
||||
static int frontier_cnt = 0;
|
||||
pstring frontier_name = pstring::sprintf("frontier_%d", frontier_cnt);
|
||||
frontier_cnt++;
|
||||
netlist_device_t *front = register_dev("nld_frontier", frontier_name);
|
||||
register_param(frontier_name + ".RIN", r_IN);
|
||||
register_param(frontier_name + ".ROUT", r_OUT);
|
||||
register_link(frontier_name + ".G", "GND");
|
||||
pstring attfn = build_fqn(attach);
|
||||
bool found = false;
|
||||
for (std::size_t i = 0; i < m_links.size(); i++)
|
||||
{
|
||||
if (m_links[i].e1 == attfn)
|
||||
{
|
||||
m_links[i].e1 = front->name() + ".I";
|
||||
found = true;
|
||||
}
|
||||
else if (m_links[i].e2 == attfn)
|
||||
{
|
||||
m_links[i].e2 = front->name() + ".I";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
netlist().error("Frontier setup: found no occurrence of %s\n", attach.cstr());
|
||||
register_link(attach, frontier_name + ".Q");
|
||||
}
|
||||
|
||||
|
||||
void netlist_setup_t::register_param(const pstring ¶m, const double value)
|
||||
{
|
||||
// FIXME: there should be a better way
|
||||
|
@ -151,6 +151,7 @@ public:
|
||||
void register_link(const pstring &sin, const pstring &sout);
|
||||
void register_param(const pstring ¶m, const pstring &value);
|
||||
void register_param(const pstring ¶m, const double value);
|
||||
void register_frontier(const pstring attach, const double r_IN, const double r_OUT);
|
||||
|
||||
void register_object(netlist_device_t &dev, const pstring &name, netlist_object_t &obj);
|
||||
bool connect(netlist_core_terminal_t &t1, netlist_core_terminal_t &t2);
|
||||
|
@ -267,6 +267,7 @@ ATTR_COLD void ptokenizer::error(const char *format, ...)
|
||||
|
||||
ppreprocessor::ppreprocessor()
|
||||
{
|
||||
m_expr_sep.add("!");
|
||||
m_expr_sep.add("(");
|
||||
m_expr_sep.add(")");
|
||||
m_expr_sep.add("+");
|
||||
@ -294,11 +295,20 @@ double ppreprocessor::expr(const pstring_list_t &sexpr, std::size_t &start, int
|
||||
if (tok == "(")
|
||||
{
|
||||
start++;
|
||||
val = expr(sexpr, start, prio);
|
||||
val = expr(sexpr, start, /*prio*/ 0);
|
||||
if (sexpr[start] != ")")
|
||||
error("parsing error!");
|
||||
start++;
|
||||
}
|
||||
else if (tok == "!")
|
||||
{
|
||||
start++;
|
||||
val = expr(sexpr, start, 90);
|
||||
if (val != 0)
|
||||
val = 0;
|
||||
else
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tok=sexpr[start];
|
||||
|
@ -5,8 +5,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "nl_convert.h"
|
||||
|
||||
template<typename Class>
|
||||
static plist_t<int> bubble(const pnamedlist_t<Class *> &sl)
|
||||
{
|
||||
plist_t<int> ret(sl.size());
|
||||
for (int i=0; i<sl.size(); i++)
|
||||
ret[i] = i;
|
||||
|
||||
for(int i=0; i < sl.size()-1;i++)
|
||||
{
|
||||
for(int j=i+1; j < sl.size(); j++)
|
||||
{
|
||||
if(sl[ret[i]]->name() > sl[ret[j]]->name())
|
||||
{
|
||||
std::swap(ret[i], ret[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
convert - convert a spice netlist
|
||||
-------------------------------------------------*/
|
||||
@ -72,17 +94,20 @@ void nl_convert_base_t::dump_nl()
|
||||
if (net->terminals().size() == 1)
|
||||
net->set_no_export();
|
||||
}
|
||||
plist_t<int> sorted = bubble(m_devs);
|
||||
for (std::size_t i=0; i<m_devs.size(); i++)
|
||||
{
|
||||
if (m_devs[i]->has_value())
|
||||
out("%s(%s, %s)\n", m_devs[i]->type().cstr(),
|
||||
m_devs[i]->name().cstr(), get_nl_val(m_devs[i]->value()).cstr());
|
||||
else if (m_devs[i]->has_model())
|
||||
out("%s(%s, \"%s\")\n", m_devs[i]->type().cstr(),
|
||||
m_devs[i]->name().cstr(), m_devs[i]->model().cstr());
|
||||
std::size_t j = sorted[i];
|
||||
|
||||
if (m_devs[j]->has_value())
|
||||
out("%s(%s, %s)\n", m_devs[j]->type().cstr(),
|
||||
m_devs[j]->name().cstr(), get_nl_val(m_devs[j]->value()).cstr());
|
||||
else if (m_devs[j]->has_model())
|
||||
out("%s(%s, \"%s\")\n", m_devs[j]->type().cstr(),
|
||||
m_devs[j]->name().cstr(), m_devs[j]->model().cstr());
|
||||
else
|
||||
out("%s(%s)\n", m_devs[i]->type().cstr(),
|
||||
m_devs[i]->name().cstr());
|
||||
out("%s(%s)\n", m_devs[j]->type().cstr(),
|
||||
m_devs[j]->name().cstr());
|
||||
}
|
||||
// print nets
|
||||
for (std::size_t i=0; i<m_nets.size(); i++)
|
||||
|
Loading…
Reference in New Issue
Block a user