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 } }
void netlist_parser::netdev_device(const pstring &dev_type, const pstring &default_param, bool isString) { netlist_device_t *dev; skipws(); pstring devname = getname2(',', ')'); pstring defparam = devname + "." + default_param; dev = m_setup.factory().new_device_by_name(dev_type, m_setup); m_setup.register_dev(dev, devname); NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr())); if (getc() != ')') { // have a default param skipws(); if (isString) { pstring val = getname(')'); ungetc(); NL_VERBOSE_OUT(("Parser: Default param: %s %s\n", defparam.cstr(), val.cstr())); m_setup.register_param(defparam, val); } else { double val = eval_param(); NL_VERBOSE_OUT(("Parser: Default param: %s %f\n", defparam.cstr(), val)); m_setup.register_param(defparam, val); } } check_char(')'); }
ATTR_COLD void netlist_base_t::start() { /* find the main clock and solver ... */ NL_VERBOSE_OUT(("Searching for mainclock and solver ...\n")); m_mainclock = get_single_device<NETLIB_NAME(mainclock)>("mainclock"); m_solver = get_single_device<NETLIB_NAME(solver)>("solver"); m_gnd = get_single_device<NETLIB_NAME(gnd)>("gnd"); m_params = get_single_device<NETLIB_NAME(netlistparams)>("parameter"); /* make sure the solver and parameters are started first! */ if (m_solver != NULL) m_solver->start_dev(); if (m_params != NULL) { m_params->start_dev(); } m_use_deactivate = (m_params->m_use_deactivate.Value() ? true : false); NL_VERBOSE_OUT(("Initializing devices ...\n")); for (netlist_device_t * const * entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) { netlist_device_t *dev = *entry; if (dev != m_solver && dev != m_params) dev->start_dev(); } }
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 (othernet == this) { netlist().warning("Connecting %s to itself. This may be right, though\n", this->name().cstr()); return; // Nothing to do } if (this->isRailNet() && othernet->isRailNet()) netlist().error("Trying to merge two rail nets: %s and %s\n", this->name().cstr(), othernet->name().cstr()); if (othernet->isRailNet()) { NL_VERBOSE_OUT(("othernet is railnet\n")); othernet->merge_net(this); } else { othernet->move_connections(this); } }
void netlist_parser::netdev_device(const pstring &dev_type) { pstring devname; netlist_device_t *dev; int cnt; skipws(); devname = getname2(',', ')'); dev = m_setup.factory().new_device_by_name(dev_type, m_setup); m_setup.register_dev(dev, devname); NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr())); cnt = 0; while (getc() != ')') { skipws(); pstring output_name = getname2(',', ')'); pstring alias = pstring::sprintf("%s.[%d]", devname.cstr(), cnt); NL_VERBOSE_OUT(("Parser: ID: %s %s\n", output_name.cstr(), alias.cstr())); m_setup.register_link(alias, output_name); skipws(); cnt++; } /* if (cnt != dev->m_terminals.count() && !dev->variable_input_count()) fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), dev->m_terminals.count(), cnt); if (dev->variable_input_count()) { NL_VERBOSE_OUT(("variable inputs %s: %d\n", dev->name().cstr(), cnt)); } */ }
void netlist_queue_t::on_post_load() { this->clear(); NL_VERBOSE_OUT(("current time %f qsize %d\n", m_netlist->time().as_double(), qsize)); for (int i = 0; i < m_qsize; i++ ) { netlist_net_t *n = m_netlist.find_net(&(m_name[i][0])); NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n)); NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double())); this->push(netlist_queue_t::entry_t(netlist_time::from_raw(m_times[i]), n)); } }
void netlist_parser::device(const pstring &dev_type) { pstring devname; net_device_t_base_factory *f = m_setup.factory().factory_by_name(dev_type, m_setup); netlist_device_t *dev; nl_util::pstring_list termlist = f->term_param_list(); nl_util::pstring_list def_params = f->def_params(); std::size_t cnt; devname = get_identifier(); dev = f->Create(); m_setup.register_dev(dev, devname); NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr())); cnt = 0; while (cnt < def_params.size()) { pstring paramfq = devname + "." + def_params[cnt]; NL_VERBOSE_OUT(("Defparam: %s\n", paramfq.cstr())); require_token(m_tok_comma); token_t tok = get_token(); if (tok.is_type(STRING)) { m_setup.register_param(paramfq, tok.str()); } else { nl_double val = eval_param(tok); m_setup.register_param(paramfq, val); } cnt++; } token_t tok = get_token(); cnt = 0; while (tok.is(m_tok_comma) && cnt < termlist.size()) { pstring output_name = get_identifier(); m_setup.register_link(devname + "." + termlist[cnt], output_name); cnt++; tok = get_token(); } if (cnt != termlist.size()) m_setup.netlist().error("netlist: input count mismatch for %s - expected %" SIZETFMT " found %" SIZETFMT "\n", devname.cstr(), termlist.size(), cnt); require_token(tok, m_tok_param_right); }
void netlist_parser::netdev_device(const pstring &dev_type) { pstring devname; net_device_t_base_factory *f = m_setup.factory().factory_by_name(dev_type, m_setup); netlist_device_t *dev; nl_util::pstring_list termlist = f->term_param_list(); pstring def_param = f->def_param(); int cnt; skipws(); devname = getname2(',', ')'); dev = f->Create(); m_setup.register_dev(dev, devname); NL_VERBOSE_OUT(("Parser: IC: %s\n", devname.cstr())); if (def_param != "") { pstring paramfq = devname + "." + def_param; NL_VERBOSE_OUT(("Defparam: %s\n", def_param.cstr())); check_char(','); skipws(); if (peekc() == '"') { pstring val = getstring(); m_setup.register_param(paramfq, val); } else { double val = eval_param(); m_setup.register_param(paramfq, val); } if (termlist.count() > 0) check_char(','); } cnt = 0; while (getc() != ')' && cnt < termlist.count()) { skipws(); pstring output_name = getname2(',', ')'); m_setup.register_link(devname + "." + termlist[cnt], output_name); skipws(); cnt++; } if (cnt != termlist.count()) fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), termlist.count(), cnt); }
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 netlist_queue_t::register_state(pstate_manager_t &manager, const pstring &module) { NL_VERBOSE_OUT(("register_state\n")); manager.save_item(m_qsize, this, module + "." + "qsize"); manager.save_item(m_times, this, module + "." + "times"); manager.save_item(&(m_name[0][0]), this, module + "." + "names", sizeof(m_name)); }
void netlist_parser::parse(const char *buf) { m_px = buf; while (!eof()) { pstring n; skipws(); if (eof()) break; n = getname('('); NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr())); if (n == "NET_ALIAS") net_alias(); else if (n == "NET_C") net_c(); else if (n == "NETDEV_PARAM") netdev_param(); else if (n == "NETDEV_R") netdev_device(n, "R"); else if (n == "NETDEV_C") netdev_device(n, "C"); else if (n == "NETDEV_POT") netdev_device(n, "R"); else if (n == "NETDEV_D") netdev_device(n, "model", true); else if ((n == "NETDEV_TTL_CONST") || (n == "NETDEV_ANALOG_CONST")) netdev_const(n); else netdev_device(n); } }
void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname) { while (true) { token_t token = get_token(); if (token.is_type(ENDOFFILE)) return; require_token(m_tok_param_left); NL_VERBOSE_OUT(("Parser: Device: %s\n", token.str().cstr())); if (token.is(m_tok_ALIAS)) net_alias(); else if (token.is(m_tok_NET_C)) net_c(); else if (token.is(m_tok_PARAM)) netdev_param(); else if (token.is(m_tok_NET_MODEL)) net_model(); else if (token.is(m_tok_SUBMODEL)) net_submodel(); else if (token.is(m_tok_INCLUDE)) net_include(); else if (token.is(m_tok_NETLIST_END)) { netdev_netlist_end(); return; } else device(token.str()); } }
void netlist_parser::parse(const char *buf) { m_px = buf; m_line_ptr = buf; m_line = 1; while (!eof()) { pstring n; skipws(); if (eof()) break; n = getname('('); NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr())); if (n == "NET_ALIAS") net_alias(); else if (n == "NET_C") net_c(); else if (n == "NETDEV_PARAM") netdev_param(); else if ((n == "NET_MODEL")) net_model(); else if (n == "NETLIST_START") netdev_netlist_start(); else if (n == "NETLIST_END") netdev_netlist_end(); else netdev_device(n); } }
void parser_t::netdev_param() { pstring param; param = get_identifier(); require_token(m_tok_comma); token_t tok = get_token(); if (tok.is_type(STRING)) { NL_VERBOSE_OUT(("Parser: Param: %s %s\n", param.cstr(), tok.str().cstr())); m_setup.register_param(param, tok.str()); } else { nl_double val = eval_param(tok); NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val)); m_setup.register_param(param, val); } require_token(m_tok_param_right); }
void netlist_parser::net_c() { pstring t1; pstring t2; skipws(); t1 = getname(','); skipws(); t2 = getname(')'); NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", t1.cstr(), t2.cstr())); m_setup.register_link(t1 , t2); }
void log_setup() { NL_VERBOSE_OUT(("Creating dynamic logs ...\n")); pstring_list_t ll(m_logs, ":"); for (int i=0; i < ll.size(); i++) { pstring name = "log_" + ll[i]; /*netlist_device_t *nc = */ m_setup->register_dev("nld_log", name); m_setup->register_link(name + ".I", ll[i]); } }
void netlist_parser::netdev_param() { pstring param; nl_double val; param = get_identifier(); require_token(m_tok_comma); val = eval_param(get_token()); NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val)); m_setup.register_param(param, val); require_token(m_tok_param_right); }
void netlist_parser::net_alias() { pstring alias; pstring out; skipws(); alias = getname(','); skipws(); out = getname(')'); NL_VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr())); m_setup.register_alias(alias, out); }
void netlist_parser::netdev_param() { pstring param; double val; skipws(); param = getname(','); skipws(); val = eval_param(); NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val)); m_setup.register_param(param, val); check_char(')'); }
ATTR_COLD void netlist_base_t::stop() { /* find the main clock and solver ... */ NL_VERBOSE_OUT(("Stopping all devices ...\n")); // Step all devices once ! for (int i = 0; i < m_devices.count(); i++) { m_devices[i]->stop_dev(); } }
void log_setup() { NL_VERBOSE_OUT(("Creating dynamic logs ...\n")); nl_util::pstring_list ll = nl_util::split(m_logs, ":"); for (int i=0; i < ll.count(); i++) { netlist_device_t *nc = m_setup->factory().new_device_by_classname("nld_log", *m_setup); pstring name = "log_" + ll[i]; m_setup->register_dev(nc, name); m_setup->register_link(name + ".I", ll[i]); } }
void parser_t::net_alias() { pstring alias = get_identifier_or_number(); require_token(m_tok_comma); pstring out = get_identifier(); require_token(m_tok_param_right); NL_VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr())); m_setup.register_alias(alias, out); }
ATTR_COLD void netlist_base_t::start() { /* find the main clock and solver ... */ m_mainclock = get_single_device<NETLIB_NAME(mainclock)>("mainclock"); m_solver = get_single_device<NETLIB_NAME(solver)>("solver"); m_gnd = get_single_device<NETLIB_NAME(gnd)>("gnd"); NL_VERBOSE_OUT(("Initializing devices ...\n")); for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry)) { netlist_device_t *dev = entry->object(); dev->start_dev(); } }
void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname) { while (true) { token_t token = get_token(); if (token.is_type(ENDOFFILE)) return; require_token(m_tok_param_left); NL_VERBOSE_OUT(("Parser: Device: %s\n", token.str().cstr())); if (token.is(m_tok_ALIAS)) net_alias(); else if (token.is(m_tok_DIPPINS)) dippins(); else if (token.is(m_tok_NET_C)) net_c(); else if (token.is(m_tok_FRONTIER)) frontier(); else if (token.is(m_tok_PARAM)) netdev_param(); else if (token.is(m_tok_NET_MODEL)) net_model(); else if (token.is(m_tok_SUBMODEL)) net_submodel(); else if (token.is(m_tok_INCLUDE)) net_include(); else if (token.is(m_tok_LOCAL_SOURCE)) net_local_source(); else if (token.is(m_tok_TRUTHTABLE_START)) net_truthtable_start(); else if (token.is(m_tok_LOCAL_LIB_ENTRY)) { m_setup.register_lib_entry(get_identifier()); require_token(m_tok_param_right); } else if (token.is(m_tok_NETLIST_END)) { netdev_netlist_end(); return; } else device(token.str()); } }
ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const void *owner, const int size, const int count, void *ptr) { pstring fullname = stname; ATTR_UNUSED pstring ts[] = { "NOT_SUPPORTED", "DT_CUSTOM", "DT_DOUBLE", "DT_INT64", "DT_INT16", "DT_INT8", "DT_INT", "DT_BOOLEAN" }; NL_VERBOSE_OUT(("SAVE: <%s> %s(%d) %p\n", fullname.cstr(), ts[dt].cstr(), size, ptr)); pstate_entry_t *p = new pstate_entry_t(stname, dt, owner, size, count, ptr); m_save.add(p); }
void parser_t::net_c() { pstring first = get_identifier(); require_token(m_tok_comma); while (true) { pstring t1 = get_identifier(); m_setup.register_link(first , t1); NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", first.cstr(), t1.cstr())); token_t n = get_token(); if (n.is(m_tok_param_right)) break; if (!n.is(m_tok_comma)) error("expected a comma, found <%s>", n.str().cstr()); } }
void netlist_parser::netdev_const(const pstring &dev_name) { pstring name; netlist_device_t *dev; pstring paramfq; double val; skipws(); name = getname(','); dev = m_setup.factory().new_device_by_name(dev_name, m_setup); m_setup.register_dev(dev, name); skipws(); val = eval_param(); paramfq = name + ".CONST"; NL_VERBOSE_OUT(("Parser: Const: %s %f\n", name.cstr(), val)); check_char(')'); m_setup.register_param(paramfq, val); }
ATTR_COLD void matrix_solver_t::setup(analog_net_t::list_t &nets) { NL_VERBOSE_OUT(("New solver setup\n")); m_nets.clear(); for (std::size_t k = 0; k < nets.size(); k++) { m_nets.add(nets[k]); } for (std::size_t k = 0; k < nets.size(); k++) { NL_VERBOSE_OUT(("setting up net\n")); analog_net_t *net = nets[k]; net->m_solver = this; for (std::size_t i = 0; i < net->m_core_terms.size(); i++) { core_terminal_t *p = net->m_core_terms[i]; NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), net->name().cstr(), (int) net->isRailNet())); switch (p->type()) { case terminal_t::TERMINAL: switch (p->device().family()) { case device_t::CAPACITOR: if (!m_step_devices.contains(&p->device())) m_step_devices.add(&p->device()); break; case device_t::BJT_EB: case device_t::DIODE: case device_t::LVCCS: case device_t::BJT_SWITCH: NL_VERBOSE_OUT(("found BJT/Diode/LVCCS\n")); if (!m_dynamic_devices.contains(&p->device())) m_dynamic_devices.add(&p->device()); break; default: break; } { terminal_t *pterm = dynamic_cast<terminal_t *>(p); add_term(k, pterm); } NL_VERBOSE_OUT(("Added terminal\n")); break; case terminal_t::INPUT: { analog_output_t *net_proxy_output = NULL; for (std::size_t i = 0; i < m_inps.size(); i++) if (m_inps[i]->m_proxied_net == &p->net().as_analog()) { net_proxy_output = m_inps[i]; break; } if (net_proxy_output == NULL) { net_proxy_output = palloc(analog_output_t); net_proxy_output->init_object(*this, this->name() + "." + pstring::sprintf("m%" SIZETFMT, SIZET_PRINTF(m_inps.size()))); m_inps.add(net_proxy_output); net_proxy_output->m_proxied_net = &p->net().as_analog(); } net_proxy_output->net().register_con(*p); // FIXME: repeated net_proxy_output->net().rebuild_list(); NL_VERBOSE_OUT(("Added input\n")); } break; default: netlist().error("unhandled element found\n"); break; } } NL_VERBOSE_OUT(("added net with %" SIZETFMT " populated connections\n", net->m_core_terms.size())); } }