netlist_time compute_next_timestep(double cur_ts) { nl_double new_solver_timestep = m_params.m_max_timestep; if (m_params.m_dynamic_ts) { for (int k = 0, iN = m_terms.size(); k < iN; k++) { analog_net_t n = m_nets[k]; terms_for_net_t t = m_terms[k].get(); nl_double DD_n = (n.Q_Analog() - t.last_V); nl_double hn = cur_ts; //printf("%f %f %f %f\n", DD_n, t->m_DD_n_m_1, hn, t->m_h_n_m_1); nl_double DD2 = (DD_n / hn - t.DD_n_m_1 / t.h_n_m_1) / (hn + t.h_n_m_1); nl_double new_net_timestep; t.h_n_m_1 = hn; t.DD_n_m_1 = DD_n; if (Math.Abs(DD2) > nl_config_global.NL_FCONST(1e-60)) // avoid div-by-zero { new_net_timestep = Math.Sqrt(m_params.m_dynamic_lte / Math.Abs(nl_config_global.NL_FCONST(0.5) * DD2)); } else { new_net_timestep = m_params.m_max_timestep; } if (new_net_timestep < new_solver_timestep) { new_solver_timestep = new_net_timestep; } t.last_V = n.Q_Analog(); } if (new_solver_timestep < m_params.m_min_timestep) { //log().warning("Dynamic timestep below min timestep. Consider decreasing MIN_TIMESTEP: {1} us", new_solver_timestep*1.0e6); new_solver_timestep = m_params.m_min_timestep; } } //if (new_solver_timestep > 10.0 * hn) // new_solver_timestep = 10.0 * hn; /* * FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere. */ return(netlist_time.Max(netlist_time.from_double(new_solver_timestep), netlist_time.quantum() * 2)); }
bool already_processed(analog_net_t n) { if (n.isRailNet()) { return(true); } foreach (var grp in groups) { if (grp.Contains(n)) //plib::container::contains(grp, n)) { return(true); } } return(false); }
bool already_processed(analog_net_t n) { // no need to process rail nets - these are known variables if (n.is_rail_net()) { return(true); } // if it's already processed - no need to continue foreach (var grp in groups) { if (plib.container.contains(grp, n)) { return(true); } } return(false); }
public void run(netlist_base_t netlist) { foreach (var net in netlist.nets()) { netlist.log().debug.op("processing {0}\n", net.name()); if (!net.isRailNet() && net.num_cons() > 0) { netlist.log().debug.op(" ==> not a rail net\n"); /* Must be an analog net */ analog_net_t n = (analog_net_t)net; if (!already_processed(n)) { groups.push_back(new analog_net_t_list_t()); process_net(n); } } } }
void process_net(analog_net_t n) { if (n.num_cons() == 0) { return; } /* add the net */ groups.back().push_back(n); foreach (var p in n.core_terms) { if (p.is_type(detail.terminal_type.TERMINAL)) { terminal_t pt = (terminal_t)p; analog_net_t other_net = pt.otherterm.net(); if (!already_processed(other_net)) { process_net(other_net); } } } }
bool check_if_processed_and_join(analog_net_t n) { // no need to process rail nets - these are known variables if (n.is_rail_net()) { return(true); } // First check if it is in a previous group. // In this case we need to merge this group into the current group if (groupspre.size() > 1) { for (size_t i = 0; i < groupspre.size() - 1; i++) { if (plib.container.contains(groupspre[i], n)) { // copy all nets foreach (var cn in groupspre[i]) { if (!plib.container.contains(groupspre.back(), cn)) { groupspre.back().push_back(cn); } } // clear groupspre[i].clear(); return(true); } } } // if it's already processed - no need to continue if (!groupspre.empty() && plib.container.contains(groupspre.back(), n)) { return(true); } return(false); }
void process_net(netlist_state_t nlstate, analog_net_t n) { // ignore empty nets. FIXME: print a warning message nlstate.log().verbose.op("Net {0}", n.name()); if (!nlstate.core_terms(n).empty()) { // add the net groupspre.back().push_back(n); // process all terminals connected to this net foreach (var term in nlstate.core_terms(n)) { nlstate.log().verbose.op("Term {0} {1}", term.name(), (int)term.type()); // only process analog terminals if (term.is_type(detail.terminal_type.TERMINAL)) { var pt = (terminal_t)term; //auto &pt = dynamic_cast<terminal_t &>(*term); // check the connected terminal var connected_terminals = nlstate.setup().get_connected_terminals(pt); foreach (var ct in connected_terminals) //for (auto ct = connected_terminals->begin(); *ct != nullptr; ct++) { if (ct == default) { continue; } analog_net_t connected_net = ct.net(); nlstate.log().verbose.op(" Connected net {0}", connected_net.name()); if (!check_if_processed_and_join(connected_net)) { process_net(nlstate, connected_net); } } } } } }
/* return number of floating point operations for solve */ //std::size_t ops() { return m_ops; } protected void setup_base(analog_net_t_list_t nets) { log().debug.op("New solver setup\n"); m_nets.clear(); m_terms.clear(); foreach (var net in nets) { m_nets.push_back(net); m_terms.push_back(new terms_for_net_t()); m_rails_temp.push_back(new terms_for_net_t()); } for (UInt32 k = 0; k < nets.size(); k++) { analog_net_t net = nets[k]; log().debug.op("setting up net\n"); net.set_solver(this); foreach (var p in net.core_terms) { log().debug.op("{0} {1} {2}\n", p.name(), net.name(), net.isRailNet()); switch (p.type()) { case detail.terminal_type.TERMINAL: if (p.device().is_timestep()) { if (!m_step_devices.Contains(p.device())) //(!plib::container::contains(m_step_devices, &p->device())) { m_step_devices.push_back(p.device()); } } if (p.device().is_dynamic()) { if (!m_dynamic_devices.Contains(p.device())) //if (!plib::container::contains(m_dynamic_devices, &p->device())) { m_dynamic_devices.push_back(p.device()); } } { terminal_t pterm = (terminal_t)p; add_term(k, pterm); } log().debug.op("Added terminal {0}\n", p.name()); break; case detail.terminal_type.INPUT: { proxied_analog_output_t net_proxy_output = null; foreach (var input in m_inps) { if (input.proxied_net == p.net()) { net_proxy_output = input; break; } } if (net_proxy_output == null) { string nname = this.name() + "." + new plib.pfmt("m{0}").op(m_inps.size()); var net_proxy_output_u = new proxied_analog_output_t(this, nname); net_proxy_output = net_proxy_output_u; m_inps.push_back(net_proxy_output_u); nl_base_global.nl_assert(p.net().is_analog()); net_proxy_output.proxied_net = (analog_net_t)p.net(); } net_proxy_output.net().add_terminal(p); // FIXME: repeated calling - kind of brute force net_proxy_output.net().rebuild_list(); log().debug.op("Added input\n"); } break; case detail.terminal_type.OUTPUT: log().fatal.op(nl_errstr_global.MF_1_UNHANDLED_ELEMENT_1_FOUND, p.name()); break; } } log().debug.op("added net with {0} populated connections\n", net.core_terms.size()); } /* now setup the matrix */ setup_matrix(); }
analog_net_t m_proxied_net; // only for proxy nets in analog input logic public proxied_analog_output_t(core_device_t dev, string aname) : base(dev, aname) { m_proxied_net = null; }