summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/nl_setup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/nl_setup.cpp')
-rw-r--r--src/lib/netlist/nl_setup.cpp838
1 files changed, 494 insertions, 344 deletions
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index df761bc3f88..b9300f5ad9c 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -6,128 +6,243 @@
*/
#include "plib/palloc.h"
-#include "plib/putil.h"
+#include "analog/nld_twoterm.h"
+#include "devices/nlid_proxy.h"
+#include "devices/nlid_system.h"
+#include "devices/nlid_truthtable.h"
#include "nl_base.h"
-#include "nl_setup.h"
-#include "nl_parser.h"
#include "nl_factory.h"
-#include "devices/nlid_system.h"
-#include "devices/nlid_proxy.h"
-#include "analog/nld_twoterm.h"
+#include "nl_parser.h"
+#include "nl_setup.h"
+#include "plib/putil.h"
#include "solver/nld_solver.h"
-#include "devices/nlid_truthtable.h"
-// ----------------------------------------------------------------------------------------
-// setup_t
-// ----------------------------------------------------------------------------------------
+#include <cmath>
namespace netlist
{
-setup_t::setup_t(netlist_t &netlist)
- : m_netlist(netlist)
- , m_factory(*this)
- , m_proxy_cnt(0)
+ // ----------------------------------------------------------------------------------------
+ // nl_parse_t
+ // ----------------------------------------------------------------------------------------
+
+ nlparse_t::nlparse_t(setup_t &setup, log_type &log)
+ : m_factory(log)
+ , m_setup(setup)
+ , m_log(log)
, m_frontier_cnt(0)
-{
- devices::initialize_factory(m_factory);
-}
+ { }
-setup_t::~setup_t()
-{
- m_links.clear();
- m_alias.clear();
- m_params.clear();
- m_terminals.clear();
- m_param_values.clear();
+ void nlparse_t::register_alias(const pstring &alias, const pstring &out)
+ {
+ pstring alias_fqn = build_fqn(alias);
+ pstring out_fqn = build_fqn(out);
+ register_alias_nofqn(alias_fqn, out_fqn);
+ }
- m_sources.clear();
-}
+ void nlparse_t::register_dippins_arr(const pstring &terms)
+ {
+ std::vector<pstring> list(plib::psplit(terms,", "));
+ if (list.size() == 0 || (list.size() % 2) == 1)
+ log().fatal(MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1,
+ build_fqn(""));
+ std::size_t n = list.size();
+ for (std::size_t i = 0; i < n / 2; i++)
+ {
+ register_alias(plib::pfmt("{1}")(i+1), list[i * 2]);
+ register_alias(plib::pfmt("{1}")(n-i), list[i * 2 + 1]);
+ }
+ }
-pstring setup_t::build_fqn(const pstring &obj_name) const
-{
- if (m_namespace_stack.empty())
- //return netlist().name() + "." + obj_name;
- return obj_name;
- else
- return m_namespace_stack.top() + "." + obj_name;
-}
+ void nlparse_t::register_dev(const pstring &classname, const pstring &name)
+ {
+ auto f = m_factory.factory_by_name(classname);
+ if (f == nullptr)
+ log().fatal(MF_1_CLASS_1_NOT_FOUND, classname);
+ else
+ {
+ /* make sure we parse macro library entries */
+ f->macro_actions(*this, name);
+ pstring key = build_fqn(name);
+ if (device_exists(key))
+ log().fatal(MF_1_DEVICE_ALREADY_EXISTS_1, name);
+ else
+ m_device_factory.insert(m_device_factory.end(), {key, f});
+ }
+ }
-void setup_t::namespace_push(const pstring &aname)
-{
- if (m_namespace_stack.empty())
- //m_namespace_stack.push(netlist().name() + "." + aname);
- m_namespace_stack.push(aname);
- else
- m_namespace_stack.push(m_namespace_stack.top() + "." + aname);
-}
+ void nlparse_t::register_link(const pstring &sin, const pstring &sout)
+ {
+ register_link_fqn(build_fqn(sin), build_fqn(sout));
+ }
-void setup_t::namespace_pop()
-{
- m_namespace_stack.pop();
-}
+ void nlparse_t::register_link_arr(const pstring &terms)
+ {
+ std::vector<pstring> list(plib::psplit(terms,", "));
+ if (list.size() < 2)
+ log().fatal(MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL);
+ for (std::size_t i = 1; i < list.size(); i++)
+ {
+ register_link(list[0], list[i]);
+ }
+ }
-void setup_t::register_lib_entry(const pstring &name, const pstring &sourcefile)
-{
- factory().register_device(plib::make_unique_base<factory::element_t, factory::library_element_t>(*this, name, name, "", sourcefile));
-}
+ void nlparse_t::include(const pstring &netlist_name)
+ {
+ for (auto &source : m_sources)
+ {
+ if (source->parse(*this, netlist_name))
+ return;
+ }
+ log().fatal(MF_1_NOT_FOUND_IN_SOURCE_COLLECTION, netlist_name);
+ }
-void setup_t::register_dev(const pstring &classname, const pstring &name)
-{
- auto f = factory().factory_by_name(classname);
- if (f == nullptr)
- log().fatal(MF_1_CLASS_1_NOT_FOUND, classname);
- /* make sure we parse macro library entries */
- f->macro_actions(netlist(), name);
- m_device_factory.push_back(std::pair<pstring, factory::element_t *>(build_fqn(name), f));
-}
-bool setup_t::device_exists(const pstring &name) const
-{
- for (auto e : m_device_factory)
+ void nlparse_t::namespace_push(const pstring &aname)
{
- if (e.first == name)
- return true;
+ if (m_namespace_stack.empty())
+ //m_namespace_stack.push(netlist().name() + "." + aname);
+ m_namespace_stack.push(aname);
+ else
+ m_namespace_stack.push(m_namespace_stack.top() + "." + aname);
}
- return false;
-}
+ void nlparse_t::namespace_pop()
+ {
+ m_namespace_stack.pop();
+ }
-void setup_t::register_model(const pstring &model_in)
-{
- auto pos = model_in.find(" ");
- if (pos == pstring::npos)
- log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
- pstring model = model_in.left(pos).trim().ucase();
- pstring def = model_in.substr(pos + 1).trim();
- if (!m_models.insert({model, def}).second)
- log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
-}
+ void nlparse_t::register_param(const pstring &param, const double value)
+ {
+ if (std::abs(value - std::floor(value)) > 1e-30 || std::abs(value) > 1e9)
+ register_param(param, plib::pfmt("{1:.9}").e(value));
+ else
+ register_param(param, plib::pfmt("{1}")(static_cast<long>(value)));
+ }
-void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
-{
- if (!m_alias.insert({alias, out}).second)
- log().fatal(MF_1_ADDING_ALI1_TO_ALIAS_LIST, alias);
-}
+ void nlparse_t::register_param(const pstring &param, const pstring &value)
+ {
+ pstring fqn = build_fqn(param);
+
+ auto idx = m_param_values.find(fqn);
+ if (idx == m_param_values.end())
+ {
+ if (!m_param_values.insert({fqn, value}).second)
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST,
+ param);
+ }
+ else
+ {
+ log().warning(MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3, fqn, idx->second,
+ value);
+ m_param_values[fqn] = value;
+ }
+ }
+
+ void nlparse_t::register_lib_entry(const pstring &name, const pstring &sourcefile)
+ {
+ m_factory.register_device(plib::make_unique<factory::library_element_t>(name, name, "", sourcefile));
+ }
+
+ void nlparse_t::register_frontier(const pstring &attach, const double r_IN, const double r_OUT)
+ {
+ pstring frontier_name = plib::pfmt("frontier_{1}")(m_frontier_cnt);
+ m_frontier_cnt++;
+ register_dev("FRONTIER_DEV", 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);
+ pstring front_fqn = build_fqn(frontier_name);
+ bool found = false;
+ for (auto & link : m_links)
+ {
+ if (link.first == attfn)
+ {
+ link.first = front_fqn + ".I";
+ found = true;
+ }
+ else if (link.second == attfn)
+ {
+ link.second = front_fqn + ".I";
+ found = true;
+ }
+ }
+ if (!found)
+ log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, attach);
+ register_link(attach, frontier_name + ".Q");
+ }
+
+ void nlparse_t::tt_factory_create(tt_desc &desc, const pstring &sourcefile)
+ {
+ auto fac = devices::tt_factory_create(desc, sourcefile);
+ m_factory.register_device(std::move(fac));
+ }
+
+ pstring nlparse_t::build_fqn(const pstring &obj_name) const
+ {
+ if (m_namespace_stack.empty())
+ //return netlist().name() + "." + obj_name;
+ return obj_name;
+ else
+ return m_namespace_stack.top() + "." + obj_name;
+ }
+
+ void nlparse_t::register_alias_nofqn(const pstring &alias, const pstring &out)
+ {
+ if (!m_alias.insert({alias, out}).second)
+ log().fatal(MF_1_ADDING_ALI1_TO_ALIAS_LIST, alias);
+ }
+
+ void nlparse_t::register_link_fqn(const pstring &sin, const pstring &sout)
+ {
+ link_t temp = link_t(sin, sout);
+ log().debug("link {1} <== {2}\n", sin, sout);
+ m_links.push_back(temp);
+ }
-void setup_t::register_alias(const pstring &alias, const pstring &out)
+ bool nlparse_t::device_exists(const pstring &name) const
+ {
+ for (auto &d : m_device_factory)
+ if (d.first == name)
+ return true;
+ return false;
+ }
+
+ bool nlparse_t::parse_stream(plib::unique_ptr<plib::pistream> &&istrm, const pstring &name)
+ {
+ return parser_t(std::move(plib::ppreprocessor(&m_defines).process(std::move(istrm))), *this).parse(name);
+ }
+
+ void nlparse_t::add_define(const pstring &defstr)
+ {
+ auto p = defstr.find("=");
+ if (p != pstring::npos)
+ add_define(plib::left(defstr, p), defstr.substr(p+1));
+ else
+ add_define(defstr, "1");
+ }
+
+ // ----------------------------------------------------------------------------------------
+ // setup_t
+ // ----------------------------------------------------------------------------------------
+
+
+setup_t::setup_t(netlist_state_t &nlstate)
+ : nlparse_t(*this, nlstate.log())
+ , m_nlstate(nlstate)
+ , m_netlist_params(nullptr)
+ , m_proxy_cnt(0)
{
- pstring alias_fqn = build_fqn(alias);
- pstring out_fqn = build_fqn(out);
- register_alias_nofqn(alias_fqn, out_fqn);
}
-void setup_t::register_dippins_arr(const pstring &terms)
+setup_t::~setup_t() noexcept
{
- std::vector<pstring> list(plib::psplit(terms,", "));
- if (list.size() == 0 || (list.size() % 2) == 1)
- log().fatal(MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1,
- build_fqn(""));
- std::size_t n = list.size();
- for (std::size_t i = 0; i < n / 2; i++)
- {
- register_alias(plib::pfmt("{1}")(i+1), list[i * 2]);
- register_alias(plib::pfmt("{1}")(n-i), list[i * 2 + 1]);
- }
+ // FIXME: can't see a need any longer
+ m_links.clear();
+ m_params.clear();
+ m_terminals.clear();
+ m_param_values.clear();
+ m_sources.clear();
}
pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
@@ -145,7 +260,7 @@ pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
return pstring("Error");
}
-pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def)
+pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def) const
{
auto i = m_param_values.find(name);
if (i != m_param_values.end())
@@ -154,40 +269,6 @@ pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def)
return def;
}
-double setup_t::get_initial_param_val(const pstring &name, const double def)
-{
- auto i = m_param_values.find(name);
- if (i != m_param_values.end())
- {
- double vald = 0;
- if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
- log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
- return vald;
- }
- else
- return def;
-}
-
-int setup_t::get_initial_param_val(const pstring &name, const int def)
-{
- auto i = m_param_values.find(name);
- if (i != m_param_values.end())
- {
- double vald = 0;
- if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
- log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
- return static_cast<int>(vald);
- }
- else
- return def;
-}
-
-void setup_t::register_param(const pstring &name, param_t &param)
-{
- if (!m_params.insert({param.name(), param_ref_t(param.name(), param.device(), param)}).second)
- log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST, name);
-}
-
void setup_t::register_term(detail::core_terminal_t &term)
{
if (!m_terminals.insert({term.name(), &term}).second)
@@ -196,30 +277,6 @@ void setup_t::register_term(detail::core_terminal_t &term)
log().debug("{1} {2}\n", termtype_as_str(term), term.name());
}
-void setup_t::register_link_arr(const pstring &terms)
-{
- std::vector<pstring> list(plib::psplit(terms,", "));
- if (list.size() < 2)
- log().fatal(MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL);
- for (std::size_t i = 1; i < list.size(); i++)
- {
- register_link(list[0], list[i]);
- }
-}
-
-
-void setup_t::register_link_fqn(const pstring &sin, const pstring &sout)
-{
- link_t temp = link_t(sin, sout);
- log().debug("link {1} <== {2}\n", sin, sout);
- m_links.push_back(temp);
-}
-
-void setup_t::register_link(const pstring &sin, const pstring &sout)
-{
- register_link_fqn(build_fqn(sin), build_fqn(sout));
-}
-
void setup_t::remove_connections(const pstring &pin)
{
pstring pinfn = build_fqn(pin);
@@ -241,59 +298,14 @@ void setup_t::remove_connections(const pstring &pin)
}
-void setup_t::register_frontier(const pstring &attach, const double r_IN, const double r_OUT)
-{
- pstring frontier_name = plib::pfmt("frontier_{1}")(m_frontier_cnt);
- m_frontier_cnt++;
- register_dev("FRONTIER_DEV", 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);
- pstring front_fqn = build_fqn(frontier_name);
- bool found = false;
- for (auto & link : m_links)
- {
- if (link.first == attfn)
- {
- link.first = front_fqn + ".I";
- found = true;
- }
- else if (link.second == attfn)
- {
- link.second = front_fqn + ".I";
- found = true;
- }
- }
- if (!found)
- log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, attach);
- register_link(attach, frontier_name + ".Q");
-}
-
-void setup_t::register_param(const pstring &param, const double value)
+void setup_t::register_param_t(const pstring &name, param_t &param)
{
- register_param(param, plib::pfmt("{1:.9}").e(value));
+ if (!m_params.insert({param.name(), param_ref_t(param.name(), param.device(), param)}).second)
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST, name);
}
-void setup_t::register_param(const pstring &param, const pstring &value)
-{
- pstring fqn = build_fqn(param);
- auto idx = m_param_values.find(fqn);
- if (idx == m_param_values.end())
- {
- if (!m_param_values.insert({fqn, value}).second)
- log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST,
- param);
- }
- else
- {
- log().warning(MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3, fqn, idx->second,
- value);
- m_param_values[fqn] = value;
- }
-}
const pstring setup_t::resolve_alias(const pstring &name) const
{
@@ -311,6 +323,42 @@ const pstring setup_t::resolve_alias(const pstring &name) const
return ret;
}
+std::vector<pstring> setup_t::get_terminals_for_device_name(const pstring &devname)
+{
+ std::vector<pstring> terms;
+ for (auto & t : m_terminals)
+ {
+ if (plib::startsWith(t.second->name(), devname))
+ {
+ pstring tn(t.second->name().substr(devname.length()+1));
+ if (tn.find(".") == pstring::npos)
+ terms.push_back(tn);
+ }
+ }
+
+ for (auto & t : m_alias)
+ {
+ if (plib::startsWith(t.first, devname))
+ {
+ pstring tn(t.first.substr(devname.length()+1));
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), tn.c_str());
+ if (tn.find(".") == pstring::npos)
+ {
+ terms.push_back(tn);
+ pstring resolved = resolve_alias(t.first);
+ //printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), resolved.c_str());
+ if (resolved != t.first)
+ {
+ auto found = std::find(terms.begin(), terms.end(), resolved.substr(devname.length()+1));
+ if (found!=terms.end())
+ terms.erase(found);
+ }
+ }
+ }
+ }
+ return terms;
+}
+
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
@@ -377,7 +425,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
{
nl_assert(out.is_logic());
- logic_output_t &out_cast = static_cast<logic_output_t &>(out);
+ auto &out_cast = static_cast<logic_output_t &>(out);
devices::nld_base_proxy *proxy = out_cast.get_proxy();
if (proxy == nullptr)
@@ -385,28 +433,25 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
// create a new one ...
pstring x = plib::pfmt("proxy_da_{1}_{2}")(out.name())(m_proxy_cnt);
auto new_proxy =
- out_cast.logic_family()->create_d_a_proxy(netlist(), x, &out_cast);
+ out_cast.logic_family()->create_d_a_proxy(m_nlstate, x, &out_cast);
m_proxy_cnt++;
-
- //new_proxy->start_dev();
-
/* connect all existing terminals to new net */
- for (auto & p : out.net().m_core_terms)
+ for (auto & p : out.net().core_terms())
{
p->clear_net(); // de-link from all nets ...
if (!connect(new_proxy->proxy_term(), *p))
log().fatal(MF_2_CONNECTING_1_TO_2,
new_proxy->proxy_term().name(), (*p).name());
}
- out.net().m_core_terms.clear(); // clear the list
+ out.net().core_terms().clear(); // clear the list
out.net().add_terminal(new_proxy->in());
out_cast.set_proxy(proxy);
proxy = new_proxy.get();
- netlist().register_dev(std::move(new_proxy));
+ m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
}
return proxy;
}
@@ -415,7 +460,7 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
nl_assert(inp.is_logic());
- logic_input_t &incast = dynamic_cast<logic_input_t &>(inp);
+ auto &incast = dynamic_cast<logic_input_t &>(inp);
devices::nld_base_proxy *proxy = incast.get_proxy();
if (proxy != nullptr)
@@ -424,7 +469,7 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
log().debug("connect_terminal_input: connecting proxy\n");
pstring x = plib::pfmt("proxy_ad_{1}_{2}")(inp.name())(m_proxy_cnt);
- auto new_proxy = incast.logic_family()->create_a_d_proxy(netlist(), x, &incast);
+ auto new_proxy = incast.logic_family()->create_a_d_proxy(m_nlstate, x, &incast);
//auto new_proxy = plib::owned_ptr<devices::nld_a_to_d_proxy>::Create(netlist(), x, &incast);
incast.set_proxy(new_proxy.get());
m_proxy_cnt++;
@@ -435,17 +480,17 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
if (inp.has_net())
{
- for (auto & p : inp.net().m_core_terms)
+ for (auto & p : inp.net().core_terms())
{
p->clear_net(); // de-link from all nets ...
if (!connect(ret->proxy_term(), *p))
log().fatal(MF_2_CONNECTING_1_TO_2,
ret->proxy_term().name(), (*p).name());
}
- inp.net().m_core_terms.clear(); // clear the list
+ inp.net().core_terms().clear(); // clear the list
}
ret->out().net().add_terminal(inp);
- netlist().register_dev(std::move(new_proxy));
+ m_nlstate.add_dev(new_proxy->name(), std::move(new_proxy));
return ret;
}
}
@@ -568,11 +613,12 @@ void setup_t::connect_terminals(detail::core_terminal_t &t1, detail::core_termin
{
log().debug("adding analog net ...\n");
// FIXME: Nets should have a unique name
- auto anet = plib::palloc<analog_net_t>(netlist(),"net." + t1.name());
- netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(anet, true));
- t1.set_net(anet);
- anet->add_terminal(t2);
- anet->add_terminal(t1);
+ auto anet = pool().make_poolptr<analog_net_t>(m_nlstate,"net." + t1.name());
+ auto anetp = anet.get();
+ m_nlstate.register_net(std::move(anet));
+ t1.set_net(anetp);
+ anetp->add_terminal(t2);
+ anetp->add_terminal(t1);
}
}
@@ -580,7 +626,7 @@ static detail::core_terminal_t &resolve_proxy(detail::core_terminal_t &term)
{
if (term.is_logic())
{
- logic_t &out = dynamic_cast<logic_t &>(term);
+ auto &out = dynamic_cast<logic_t &>(term);
if (out.has_proxy())
return out.get_proxy()->proxy_term();
}
@@ -596,7 +642,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
ret = connect(t2, t1.net().railterminal());
if (!ret)
{
- for (auto & t : t1.net().m_core_terms)
+ for (auto & t : t1.net().core_terms())
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t2, *t);
@@ -611,7 +657,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
ret = connect(t1, t2.net().railterminal());
if (!ret)
{
- for (auto & t : t2.net().m_core_terms)
+ for (auto & t : t2.net().core_terms())
{
if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t1, *t);
@@ -623,8 +669,6 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
return ret;
}
-
-
bool setup_t::connect(detail::core_terminal_t &t1_in, detail::core_terminal_t &t2_in)
{
log().debug("Connecting {1} to {2}\n", t1_in.name(), t2_in.name());
@@ -712,18 +756,7 @@ void setup_t::resolve_inputs()
// delete empty nets
- netlist().m_nets.erase(
- std::remove_if(netlist().m_nets.begin(), netlist().m_nets.end(),
- [](plib::owned_ptr<detail::net_t> &x)
- {
- if (x->num_cons() == 0)
- {
- x->netlist().log().verbose("Deleting net {1} ...", x->name());
- return true;
- }
- else
- return false;
- }), netlist().m_nets.end());
+ delete_empty_nets();
pstring errstr("");
@@ -744,7 +777,7 @@ void setup_t::resolve_inputs()
}
-void setup_t::start_devices()
+void setup_t::register_dynamic_log_devices()
{
pstring env = plib::util::environment("NL_LOGS", "");
@@ -752,41 +785,43 @@ void setup_t::start_devices()
{
log().debug("Creating dynamic logs ...");
std::vector<pstring> loglist(plib::psplit(env, ":"));
- for (pstring ll : loglist)
+ for (const pstring &ll : loglist)
{
pstring name = "log_" + ll;
- auto nc = factory().factory_by_name("LOG")->Create(netlist(), name);
+ auto nc = factory().factory_by_name("LOG")->Create(m_nlstate, name);
register_link(name + ".I", ll);
log().debug(" dynamic link {1}: <{2}>\n",ll, name);
- netlist().register_dev(std::move(nc));
+ m_nlstate.add_dev(nc->name(), std::move(nc));
}
}
}
-plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log()
+log_type &setup_t::log()
{
- return netlist().log();
+ return m_nlstate.log();
}
-const plib::plog_base<netlist_t, NL_DEBUG> &setup_t::log() const
+const log_type &setup_t::log() const
{
- return netlist().log();
+ return m_nlstate.log();
}
// ----------------------------------------------------------------------------------------
-// Model
+// Models
// ----------------------------------------------------------------------------------------
-static pstring model_string(detail::model_map_t &map)
+void models_t::register_model(pstring model_in)
{
- pstring ret = map["COREMODEL"] + "(";
- for (auto & i : map)
- ret = ret + i.first + "=" + i.second + " ";
-
- return ret + ")";
+ auto pos = model_in.find(" ");
+ if (pos == pstring::npos)
+ throw nl_exception(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
+ pstring model = plib::ucase(plib::trim(plib::left(model_in, pos)));
+ pstring def = plib::trim(model_in.substr(pos + 1));
+ if (!m_models.insert({model, def}).second)
+ throw nl_exception(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
}
-void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
+void models_t::model_parse(const pstring &model_in, model_map_t &map)
{
pstring model = model_in;
std::size_t pos = 0;
@@ -797,15 +832,15 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
pos = model.find("(");
if (pos != pstring::npos) break;
- key = model.ucase();
+ key = plib::ucase(model);
auto i = m_models.find(key);
if (i == m_models.end())
- log().fatal(MF_1_MODEL_NOT_FOUND, model);
+ throw nl_exception(MF_1_MODEL_NOT_FOUND, model);
model = i->second;
}
- pstring xmodel = model.left(pos);
+ pstring xmodel = plib::left(model, pos);
- if (xmodel.equals("_"))
+ if (xmodel == "_")
map["COREMODEL"] = key;
else
{
@@ -813,46 +848,65 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
if (i != m_models.end())
model_parse(xmodel, map);
else
- log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
+ throw nl_exception(MF_1_MODEL_NOT_FOUND, model_in);
}
- pstring remainder = model.substr(pos + 1).trim();
- if (!remainder.endsWith(")"))
- log().fatal(MF_1_MODEL_ERROR_1, model);
+ pstring remainder = plib::trim(model.substr(pos + 1));
+ if (!plib::endsWith(remainder, ")"))
+ throw nl_exception(MF_1_MODEL_ERROR_1, model);
// FIMXE: Not optimal
- remainder = remainder.left(remainder.length() - 1);
+ remainder = plib::left(remainder, remainder.size() - 1);
std::vector<pstring> pairs(plib::psplit(remainder," ", true));
for (pstring &pe : pairs)
{
auto pose = pe.find("=");
if (pose == pstring::npos)
- log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
- map[pe.left(pose).ucase()] = pe.substr(pose + 1);
+ throw nl_exception(MF_1_MODEL_ERROR_ON_PAIR_1, model);
+ map[plib::ucase(plib::left(pe, pose))] = pe.substr(pose + 1);
}
}
-const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
+pstring models_t::model_string(model_map_t &map)
+{
+ pstring ret = map["COREMODEL"] + "(";
+ for (auto & i : map)
+ ret = ret + i.first + "=" + i.second + " ";
+
+ return ret + ")";
+}
+
+pstring models_t::model_value_str(pstring model, pstring entity)
{
+ model_map_t &map = m_cache[model];
+
+ if (map.size() == 0)
+ model_parse(model , map);
+
pstring ret;
- if (entity != entity.ucase())
- log().fatal(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
+ if (entity != plib::ucase(entity))
+ throw nl_exception(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
model_string(map));
if (map.find(entity) == map.end())
- log().fatal(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
+ throw nl_exception(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
else
ret = map[entity];
return ret;
}
-nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
+nl_double models_t::model_value(pstring model, pstring entity)
{
- pstring tmp = model_value_str(map, entity);
+ model_map_t &map = m_cache[model];
+
+ if (map.size() == 0)
+ model_parse(model , map);
- nl_double factor = NL_FCONST(1.0);
- auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.length() - 1));
+ pstring tmp = model_value_str(model, entity);
+
+ nl_double factor = plib::constants<nl_double>::one();
+ auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1));
switch (*p)
{
case 'M': factor = 1e6; break;
@@ -865,85 +919,69 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
case 'a': factor = 1e-18; break;
default:
if (*p < '0' || *p > '9')
- log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
+ throw nl_exception(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
}
- if (factor != NL_FCONST(1.0))
- tmp = tmp.left(tmp.length() - 1);
- return tmp.as_double() * factor;
+ if (factor != plib::constants<nl_double>::one())
+ tmp = plib::left(tmp, tmp.size() - 1);
+ // FIXME: check for errors
+ //printf("%s %s %e %e\n", entity.c_str(), tmp.c_str(), plib::pstonum<nl_double>(tmp), factor);
+ return plib::pstonum<nl_double>(tmp) * factor;
}
class logic_family_std_proxy_t : public logic_family_desc_t
{
public:
- logic_family_std_proxy_t() { }
- virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
+ logic_family_std_proxy_t() = default;
+ pool_owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist,
const pstring &name, logic_output_t *proxied) const override;
- virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
+ pool_owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
};
-plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
+pool_owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_state_t &anetlist,
const pstring &name, logic_output_t *proxied) const
{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
}
-plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
+pool_owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const
{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+ return pool().make_poolptr<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
}
const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
{
- detail::model_map_t map;
- model_parse(model, map);
- if (model_value_str(map, "TYPE") == "TTL")
+ if (m_models.model_value_str(model, "TYPE") == "TTL")
return family_TTL();
- if (model_value_str(map, "TYPE") == "CD4XXX")
+ if (m_models.model_value_str(model, "TYPE") == "CD4XXX")
return family_CD4XXX();
- for (auto & e : netlist().m_family_cache)
+ for (auto & e : m_nlstate.m_family_cache)
if (e.first == model)
return e.second.get();
- auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
+ auto ret = plib::make_unique<logic_family_std_proxy_t>();
- ret->m_fixed_V = model_value(map, "FV");
- ret->m_low_thresh_PCNT = model_value(map, "IVL");
- ret->m_high_thresh_PCNT = model_value(map, "IVH");
- ret->m_low_VO = model_value(map, "OVL");
- ret->m_high_VO = model_value(map, "OVH");
- ret->m_R_low = model_value(map, "ORL");
- ret->m_R_high = model_value(map, "ORH");
+ ret->m_fixed_V = m_models.model_value(model, "FV");
+ ret->m_low_thresh_PCNT = m_models.model_value(model, "IVL");
+ ret->m_high_thresh_PCNT = m_models.model_value(model, "IVH");
+ ret->m_low_VO = m_models.model_value(model, "OVL");
+ ret->m_high_VO = m_models. model_value(model, "OVH");
+ ret->m_R_low = m_models.model_value(model, "ORL");
+ ret->m_R_high = m_models.model_value(model, "ORH");
auto retp = ret.get();
- netlist().m_family_cache.emplace_back(model, std::move(ret));
+ m_nlstate.m_family_cache.emplace_back(model, std::move(ret));
return retp;
}
-void setup_t::tt_factory_create(tt_desc &desc, const pstring &sourcefile)
-{
- devices::tt_factory_create(*this, desc, sourcefile);
-}
-
-
// ----------------------------------------------------------------------------------------
// Sources
// ----------------------------------------------------------------------------------------
-void setup_t::include(const pstring &netlist_name)
-{
- for (auto &source : m_sources)
- {
- if (source->parse(netlist_name))
- return;
- }
- log().fatal(MF_1_NOT_FOUND_IN_SOURCE_COLLECTION, netlist_name);
-}
-
-std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
+plib::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
{
for (auto &source : m_sources)
{
@@ -955,77 +993,189 @@ std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring &name)
}
}
log().warning(MW_1_DATA_1_NOT_FOUND, name);
- return std::unique_ptr<plib::pistream>(nullptr);
+ return plib::unique_ptr<plib::pistream>(nullptr);
}
-bool setup_t::parse_stream(plib::putf8_reader &istrm, const pstring &name)
-{
- plib::pomemstream ostrm;
- plib::putf8_writer owrt(ostrm);
+// ----------------------------------------------------------------------------------------
+// Device handling
+// ----------------------------------------------------------------------------------------
- plib::ppreprocessor(&m_defines).process(istrm, owrt);
- plib::pimemstream istrm2(ostrm);
- plib::putf8_reader reader2(istrm2);
- return parser_t(reader2, *this).parse(name);
+void setup_t::delete_empty_nets()
+{
+ m_nlstate.nets().erase(
+ std::remove_if(m_nlstate.nets().begin(), m_nlstate.nets().end(),
+ [](pool_owned_ptr<detail::net_t> &x)
+ {
+ if (x->num_cons() == 0)
+ {
+ x->state().log().verbose("Deleting net {1} ...", x->name());
+ x->state().run_state_manager().remove_save_items(x.get());
+ return true;
+ }
+ else
+ return false;
+ }), m_nlstate.nets().end());
}
-void setup_t::register_define(pstring defstr)
+// ----------------------------------------------------------------------------------------
+// Run preparation
+// ----------------------------------------------------------------------------------------
+
+void setup_t::prepare_to_run()
{
- auto p = defstr.find("=");
- if (p != pstring::npos)
- register_define(defstr.left(p), defstr.substr(p+1));
+ register_dynamic_log_devices();
+
+ /* make sure the solver and parameters are started first! */
+
+ for (auto & e : m_device_factory)
+ {
+ if ( factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ || factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ m_nlstate.add_dev(e.first, pool_owned_ptr<device_t>(e.second->Create(m_nlstate, e.first)));
+ }
+ }
+
+ log().debug("Searching for solver and parameters ...\n");
+
+ auto solver = m_nlstate.get_single_device<devices::NETLIB_NAME(solver)>("solver");
+ m_netlist_params = m_nlstate.get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
+
+ /* create devices */
+
+ log().debug("Creating devices ...\n");
+ for (auto & e : m_device_factory)
+ {
+ if ( !factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ && !factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ auto dev = pool_owned_ptr<device_t>(e.second->Create(m_nlstate, e.first));
+ m_nlstate.add_dev(dev->name(), std::move(dev));
+ }
+ }
+
+ log().debug("Looking for unknown parameters ...\n");
+ for (auto &p : m_param_values)
+ {
+ auto f = m_params.find(p.first);
+ if (f == m_params.end())
+ {
+ if (plib::endsWith(p.first, pstring(".HINT_NO_DEACTIVATE")))
+ {
+ // FIXME: get device name, check for device
+ }
+ else
+ log().info("Unknown parameter: {}", p.first);
+ }
+ }
+
+ bool use_deactivate = m_netlist_params->m_use_deactivate() ? true : false;
+
+ for (auto &d : m_nlstate.devices())
+ {
+ if (use_deactivate)
+ {
+ auto p = m_param_values.find(d.second->name() + ".HINT_NO_DEACTIVATE");
+ if (p != m_param_values.end())
+ {
+ //FIXME: check for errors ...
+ auto v = plib::pstonum<double>(p->second);
+ if (std::abs(v - std::floor(v)) > 1e-6 )
+ log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
+ d.second->set_hint_deactivate(v == 0.0);
+ }
+ }
+ else
+ d.second->set_hint_deactivate(false);
+ }
+
+ /* resolve inputs */
+ resolve_inputs();
+
+ log().verbose("looking for two terms connected to rail nets ...");
+ for (auto & t : m_nlstate.get_device_list<analog::NETLIB_NAME(twoterm)>())
+ {
+ if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
+ {
+ log().warning(MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3,
+ t->name(), t->m_N.net().name(), t->m_P.net().name());
+ t->m_N.net().remove_terminal(t->m_N);
+ t->m_P.net().remove_terminal(t->m_P);
+ m_nlstate.remove_dev(t);
+ }
+ }
+
+ log().verbose("initialize solver ...\n");
+
+ if (solver == nullptr)
+ {
+ for (auto &p : m_nlstate.nets())
+ if (p->is_analog())
+ log().fatal(MF_0_NO_SOLVER);
+ }
else
- register_define(defstr, "1");
+ solver->post_start();
+
+ for (auto &n : m_nlstate.nets())
+ for (auto & term : n->core_terms())
+ {
+ //core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object());
+ core_device_t *dev = &term->device();
+ dev->set_default_delegate(*term);
+ }
+
}
// ----------------------------------------------------------------------------------------
// base sources
// ----------------------------------------------------------------------------------------
-bool source_t::parse(const pstring &name)
+bool source_t::parse(nlparse_t &setup, const pstring &name)
{
if (m_type != SOURCE)
return false;
else
{
- auto rstream = stream(name);
- plib::putf8_reader reader(*rstream);
- return m_setup.parse_stream(reader, name);
+ return setup.parse_stream(stream(name), name);
}
}
-std::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
+ plib::unused_var(name);
+ return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
}
-std::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_mem_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pimemstream>(m_str.c_str(), m_str.mem_t_size());
+ plib::unused_var(name);
+ return plib::make_unique<plib::pimemstream>(m_str.c_str(), std::strlen(m_str.c_str()));
}
-std::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_file_t::stream(const pstring &name)
{
- return plib::make_unique_base<plib::pistream, plib::pifilestream>(m_filename);
+ plib::unused_var(name);
+ return plib::make_unique<plib::pifilestream>(m_filename);
}
-bool source_proc_t::parse(const pstring &name)
+bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
{
if (name == m_setup_func_name)
{
- m_setup_func(setup());
+ m_setup_func(setup);
return true;
}
else
return false;
}
-std::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
+plib::unique_ptr<plib::pistream> source_proc_t::stream(const pstring &name)
{
- std::unique_ptr<plib::pistream> p(nullptr);
+ plib::unused_var(name);
+ plib::unique_ptr<plib::pistream> p(nullptr);
return p;
}
-}
+} // namespace netlist