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(VCCS, VCCS, "-")
ENTRY(CCCS, CCCS, "-") ENTRY(CCCS, CCCS, "-")
ENTRY(dummy_input, DUMMY_INPUT, "-") 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_EB, QBJT_EB, "model")
ENTRY(QBJT_switch, QBJT_SW, "model") ENTRY(QBJT_switch, QBJT_SW, "model")
ENTRY(ttl_input, TTL_INPUT, "IN") ENTRY(ttl_input, TTL_INPUT, "IN")

View File

@ -44,19 +44,26 @@
#define DUMMY_INPUT(_name) \ #define DUMMY_INPUT(_name) \
NET_REGISTER_DEV(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_REGISTER_DEV(frontier, _name) \
NET_C(_IN, _name.I) \ NET_C(_IN, _name.I) \
NET_C(_G, _name.G) \
NET_C(_OUT, _name.Q) 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) \ #define RES_SWITCH(_name, _IN, _P1, _P2) \
NET_REGISTER_DEV(res_sw, _name) \ NET_REGISTER_DEV(res_sw, _name) \
NET_C(_IN, _name.I) \ NET_C(_IN, _name.I) \
NET_C(_P1, _name.1) \ NET_C(_P1, _name.1) \
NET_C(_P2, _name.2) NET_C(_P2, _name.2)
/* Default device to hold netlist parameters */ /* Default device to hold netlist parameters */
#define PARAMETERS(_name) \ #define PARAMETERS(_name) \
NET_REGISTER_DEV(netlistparams, _name) NET_REGISTER_DEV(netlistparams, _name)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// mainclock // mainclock
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -207,12 +214,24 @@ protected:
void start() void start()
{ {
register_input("I", m_I); register_param("RIN", m_p_RIN, 1.0e6);
register_output("Q", m_Q); 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() 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() void update()
@ -221,9 +240,13 @@ protected:
} }
private: private:
NETLIB_NAME(twoterm) m_RIN;
NETLIB_NAME(twoterm) m_ROUT;
netlist_analog_input_t m_I; netlist_analog_input_t m_I;
netlist_analog_output_t m_Q; 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_ALIAS = register_token("ALIAS");
m_tok_NET_C = register_token("NET_C"); m_tok_NET_C = register_token("NET_C");
m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
m_tok_PARAM = register_token("PARAM"); m_tok_PARAM = register_token("PARAM");
m_tok_NET_MODEL = register_token("NET_MODEL"); m_tok_NET_MODEL = register_token("NET_MODEL");
m_tok_INCLUDE = register_token("INCLUDE"); m_tok_INCLUDE = register_token("INCLUDE");
@ -117,6 +118,8 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname)
net_alias(); net_alias();
else if (token.is(m_tok_NET_C)) else if (token.is(m_tok_NET_C))
net_c(); net_c();
else if (token.is(m_tok_FRONTIER))
frontier();
else if (token.is(m_tok_PARAM)) else if (token.is(m_tok_PARAM))
netdev_param(); netdev_param();
else if (token.is(m_tok_NET_MODEL)) else if (token.is(m_tok_NET_MODEL))
@ -217,6 +220,19 @@ void netlist_parser::net_submodel()
m_setup.namespace_pop(); 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() void netlist_parser::net_include()
{ {
// don't do much // don't do much

View File

@ -25,6 +25,7 @@ public:
void net_alias(); void net_alias();
void netdev_param(); void netdev_param();
void net_c(); void net_c();
void frontier();
void device(const pstring &dev_type); void device(const pstring &dev_type);
void netdev_netlist_start(); void netdev_netlist_start();
void netdev_netlist_end(); void netdev_netlist_end();
@ -48,6 +49,7 @@ private:
token_id_t m_tok_comma; token_id_t m_tok_comma;
token_id_t m_tok_ALIAS; token_id_t m_tok_ALIAS;
token_id_t m_tok_NET_C; token_id_t m_tok_NET_C;
token_id_t m_tok_FRONTIER;
token_id_t m_tok_PARAM; token_id_t m_tok_PARAM;
token_id_t m_tok_NET_MODEL; token_id_t m_tok_NET_MODEL;
token_id_t m_tok_NETLIST_START; 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()); // 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) void netlist_setup_t::register_param(const pstring &param, const double value)
{ {
// FIXME: there should be a better way // 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_link(const pstring &sin, const pstring &sout);
void register_param(const pstring &param, const pstring &value); void register_param(const pstring &param, const pstring &value);
void register_param(const pstring &param, const double 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); 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); 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() ppreprocessor::ppreprocessor()
{ {
m_expr_sep.add("!");
m_expr_sep.add("("); m_expr_sep.add("(");
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 == "(") if (tok == "(")
{ {
start++; start++;
val = expr(sexpr, start, prio); val = expr(sexpr, start, /*prio*/ 0);
if (sexpr[start] != ")") if (sexpr[start] != ")")
error("parsing error!"); error("parsing error!");
start++; start++;
} }
else if (tok == "!")
{
start++;
val = expr(sexpr, start, 90);
if (val != 0)
val = 0;
else
val = 1;
}
else else
{ {
tok=sexpr[start]; tok=sexpr[start];

View File

@ -5,8 +5,30 @@
* *
*/ */
#include <algorithm>
#include "nl_convert.h" #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 convert - convert a spice netlist
-------------------------------------------------*/ -------------------------------------------------*/
@ -72,17 +94,20 @@ void nl_convert_base_t::dump_nl()
if (net->terminals().size() == 1) if (net->terminals().size() == 1)
net->set_no_export(); net->set_no_export();
} }
plist_t<int> sorted = bubble(m_devs);
for (std::size_t i=0; i<m_devs.size(); i++) for (std::size_t i=0; i<m_devs.size(); i++)
{ {
if (m_devs[i]->has_value()) std::size_t j = sorted[i];
out("%s(%s, %s)\n", m_devs[i]->type().cstr(),
m_devs[i]->name().cstr(), get_nl_val(m_devs[i]->value()).cstr()); if (m_devs[j]->has_value())
else if (m_devs[i]->has_model()) out("%s(%s, %s)\n", m_devs[j]->type().cstr(),
out("%s(%s, \"%s\")\n", m_devs[i]->type().cstr(), m_devs[j]->name().cstr(), get_nl_val(m_devs[j]->value()).cstr());
m_devs[i]->name().cstr(), m_devs[i]->model().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 else
out("%s(%s)\n", m_devs[i]->type().cstr(), out("%s(%s)\n", m_devs[j]->type().cstr(),
m_devs[i]->name().cstr()); m_devs[j]->name().cstr());
} }
// print nets // print nets
for (std::size_t i=0; i<m_nets.size(); i++) for (std::size_t i=0; i<m_nets.size(); i++)