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:
couriersud 2015-06-08 01:39:51 +02:00
parent 3cf2f2444f
commit 7cd0008654
8 changed files with 120 additions and 13 deletions

View File

@ -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")

View File

@ -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;
};
// -----------------------------------------------------------------------------

View File

@ -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

View File

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

View File

@ -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 &param, const double value)
{
// FIXME: there should be a better way

View File

@ -151,6 +151,7 @@ public:
void register_link(const pstring &sin, const pstring &sout);
void register_param(const pstring &param, const pstring &value);
void register_param(const pstring &param, 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);

View File

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

View File

@ -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++)