diff options
author | 2019-03-25 22:44:58 +0100 | |
---|---|---|
committer | 2019-03-25 22:44:58 +0100 | |
commit | c24473ddff715ecec2e258a6eb38960cf8c8e98e (patch) | |
tree | 8ea44b6396a6129913c0aac13859b5de9965e972 /src/lib/netlist/nl_setup.cpp | |
parent | 009cba4fb8102102168ef32870892438327f3705 (diff) | |
parent | 598cd5227223c3b04ca31f0dbc1981256d9ea3ff (diff) |
conflict resolution (nw)
Diffstat (limited to 'src/lib/netlist/nl_setup.cpp')
-rw-r--r-- | src/lib/netlist/nl_setup.cpp | 838 |
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 ¶m, 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 ¶m, 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 ¶m) -{ - 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 ¶m, const double value) +void setup_t::register_param_t(const pstring &name, param_t ¶m) { - 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 ¶m, 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 |