diff options
author | 2019-03-26 11:13:37 +1100 | |
---|---|---|
committer | 2019-03-26 11:13:37 +1100 | |
commit | 97b67170277437131adf6ed4d60139c172529e4f (patch) | |
tree | 7a5cbf608f191075f1612b1af15832c206a3fe2d /src/lib/netlist/nl_setup.cpp | |
parent | b380514764cf857469bae61c11143a19f79a74c5 (diff) |
(nw) Clean up the mess on master
This effectively reverts b380514764cf857469bae61c11143a19f79a74c5 and
c24473ddff715ecec2e258a6eb38960cf8c8e98e, restoring the state at
598cd5227223c3b04ca31f0dbc1981256d9ea3ff.
Before pushing, please check that what you're about to push is sane.
Check your local commit log and ensure there isn't anything out-of-place
before pushing to mainline. When things like this happen, it wastes
everyone's time. I really don't need this in a week when real work⢠is
busting my balls and I'm behind where I want to be with preparing for
MAME release.
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 |