void queue_t::on_pre_save() { netlist().log().debug("on_pre_save\n"); m_qsize = this->count(); netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize); for (int i = 0; i < m_qsize; i++ ) { m_times[i] = this->listptr()[i].exec_time().as_raw(); pstring p = this->listptr()[i].object()->name(); int n = p.len(); n = std::min(63, n); std::strncpy(m_names[i].m_buf, p.cstr(), n); m_names[i].m_buf[n] = 0; } }
void detail::queue_t::on_pre_save() { netlist().log().debug("on_pre_save\n"); m_qsize = this->size(); netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize); for (std::size_t i = 0; i < m_qsize; i++ ) { m_times[i] = this->listptr()[i].m_exec_time.as_raw(); pstring p = this->listptr()[i].m_object->name(); std::size_t n = p.len(); if (n > 63) n = 63; std::strncpy(m_names[i].m_buf, p.cstr(), n); m_names[i].m_buf[n] = 0; } }
void mymain(int argc, _TCHAR *argv[]) { string infile; if(argc != 2) { cout << "Usage: placement input_file" << endl; cout << "Using default input file: input.ap" << endl; infile = "input.ap"; } else { infile = argv[1]; } output.open((infile+".out").c_str(), ios_base::out); NetList netlist(infile.c_str()); netlist.print(); AnalyticForm aform(netlist); aform.print(); UmfpackHelper umfpack(aform.m, aform.n, aform.A, aform.bx, aform.by); umfpack.print(); }
ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) { NL_VERBOSE_OUT(("merging nets ...\n")); if (othernet == NULL) return; // Nothing to do if (this->isRailNet() && othernet->isRailNet()) netlist().error("Trying to merge to rail nets\n"); if (othernet->isRailNet()) { NL_VERBOSE_OUT(("othernet is railnet\n")); othernet->merge_net(this); } else { netlist_core_terminal_t *p = othernet->m_head; while (p != NULL) { netlist_core_terminal_t *pn = p->m_update_list_next; register_con(*p); p = pn; } othernet->m_head = NULL; // FIXME: othernet needs to be free'd from memory } }
ATTR_COLD void netlist_device_t::register_sub(const pstring &name, netlist_device_t &dev) { dev.init(netlist(), this->name() + "." + name); // FIXME: subdevices always first inherit the logic family of the parent dev.set_logic_family(this->logic_family()); dev.start_dev(); }
ATTR_COLD double netlist_param_model_t::model_value(const pstring &entity, const double defval) const { pstring tmp = this->Value(); // .model 1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon) int p = tmp.ucase().find(entity.ucase() + "="); if (p>=0) { int pblank = tmp.find(" ", p); if (pblank < 0) pblank = tmp.len() + 1; tmp = tmp.substr(p, pblank - p); int pequal = tmp.find("=", 0); if (pequal < 0) netlist().error("parameter %s misformat in model %s temp %s\n", entity.cstr(), Value().cstr(), tmp.cstr()); tmp = tmp.substr(pequal+1); double factor = 1.0; switch (*(tmp.right(1).cstr())) { case 'm': factor = 1e-3; break; case 'u': factor = 1e-6; break; case 'n': factor = 1e-9; break; case 'p': factor = 1e-12; break; case 'f': factor = 1e-15; break; case 'a': factor = 1e-18; break; } if (factor != 1.0) tmp = tmp.left(tmp.len() - 1); return atof(tmp.cstr()) * factor; } else return defval; }
ATTR_HOT void netlist_net_t::dec_active(netlist_core_terminal_t &term) { m_active--; m_list_active.remove(term); if (m_active == 0 && netlist().use_deactivate()) railterminal().netdev().dec_active(); }
void matrix_solver_t::solve_base(C *p) { m_stat_vsolver_calls++; if (is_dynamic()) { int this_resched; int newton_loops = 0; do { update_dynamic(); // Gauss-Seidel will revert to Gaussian elemination if steps exceeded. this_resched = p->vsolve_non_dynamic(true); newton_loops++; } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); m_stat_newton_raphson += newton_loops; // reschedule .... if (this_resched > 1 && !m_Q_sync.net().is_queued()) { netlist().warning("NEWTON_LOOPS exceeded on net %s... reschedule", this->name().cstr()); m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay); } } else { p->vsolve_non_dynamic(false); } }
void queue_t::register_state(pstate_manager_t &manager, const pstring &module) { netlist().log().debug("register_state\n"); manager.save_item(m_qsize, this, module + "." + "qsize"); manager.save_item(&m_times[0], this, module + "." + "times", m_times.size()); manager.save_item(&(m_names[0].m_buf[0]), this, module + "." + "names", m_names.size() * sizeof(names_t)); }
logic_input_t::logic_input_t(core_device_t &dev, const pstring &aname) : logic_t(dev, aname, INPUT) { set_state(STATE_INP_ACTIVE); set_logic_family(dev.logic_family()); netlist().setup().register_term(*this); }
ATTR_COLD void netlist_core_device_t::start_dev() { #if (NL_KEEP_STATISTICS) netlist().m_started_devices.add(this, false); #endif start(); }
ATTR_HOT void net_t::dec_active(core_terminal_t &term) { m_active--; nl_assert(m_active >= 0); m_list_active.remove(term); if (m_active == 0 && netlist().use_deactivate()) railterminal().device().dec_active(); }
terminal_t::terminal_t(core_device_t &dev, const pstring &aname) : analog_t(dev, aname, TERMINAL) , m_otherterm(nullptr) , m_Idr1(*this, "m_Idr1", nullptr) , m_go1(*this, "m_go1", nullptr) , m_gt1(*this, "m_gt1", nullptr) { netlist().setup().register_term(*this); }
param_template_t<C, T>::param_template_t(device_t &device, const pstring name, const C val) : param_t(T, device, device.name() + "." + name) , m_param(val) { /* pstrings not yet supported, these need special logic */ if (T != param_t::STRING && T != param_t::MODEL) netlist().save(*this, m_param, "m_param"); device.setup().register_and_set_param(device.name() + "." + name, *this); }
logic_output_t::logic_output_t(core_device_t &dev, const pstring &aname) : logic_t(dev, aname, OUTPUT) , m_my_net(dev.netlist(), name() + ".net", this) { set_state(STATE_OUT); this->set_net(&m_my_net); set_logic_family(dev.logic_family()); netlist().setup().register_term(*this); }
analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname) : analog_t(dev, aname, OUTPUT) , m_my_net(dev.netlist(), name() + ".net", this) { this->set_net(&m_my_net); set_state(STATE_OUT); net().m_cur_Analog = NL_FCONST(0.0); netlist().setup().register_term(*this); }
nld_d_to_a_proxy::nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied) : nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P) , m_GNDHack(*this, "_Q") , m_RV(*this, "RV") , m_last_state(*this, "m_last_var", -1) , m_is_timestep(false) { const pstring power_syms[3][2] ={ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}; //register_sub(m_RV); //register_term("1", m_RV.m_P); //register_term("2", m_RV.m_N); register_subalias("Q", m_RV.m_P); connect(m_RV.m_N, m_GNDHack); bool f = false; for (int i = 0; i < 3; i++) { pstring devname = out_proxied->device().name(); auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0], detail::terminal_type::INPUT, false); auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1], detail::terminal_type::INPUT, false); if (tp != nullptr && tn != nullptr) { /* alternative logic */ f = true; } } if (!f) log().warning(MW_1_NO_POWER_TERMINALS_ON_DEVICE_1, out_proxied->device().name()); else log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name()); #if (0) printf("%s %s\n", out_proxied->name().c_str(), out_proxied->device().name().c_str()); auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::terminal_type::OUTPUT, false); if (x) printf("==> %s\n", x->name().c_str()); #endif }
void netlist_queue_t::on_pre_save() { NL_VERBOSE_OUT(("on_pre_save\n")); m_qsize = this->count(); NL_VERBOSE_OUT(("current time %f qsize %d\n", netlist().time().as_double(), m_qsize)); for (int i = 0; i < m_qsize; i++ ) { m_times[i] = this->listptr()[i].exec_time().as_raw(); const char *p = this->listptr()[i].object()->name().cstr(); int n = MIN(63, strlen(p)); strncpy(&(m_name[i][0]), p, n); m_name[i][n] = 0; } }
void detail::net_t::inc_active(core_terminal_t &term) { m_active++; m_list_active.push_front(&term); nl_assert(m_active <= static_cast<int>(num_cons())); if (m_active == 1) { railterminal().device().do_inc_active(); if (m_in_queue == 0) { if (m_time > netlist().time()) { m_in_queue = 1; /* pending */ netlist().push_to_queue(*this, m_time); } else { m_cur_Q = m_new_Q; m_in_queue = 2; } } } }
const netlist_time matrix_solver_t::solve() { const netlist_time now = netlist().time(); const netlist_time delta = now - m_last_step; // We are already up to date. Avoid oscillations. // FIXME: Make this a parameter! if (delta < netlist_time::quantum()) return netlist_time::zero(); /* update all terminals for new time step */ m_last_step = now; step(delta); solve_base(); const netlist_time next_time_step = compute_next_timestep(delta.as_double()); update_inputs(); return next_time_step; }
netlist_time matrix_solver_t::solve() { const netlist_time now = netlist().time(); const netlist_time delta = now - m_last_step; // We are already up to date. Avoid oscillations. // FIXME: Make this a parameter! if (delta < netlist_time::from_nsec(1)) // 20000 return netlist_time::from_nsec(0); /* update all terminals for new time step */ m_last_step = now; m_cur_ts = delta.as_double(); step(delta); const netlist_time next_time_step = solve_base(); update_inputs(); return next_time_step; }
matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const bool use_specific) { if (use_specific && m_N == 1) return palloc(matrix_solver_direct1_t(&m_params)); else if (use_specific && m_N == 2) return palloc(matrix_solver_direct2_t(&m_params)); else { if (size >= m_gs_threshold) { if (pstring("SOR_MAT").equals(m_iterative_solver)) { typedef matrix_solver_SOR_mat_t<m_N,_storage_N> solver_mat; return palloc(solver_mat(&m_params, size)); } else if (pstring("SOR").equals(m_iterative_solver)) { typedef matrix_solver_SOR_t<m_N,_storage_N> solver_GS; return palloc(solver_GS(&m_params, size)); } else if (pstring("GMRES").equals(m_iterative_solver)) { typedef matrix_solver_GMRES_t<m_N,_storage_N> solver_GMRES; return palloc(solver_GMRES(&m_params, size)); } else { netlist().log().fatal("Unknown solver type: {1}\n", m_iterative_solver.Value()); return NULL; } } else { typedef matrix_solver_direct_t<m_N,_storage_N> solver_D; return palloc(solver_D(&m_params, size)); } } }
void NETLIB_NAME(solver)::post_start() { std::vector<analog_net_t::list_t> groups; const bool use_specific = true; m_params.m_pivot = m_pivot(); m_params.m_accuracy = m_accuracy(); /* FIXME: Throw when negative */ m_params.m_gs_loops = static_cast<unsigned>(m_gs_loops()); m_params.m_nr_loops = static_cast<unsigned>(m_nr_loops()); m_params.m_nt_sync_delay = netlist_time::from_double(m_sync_delay()); m_params.m_lte = m_lte(); m_params.m_sor = m_sor(); m_params.m_min_timestep = m_min_timestep(); m_params.m_dynamic = (m_dynamic() == 1 ? true : false); m_params.m_max_timestep = netlist_time::from_double(1.0 / m_freq()).as_double(); if (m_params.m_dynamic) { m_params.m_max_timestep *= 1;//NL_FCONST(1000.0); } else { m_params.m_min_timestep = m_params.m_max_timestep; } //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::) // Override log statistics pstring p = plib::util::environment("NL_STATS"); if (p != "") m_params.m_log_stats = p.as_long(); else m_params.m_log_stats = m_log_stats(); netlist().log().verbose("Scanning net groups ..."); // determine net groups for (auto & net : netlist().m_nets) { netlist().log().debug("processing {1}\n", net->name()); if (!net->isRailNet()) { netlist().log().debug(" ==> not a rail net\n"); /* Must be an analog net */ analog_net_t *n = static_cast<analog_net_t *>(net.get()); if (!n->already_processed(groups)) { groups.push_back(analog_net_t::list_t()); n->process_net(groups); } } } // setup the solvers netlist().log().verbose("Found {1} net groups in {2} nets\n", groups.size(), netlist().m_nets.size()); for (auto & grp : groups) { std::unique_ptr<matrix_solver_t> ms; unsigned net_count = static_cast<unsigned>(grp.size()); switch (net_count) { case 1: ms = create_solver<1,1>(1, use_specific); break; case 2: ms = create_solver<2,2>(2, use_specific); break; case 3: ms = create_solver<3,3>(3, use_specific); break; case 4: ms = create_solver<4,4>(4, use_specific); break; case 5: ms = create_solver<5,5>(5, use_specific); break; case 6: ms = create_solver<6,6>(6, use_specific); break; case 7: ms = create_solver<7,7>(7, use_specific); break; case 8: ms = create_solver<8,8>(8, use_specific); break; case 10: ms = create_solver<10,10>(10, use_specific); break; case 11: ms = create_solver<11,11>(11, use_specific); break; case 12: ms = create_solver<12,12>(12, use_specific); break; case 15: ms = create_solver<15,15>(15, use_specific); break; case 31: ms = create_solver<31,31>(31, use_specific); break; case 49: ms = create_solver<49,49>(49, use_specific); break; #if 0 case 87: ms = create_solver<87,87>(87, use_specific); break; #endif default: netlist().log().warning("No specific solver found for netlist of size {1}", net_count); if (net_count <= 16) { ms = create_solver<0,16>(net_count, use_specific); } else if (net_count <= 32) { ms = create_solver<0,32>(net_count, use_specific); } else if (net_count <= 64) { ms = create_solver<0,64>(net_count, use_specific); } else if (net_count <= 128) { ms = create_solver<0,128>(net_count, use_specific); } else { netlist().log().fatal("Encountered netgroup with > 128 nets"); ms = nullptr; /* tease compilers */ } break; } // FIXME ... ms->set_delegate_pointer(); ms->setup(grp); netlist().log().verbose("Solver {1}", ms->name()); netlist().log().verbose(" ==> {2} nets", grp.size()); netlist().log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic"); netlist().log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep"); for (auto &n : grp) { netlist().log().verbose("Net {1}", n->name()); for (const auto &pcore : n->m_core_terms) { netlist().log().verbose(" {1}", pcore->name()); } } m_mat_solvers.push_back(std::move(ms)); } }
std::unique_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(unsigned size, const bool use_specific) { pstring solvername = plib::pfmt("Solver_{1}")(m_mat_solvers.size()); if (use_specific && m_N == 1) return plib::make_unique<matrix_solver_direct1_t>(netlist(), solvername, &m_params); else if (use_specific && m_N == 2) return plib::make_unique<matrix_solver_direct2_t>(netlist(), solvername, &m_params); else { if (static_cast<int>(size) >= m_gs_threshold()) { if (pstring("SOR_MAT").equals(m_iterative_solver())) { typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat; return plib::make_unique<solver_sor_mat>(netlist(), solvername, &m_params, size); } else if (pstring("MAT_CR").equals(m_iterative_solver())) { typedef matrix_solver_GCR_t<m_N,storage_N> solver_mat; return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } else if (pstring("MAT").equals(m_iterative_solver())) { typedef matrix_solver_direct_t<m_N,storage_N> solver_mat; return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } else if (pstring("SM").equals(m_iterative_solver())) { /* Sherman-Morrison Formula */ typedef matrix_solver_sm_t<m_N,storage_N> solver_mat; return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } else if (pstring("W").equals(m_iterative_solver())) { /* Woodbury Formula */ typedef matrix_solver_w_t<m_N,storage_N> solver_mat; return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size); } else if (pstring("SOR").equals(m_iterative_solver())) { typedef matrix_solver_SOR_t<m_N,storage_N> solver_GS; return plib::make_unique<solver_GS>(netlist(), solvername, &m_params, size); } else if (pstring("GMRES").equals(m_iterative_solver())) { typedef matrix_solver_GMRES_t<m_N,storage_N> solver_GMRES; return plib::make_unique<solver_GMRES>(netlist(), solvername, &m_params, size); } else { netlist().log().fatal("Unknown solver type: {1}\n", m_iterative_solver()); return nullptr; } } else { typedef matrix_solver_direct_t<m_N,storage_N> solver_D; return plib::make_unique<solver_D>(netlist(), solvername, &m_params, size); } } }
ATTR_COLD void NETLIB_NAME(solver)::post_start() { analog_net_t::list_t groups[256]; int cur_group = -1; const bool use_specific = true; m_params.m_accuracy = m_accuracy.Value(); m_params.m_gs_loops = m_gs_loops.Value(); m_params.m_nr_loops = m_nr_loops.Value(); m_params.m_nt_sync_delay = m_sync_delay.Value(); m_params.m_lte = m_lte.Value(); m_params.m_sor = m_sor.Value(); m_params.m_min_timestep = m_min_timestep.Value(); m_params.m_dynamic = (m_dynamic.Value() == 1 ? true : false); m_params.m_max_timestep = netlist_time::from_hz(m_freq.Value()).as_double(); if (m_params.m_dynamic) { m_params.m_max_timestep *= NL_FCONST(1000.0); } else { m_params.m_min_timestep = m_params.m_max_timestep; } // Override log statistics pstring p = nl_util::environment("NL_STATS"); if (p != "") m_params.m_log_stats = (bool) p.as_long(); else m_params.m_log_stats = (bool) m_log_stats.Value(); netlist().log("Scanning net groups ..."); // determine net groups for (std::size_t i=0; i<netlist().m_nets.size(); i++) { SOLVER_VERBOSE_OUT(("processing %s\n", netlist().m_nets[i]->name().cstr())); if (!netlist().m_nets[i]->isRailNet()) { SOLVER_VERBOSE_OUT((" ==> not a rail net\n")); analog_net_t *n = &netlist().m_nets[i]->as_analog(); if (!n->already_processed(groups, cur_group)) { cur_group++; n->process_net(groups, cur_group); } } } // setup the solvers netlist().log("Found %d net groups in %" SIZETFMT " nets\n", cur_group + 1, SIZET_PRINTF(netlist().m_nets.size())); for (int i = 0; i <= cur_group; i++) { matrix_solver_t *ms; std::size_t net_count = groups[i].size(); switch (net_count) { case 1: ms = create_solver<1,1>(1, use_specific); break; case 2: ms = create_solver<2,2>(2, use_specific); break; case 3: ms = create_solver<3,3>(3, use_specific); break; case 4: ms = create_solver<4,4>(4, use_specific); break; case 5: ms = create_solver<5,5>(5, use_specific); break; case 6: ms = create_solver<6,6>(6, use_specific); break; case 7: ms = create_solver<7,7>(7, use_specific); break; case 8: ms = create_solver<8,8>(8, use_specific); break; case 12: ms = create_solver<12,12>(12, use_specific); break; case 87: ms = create_solver<87,87>(87, use_specific); break; default: if (net_count <= 16) { ms = create_solver<0,16>(net_count, use_specific); } else if (net_count <= 32) { ms = create_solver<0,32>(net_count, use_specific); } else if (net_count <= 64) { ms = create_solver<0,64>(net_count, use_specific); } else if (net_count <= 128) { ms = create_solver<0,128>(net_count, use_specific); } else { netlist().error("Encountered netgroup with > 128 nets"); ms = NULL; /* tease compilers */ } break; } register_sub(pstring::sprintf("Solver_%" SIZETFMT,SIZET_PRINTF(m_mat_solvers.size())), *ms); ms->vsetup(groups[i]); m_mat_solvers.add(ms); netlist().log("Solver %s", ms->name().cstr()); netlist().log(" # %d ==> %" SIZETFMT " nets", i, SIZET_PRINTF(groups[i].size())); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr()); netlist().log(" has %s elements", ms->is_dynamic() ? "dynamic" : "no dynamic"); netlist().log(" has %s elements", ms->is_timestep() ? "timestep" : "no timestep"); for (std::size_t j=0; j<groups[i].size(); j++) { netlist().log("Net %" SIZETFMT ": %s", SIZET_PRINTF(j), groups[i][j]->name().cstr()); net_t *n = groups[i][j]; for (std::size_t k = 0; k < n->m_core_terms.size(); k++) { const core_terminal_t *p = n->m_core_terms[k]; netlist().log(" %s", p->name().cstr()); } } } }
matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const bool use_specific) { pstring solvername = pfmt("Solver_{1}")(m_mat_solvers.size()); if (use_specific && m_N == 1) return palloc(matrix_solver_direct1_t(netlist(), solvername, &m_params)); else if (use_specific && m_N == 2) return palloc(matrix_solver_direct2_t(netlist(), solvername, &m_params)); else { if (size >= m_gs_threshold) { if (pstring("SOR_MAT").equals(m_iterative_solver)) { typedef matrix_solver_SOR_mat_t<m_N,_storage_N> solver_sor_mat; return palloc(solver_sor_mat(netlist(), solvername, &m_params, size)); } else if (pstring("MAT_CR").equals(m_iterative_solver)) { typedef matrix_solver_GCR_t<m_N,_storage_N> solver_mat; return palloc(solver_mat(netlist(), solvername, &m_params, size)); } else if (pstring("MAT").equals(m_iterative_solver)) { typedef matrix_solver_direct_t<m_N,_storage_N> solver_mat; return palloc(solver_mat(netlist(), solvername, &m_params, size)); } else if (pstring("SM").equals(m_iterative_solver)) { /* Sherman-Morrison Formula */ typedef matrix_solver_sm_t<m_N,_storage_N> solver_mat; return palloc(solver_mat(netlist(), solvername, &m_params, size)); } else if (pstring("W").equals(m_iterative_solver)) { /* Woodbury Formula */ typedef matrix_solver_w_t<m_N,_storage_N> solver_mat; return palloc(solver_mat(netlist(), solvername, &m_params, size)); } else if (pstring("SOR").equals(m_iterative_solver)) { typedef matrix_solver_SOR_t<m_N,_storage_N> solver_GS; return palloc(solver_GS(netlist(), solvername, &m_params, size)); } else if (pstring("GMRES").equals(m_iterative_solver)) { typedef matrix_solver_GMRES_t<m_N,_storage_N> solver_GMRES; return palloc(solver_GMRES(netlist(), solvername, &m_params, size)); } else { netlist().log().fatal("Unknown solver type: {1}\n", m_iterative_solver.Value()); return nullptr; } } else { typedef matrix_solver_direct_t<m_N,_storage_N> solver_D; return palloc(solver_D(netlist(), solvername, &m_params, size)); } } }
ATTR_COLD netlist_net_t::~netlist_net_t() { if (isInitialized()) netlist().remove_save_items(this); }
ATTR_COLD void NETLIB_NAME(solver)::post_start() { pvector_t<analog_net_t::list_t> groups; const bool use_specific = true; m_params.m_pivot = m_pivot.Value(); m_params.m_accuracy = m_accuracy.Value(); m_params.m_gs_loops = m_gs_loops.Value(); m_params.m_nr_loops = m_nr_loops.Value(); m_params.m_nt_sync_delay = netlist_time::from_double(m_sync_delay.Value()); m_params.m_lte = m_lte.Value(); m_params.m_sor = m_sor.Value(); m_params.m_min_timestep = m_min_timestep.Value(); m_params.m_dynamic = (m_dynamic.Value() == 1 ? true : false); m_params.m_max_timestep = netlist_time::from_hz(m_freq.Value()).as_double(); if (m_params.m_dynamic) { m_params.m_max_timestep *= NL_FCONST(1000.0); } else { m_params.m_min_timestep = m_params.m_max_timestep; } // Override log statistics pstring p = nl_util::environment("NL_STATS"); if (p != "") m_params.m_log_stats = (bool) p.as_long(); else m_params.m_log_stats = (bool) m_log_stats.Value(); netlist().log().verbose("Scanning net groups ..."); // determine net groups for (auto & net : netlist().m_nets) { netlist().log().debug("processing {1}\n", net->name()); if (!net->isRailNet()) { netlist().log().debug(" ==> not a rail net\n"); analog_net_t *n = &net->as_analog(); if (!n->already_processed(groups)) { groups.push_back(analog_net_t::list_t()); n->process_net(groups); } } } // setup the solvers netlist().log().verbose("Found {1} net groups in {2} nets\n", groups.size(), netlist().m_nets.size()); for (auto & grp : groups) { matrix_solver_t *ms; std::size_t net_count = grp.size(); switch (net_count) { case 1: ms = create_solver<1,1>(1, use_specific); break; case 2: ms = create_solver<2,2>(2, use_specific); break; case 3: ms = create_solver<3,3>(3, use_specific); break; case 4: ms = create_solver<4,4>(4, use_specific); break; case 5: ms = create_solver<5,5>(5, use_specific); break; case 6: ms = create_solver<6,6>(6, use_specific); break; case 7: ms = create_solver<7,7>(7, use_specific); break; case 8: ms = create_solver<8,8>(8, use_specific); break; case 10: ms = create_solver<10,10>(10, use_specific); break; case 11: ms = create_solver<11,11>(11, use_specific); break; case 12: ms = create_solver<12,12>(12, use_specific); break; case 15: ms = create_solver<15,15>(15, use_specific); break; case 31: ms = create_solver<31,31>(31, use_specific); break; case 49: ms = create_solver<49,49>(49, use_specific); break; #if 0 case 87: ms = create_solver<87,87>(87, use_specific); break; #endif default: netlist().log().warning("No specific solver found for netlist of size {1}", (unsigned) net_count); if (net_count <= 16) { ms = create_solver<0,16>(net_count, use_specific); } else if (net_count <= 32) { ms = create_solver<0,32>(net_count, use_specific); } else if (net_count <= 64) { ms = create_solver<0,64>(net_count, use_specific); } else if (net_count <= 128) { ms = create_solver<0,128>(net_count, use_specific); } else { netlist().log().fatal("Encountered netgroup with > 128 nets"); ms = nullptr; /* tease compilers */ } break; } register_sub(*ms); ms->setup(grp); m_mat_solvers.push_back(ms); netlist().log().verbose("Solver {1}", ms->name()); netlist().log().verbose(" ==> {2} nets", grp.size()); netlist().log().verbose(" has {1} elements", ms->is_dynamic() ? "dynamic" : "no dynamic"); netlist().log().verbose(" has {1} elements", ms->is_timestep() ? "timestep" : "no timestep"); for (net_t *n : grp) { netlist().log().verbose("Net {1}", n->name()); for (const core_terminal_t *pcore : n->m_core_terms) { netlist().log().verbose(" {1}", pcore->name()); } } } }
ATTR_COLD netlist_setup_t &netlist_device_t::setup() { return netlist().setup(); }
ATTR_COLD const pstring &netlist_object_t::name() const { if (m_name == "") netlist().error("object not initialized"); return m_name; }