Exemplo n.º 1
0
            //#define ENTRYY(n, m, s)    case (n * 100 + m): \
            //    { using xtype = netlist_factory_truthtable_t<n, m>; \
            //        ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break

            //#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
            //                    ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \
            //                    ENTRYY(n, 7, s); ENTRYY(n, 8, s)

            public static void tt_factory_create(setup_t setup, tt_desc desc, string sourcefile)
            {
                netlist_base_factory_truthtable_t ret;

                //switch (desc.ni * 100 + desc.no)
                //{
                //    ENTRY(1, sourcefile);
                //    ENTRY(2, sourcefile);
                //    ENTRY(3, sourcefile);
                //    ENTRY(4, sourcefile);
                //    ENTRY(5, sourcefile);
                //    ENTRY(6, sourcefile);
                //    ENTRY(7, sourcefile);
                //    ENTRY(8, sourcefile);
                //    ENTRY(9, sourcefile);
                //    ENTRY(10, sourcefile);
                //    ENTRY(11, sourcefile);
                //    ENTRY(12, sourcefile);
                //    default:
                //        pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
                //        nl_assert_always(false, msg);
                //}

                // re-write of the above case statement
                if (desc.ni >= 1 && desc.ni <= 12 &&
                    desc.no >= 1 && desc.no <= 8)
                {
                    ret = new netlist_factory_truthtable_t(desc.ni, desc.no, desc.name, desc.classname, desc.def_param, sourcefile);
                }
                else
                {
                    string msg = new plib.pfmt("unable to create truthtable<{0},{1}>").op(desc.ni, desc.no);
                    nl_base_global.nl_assert_always(false, msg);
                    ret = new netlist_factory_truthtable_t(0, 0, null, null, null, null);
                }


                ret.desc = desc.desc;
                if (desc.family != "")
                {
                    ret.family = setup.family_from_model(desc.family);
                }

                setup.factory().register_device(ret);  //std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
            }
Exemplo n.º 2
0
        protected void error(string errs)  //void ptoken_reader::error(const perrmsg &errs)
        {
            string s           = "";
            string trail       = "                 from ";
            string trail_first = "In file included from ";
            string e           = new plib.pfmt("{0}:{1}:0: error: {2}\n")
                                 .op(m_source_location.back().file_name(), m_source_location.back().line(), errs);

            m_source_location.pop_back();
            while (!m_source_location.empty())
            {
                if (m_source_location.size() == 1)
                {
                    trail = trail_first;
                }
                s = new plib.pfmt("{0}{1}:{2}:0\n{3}").op(trail, m_source_location.back().file_name(), m_source_location.back().line(), s);
                m_source_location.pop_back();
            }

            verror("\n" + s + e + " " + m_line + "\n");
        }
Exemplo n.º 3
0
        void error(string err)
        {
            string s           = "";
            string trail       = "                 from ";
            string trail_first = "In file included from ";
            string e           = new plib.pfmt("{0}:{1}:0: error: {2}\n")
                                 .op(m_stack.back().m_name, m_stack.back().m_lineno, err);

            m_stack.pop_back();
            while (!m_stack.empty())
            {
                if (m_stack.size() == 1)
                {
                    trail = trail_first;
                }
                s = new plib.pfmt("{0}{1}:{2}:0\n{3}").op(trail, m_stack.back().m_name, m_stack.back().m_lineno, s);
                m_stack.pop_back();
            }

            throw new pexception("\n" + s + e + " " + m_line + "\n");
        }
Exemplo n.º 4
0
        public void register_frontier(string attach, string r_IN, string r_OUT)
        {
            string frontier_name = new plib.pfmt("frontier_{0}").op(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");
            string attfn     = build_fqn(attach);
            string front_fqn = build_fqn(frontier_name);
            bool   found     = false;

            for (int i = 0; i < m_abstract.m_links.Count; i++)  //for (auto & link  : m_abstract.m_links)
            {
                var link = m_abstract.m_links[i];

                if (link.first == attfn)
                {
                    m_abstract.m_links[i] = new abstract_t_link_t(front_fqn + ".I", link.second);  //link.first = front_fqn + ".I";
                    found = true;
                }
                else if (link.second == attfn)
                {
                    m_abstract.m_links[i] = new abstract_t_link_t(link.first, front_fqn + ".I");  //link.second = front_fqn + ".I";
                    found = true;
                }
            }

            if (!found)
            {
                log().fatal.op(MF_FOUND_NO_OCCURRENCE_OF_1(attach));
                throw new nl_exception(MF_FOUND_NO_OCCURRENCE_OF_1(attach));
            }

            register_link(attach, frontier_name + ".Q");
        }
Exemplo n.º 5
0
            //template <typename FT, int SIZE>
            void generate_code(out string strm)  //void matrix_solver_GCR_t<FT, SIZE>::generate_code(plib::putf8_fmt_writer &strm)
            {
                strm = "";

                size_t iN       = this.size();
                string fptype   = fp_constants_double.name();   //pstring fptype(fp_constants<FT>::name());
                string fpsuffix = fp_constants_double.suffix(); //pstring fpsuffix(fp_constants<FT>::suffix());

                // avoid unused variable warnings
                strm += string.Format("\tplib::unused_var({0});\n", "cnV");

                for (size_t i = 0; i < mat.nz_num; i++)
                {
                    strm += string.Format("\t{0} m_A{1}(0.0);\n", fptype, i, i);
                }

                for (size_t k = 0; k < iN; k++)
                {
                    var net = this.m_terms[k];

                    // FIXME: gonn, gtn and Idr - which float types should they have?

                    //auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<FT>::zero());
                    //*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;

                    var pd = this.m_mat_ptr.op(k)[net.railstart()] - new Pointer <FT>(this.mat.A, 0);  //auto pd = this->m_mat_ptr[k][net.railstart()] - &this->mat.A[0];
#if false
                    string terms = new plib.pfmt("m_A{0} = gt[{1}]").op(pd.Offset, this.m_gtn.didx(k, 0));
                    for (size_t i = 1; i < net.count(); i++)
                    {
                        terms += new plib.pfmt(" + gt[{0}]").op(this.m_gtn.didx(k, i));
                    }

                    strm += string.Format("\t{0};\n", terms);
#else
                    for (size_t i = 0; i < net.count(); i++)
                    {
                        strm += string.Format("\tm_A{0} += gt[{1}];\n", pd, this.m_gtn.didx(k, i));
                    }
#endif

                    //for (std::size_t i = 0; i < railstart; i++)
                    //  *tcr_r[i]       += static_cast<FT>(go[i]);

                    for (size_t i = 0; i < net.railstart(); i++)
                    {
                        var p = this.m_mat_ptr.op(k)[i] - new Pointer <FT>(this.mat.A, 0);  //auto p = this->m_mat_ptr[k][i] - &this->mat.A[0];
                        strm += string.Format("\tm_A{0} += go[{1}];\n", p, this.m_gonn.didx(k, i));
                    }

#if false
                    //auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<FT>::zero()));

                    terms = new plib.pfmt("{0} RHS{1} = Idr[{2}]").op(fptype, k, this.m_Idrn.didx(k, 0));
                    for (size_t i = 1; i < net.count(); i++)
                    {
                        terms += new plib.pfmt(" + Idr[{0}]").op(this.m_Idrn.didx(k, i));
                    }
                    //for (std::size_t i = railstart; i < term_count; i++)
                    //  RHS_t +=  (- go[i]) * *cnV[i];

                    for (size_t i = net.railstart(); i < net.count(); i++)
                    {
                        terms += new plib.pfmt(" - go[{0}] * *cnV[{1}]").op(this.m_gonn.didx(k, i), this.m_connected_net_Vn.didx(k, i));
                    }

                    strm += string.Format("\t{0};\n", terms);
#else
                    //auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<FT>::zero()));
                    strm += string.Format("\t{0} RHS{1} = Idr[{2}];\n", fptype, k, this.m_Idrn.didx(k, 0));
                    for (size_t i = 1; i < net.count(); i++)
                    {
                        strm += string.Format("\tRHS{0} += Idr[{1}];\n", k, this.m_Idrn.didx(k, i));
                    }
                    //for (std::size_t i = railstart; i < term_count; i++)
                    //  RHS_t +=  (- go[i]) * *cnV[i];

                    for (size_t i = net.railstart(); i < net.count(); i++)
                    {
                        strm += string.Format("\tRHS{0} -= go[{1}] * *cnV[{2}];\n", k, this.m_gonn.didx(k, i), this.m_connected_net_Vn.didx(k, i));
                    }
#endif
                }

                for (size_t i = 0; i < iN - 1; i++)
                {
                    //const auto &nzbd = this->m_terms[i].m_nzbd;
                    var nzbd       = mat.nzbd(i);
                    var nzbd_count = mat.nzbd_count(i);

                    if (nzbd_count > 0)
                    {
                        size_t pi = mat.diag[i];

                        //const FT f = 1.0 / m_A[pi++];
                        strm += string.Format("\tconst {0} f{1} = 1.0{2} / m_A{3};\n", fptype, i, fpsuffix, pi);
                        pi++;
                        size_t piie = mat.row_idx[i + 1];

                        //for (auto & j : nzbd)
                        for (size_t jj = 0; jj < nzbd_count; jj++)
                        {
                            size_t j = nzbd[jj];

                            // proceed to column i
                            size_t pj = mat.row_idx[j];

                            while (mat.col_idx[pj] < i)
                            {
                                pj++;
                            }

                            //const FT f1 = - m_A[pj++] * f;
                            strm += string.Format("\tconst {0} f{1}_{2} = -f{3} * m_A{4};\n", fptype, i, j, i, pj);
                            pj++;

                            // subtract row i from j
                            for (size_t pii = pi; pii < piie;)
                            {
                                while (mat.col_idx[pj] < mat.col_idx[pii])
                                {
                                    pj++;
                                }
                                //m_A[pj++] += m_A[pii++] * f1;
                                strm += string.Format("\tm_A{0} += m_A{1} * f{2}_{3};\n", pj, pii, i, j);
                                pj++; pii++;
                            }
                            //RHS[j] += f1 * RHS[i];
                            strm += string.Format("\tRHS{0} += f{1}_{2} * RHS{3};\n", j, i, j, i);
                        }
                    }
                }

                //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
                strm += string.Format("\tV[{0}] = RHS{1} / m_A{2};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
                for (size_t j = iN - 1; j-- > 0;)
                {
#if true
                    strm += string.Format("\t{0} tmp{1} = 0.0{2};\n", fptype, j, fpsuffix);
                    size_t e = mat.row_idx[j + 1];
                    for (size_t pk = (size_t)mat.diag[j] + 1; pk < e; pk++)
                    {
                        strm += string.Format("\ttmp{0} += m_A{1} * V[{2}];\n", j, pk, mat.col_idx[pk]);
                    }
                    strm += string.Format("\tV[{0}] = (RHS{0} - tmp{0}) / m_A{3};\n", j, j, j, mat.diag[j]);
#else
                    pstring           tmp;
                    const std::size_t e = mat.row_idx[j + 1];
                    for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
                    {
                        tmp = tmp + plib::pfmt(" + m_A{2} * V[{3}]")(j, pk, mat.col_idx[pk]);
                    }
                    if (tmp.empty())
                    {
                        strm("\tV[{1}] = RHS{1} / m_A{2};\n", j, mat.diag[j]);
                    }
                    else
                    {
                        //strm("\tconst {1} tmp{2} = {3};\n", fptype, j, tmp.substr(3));
                        //strm("\tV[{1}] = (RHS{1} - tmp{1}) / m_A{2};\n", j, mat.diag[j]);
                        strm("\tV[{1}] = (RHS{1} - ({2})) / m_A{3};\n", j, tmp.substr(3), mat.diag[j]);
                    }
#endif
                }
            }
Exemplo n.º 6
0
            public void post_start()
            {
                log().verbose.op("Scanning net groups ...");
                // determine net groups

                net_splitter splitter = new net_splitter();

                splitter.run(state());

                log().verbose.op("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size());

                int num_errors = 0;

                log().verbose.op("checking net consistency  ...");
                foreach (var grp in splitter.groups)
                {
                    int    railterms   = 0;
                    string nets_in_grp = "";
                    foreach (var n in grp)
                    {
                        nets_in_grp += (n.name() + " ");
                        if (!n.is_analog())
                        {
                            state().log().error.op(ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n.name()));
                            num_errors++;
                        }

                        if (n.is_rail_net())
                        {
                            state().log().error.op(ME_SOLVER_CONSISTENCY_RAIL_NET(n.name()));
                            num_errors++;
                        }

                        foreach (var t in state().core_terms(n))
                        {
                            if (!t.has_net())
                            {
                                state().log().error.op(ME_SOLVER_TERMINAL_NO_NET(t.name()));
                                num_errors++;
                            }
                            else
                            {
                                var otherterm = t is terminal_t ? (terminal_t)t : null;  //auto *otherterm = dynamic_cast<terminal_t *>(t);
                                if (otherterm != null)
                                {
                                    if (state().setup().get_connected_terminal(otherterm).net().is_rail_net())
                                    {
                                        railterms++;
                                    }
                                }
                            }
                        }
                    }

                    if (railterms == 0)
                    {
                        state().log().error.op(ME_SOLVER_NO_RAIL_TERMINAL(nets_in_grp));
                        num_errors++;
                    }
                }

                if (num_errors > 0)
                {
                    throw new nl_exception(MF_SOLVER_CONSISTENCY_ERRORS(num_errors));
                }

                // setup the solvers
                foreach (var grp in splitter.groups)
                {
                    nld_solver_solver_ptr ms       = null;
                    string sname                   = new plib.pfmt("Solver_{0}").op(m_mat_solvers.size());
                    nld_solver_params_uptr params_ = new solver.solver_parameters_t(this, sname + ".", m_params);  //params_uptr params = plib::make_unique<solver::solver_parameters_t, solver_arena>(*this, sname + ".", m_params);

                    switch (params_.m_fp_type.op())
                    {
                    case solver.matrix_fp_type_e.FLOAT:
                        if (!config.use_float_matrix)
                        {
                            log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        }

                        //ms = create_solvers<std::conditional_t<config::use_float_matrix::value, float, double>>(sname, params.get(), grp);
                        if (config.use_float_matrix)
                        {
                            ms = create_solvers <float, plib.constants_operators_float>(sname, params_, grp);
                        }
                        else
                        {
                            ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);
                        }
                        break;

                    case solver.matrix_fp_type_e.DOUBLE:
                        ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);     //ms = create_solvers<double>(sname, params.get(), grp);
                        break;

                    case solver.matrix_fp_type_e.LONGDOUBLE:
                        if (!config.use_long_double_matrix)
                        {
                            log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        }

                        //ms = create_solvers<std::conditional_t<config::use_long_double_matrix::value, long double, double>>(sname, params.get(), grp);
                        if (config.use_long_double_matrix)
                        {
                            throw new emu_unimplemented();      //ms = create_solvers<long double>(sname, params_, grp);
                        }
                        else
                        {
                            ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);
                        }
                        break;

                    case solver.matrix_fp_type_e.FLOATQ128:
#if (NL_USE_FLOAT128)
                        ms = create_solvers <FLOAT128>(sname, params.get(), grp);
#else
                        log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);     //ms = create_solvers<double>(sname, params.get(), grp);
#endif
                        break;
                    }

                    log().verbose.op("Solver {0}", ms.name());
                    log().verbose.op("       ==> {0} nets", grp.size());
                    log().verbose.op("       has {0} dynamic elements", ms.dynamic_device_count());
                    log().verbose.op("       has {0} timestep elements", ms.timestep_device_count());
                    foreach (var n in grp)
                    {
                        log().verbose.op("Net {0}", n.name());
                        foreach (var t in state().core_terms(n))
                        {
                            log().verbose.op("   {0}", t.name());
                        }
                    }

                    m_mat_params.push_back(params_);

                    m_mat_solvers.push_back(ms);
                }
            }
Exemplo n.º 7
0
        //bool parse(plib::istream_uptr &&strm, const pstring &nlname);


        public bool parse(parser_t_token_store tokstor, string nlname)
        {
            set_token_source(tokstor);

            bool in_nl = false;

            while (true)
            {
                // FIXME: line numbers in cached local netlists are wrong
                //        need to process raw tokens here.
                parser_t_token_t token = get_token_raw();

                if (token.is_type(parser_t_token_type.ENDOFFILE))
                {
                    return(false);
                }

                if (token.is_(m_tok_NETLIST_END) || token.is_(m_tok_TRUTHTABLE_END))
                {
                    if (!in_nl)
                    {
                        error(MF_PARSER_UNEXPECTED_1(token.str()));
                    }
                    else
                    {
                        in_nl = false;
                    }

                    require_token(m_tok_paren_left);
                    require_token(m_tok_paren_right);

                    m_cur_local.push_back(token);
                    m_cur_local.push_back(new parser_t_token_t(m_tok_paren_left));
                    m_cur_local.push_back(new parser_t_token_t(m_tok_paren_right));
                }
                else if (token.is_(m_tok_NETLIST_START) || token.is_(m_tok_TRUTHTABLE_START))
                {
                    if (in_nl)
                    {
                        error(MF_PARSER_UNEXPECTED_1(token.str()));
                    }

                    require_token(m_tok_paren_left);
                    parser_t_token_t name = get_token();
                    if (token.is_(m_tok_NETLIST_START) && (name.str() == nlname || nlname.empty()))
                    {
                        require_token(m_tok_paren_right);
                        parse_netlist();
                        return(true);
                    }

                    if (token.is_(m_tok_TRUTHTABLE_START) && name.str() == nlname)
                    {
                        net_truthtable_start(nlname);
                        return(true);
                    }

                    // create a new cached local store
                    m_local.emplace(name.str(), new parser_t_token_store());
                    m_cur_local = m_local[name.str()];
                    var sl = sourceloc();
                    var li = new plib.pfmt("# {0} \"{1}\"").op(sl.line(), sl.file_name());

                    m_cur_local.push_back(new parser_t_token_t(parser_t_token_type.LINEMARKER, li));
                    m_cur_local.push_back(token);
                    m_cur_local.push_back(new parser_t_token_t(m_tok_paren_left));
                    m_cur_local.push_back(name);
                    //m_cur_local->push_back(token_t(m_tok_paren_right));
                    in_nl = true;
                }
                // FIXME: do we really need this going forward ? there should be no need
                //        for NETLIST_EXTERNAL in netlist files
                else if (token.is_(m_tok_NETLIST_EXTERNAL))
                {
                    if (in_nl)
                    {
                        error(MF_UNEXPECTED_NETLIST_EXTERNAL());
                    }

                    require_token(m_tok_paren_left);
                    parser_t_token_t name = get_token();
                    require_token(m_tok_paren_right);
                }
                else if (!in_nl)
                {
                    if (!token.is_(m_tok_static) && !token.is_type(parser_t_token_type.SOURCELINE) &&
                        !token.is_type(parser_t_token_type.LINEMARKER))
                    {
                        error(MF_EXPECTED_NETLIST_START_1(token.str()));
                    }
                }
                else
                {
                    m_cur_local.push_back(token);
                }
            }
        }
Exemplo n.º 8
0
            //template <typename T>
            //void store(const T * RESTRICT V);
            //template <typename T>
            //T delta(const T * RESTRICT V);

            //template <typename T>
            //void build_LE_A();
            //template <typename T>
            //void build_LE_RHS();


            /* calculate matrix */
            void setup_matrix()
            {
                UInt32 iN = (UInt32)m_nets.size();

                for (UInt32 k = 0; k < iN; k++)
                {
                    m_terms[k].railstart = m_terms[k].count();
                    for (UInt32 i = 0; i < m_rails_temp[k].count(); i++)
                    {
                        this.m_terms[k].add(m_rails_temp[k].terms()[i], m_rails_temp[k].connected_net_idx()[i], false);
                    }

                    m_terms[k].set_pointers();
                }

                foreach (terms_for_net_t rt in m_rails_temp)
                {
                    rt.clear(); // no longer needed
                    //plib::pfree(rt); // no longer needed
                }

                m_rails_temp.clear();

                /* Sort in descending order by number of connected matrix voltages.
                 * The idea is, that for Gauss-Seidel algo the first voltage computed
                 * depends on the greatest number of previous voltages thus taking into
                 * account the maximum amout of information.
                 *
                 * This actually improves performance on popeye slightly. Average
                 * GS computations reduce from 2.509 to 2.370
                 *
                 * Smallest to largest : 2.613
                 * Unsorted            : 2.509
                 * Largest to smallest : 2.370
                 *
                 * Sorting as a general matrix pre-conditioning is mentioned in
                 * literature but I have found no articles about Gauss Seidel.
                 *
                 * For Gaussian Elimination however increasing order is better suited.
                 * NOTE: Even better would be to sort on elements right of the matrix diagonal.
                 *
                 */

                if (m_sort != eSortType.NOSORT)
                {
                    int sort_order = (m_sort == eSortType.DESCENDING ? 1 : -1);

                    for (UInt32 k = 0; k < iN - 1; k++)
                    {
                        for (UInt32 i = k + 1; i < iN; i++)
                        {
                            if (((int)(m_terms[k].railstart) - (int)(m_terms[i].railstart)) * sort_order < 0)
                            {
                                //std::swap(m_terms[i], m_terms[k]);
                                var termsTemp = m_terms[i];
                                m_terms[i] = m_terms[k];
                                m_terms[k] = termsTemp;
                                //std::swap(m_nets[i], m_nets[k]);
                                var netsTemp = m_nets[i];
                                m_nets[i] = m_nets[k];
                                m_nets[k] = netsTemp;
                            }
                        }
                    }

                    foreach (var term in m_terms)
                    {
                        var other = term.connected_net_idx();
                        for (UInt32 i = 0; i < term.count(); i++)
                        {
                            if (other[i] != -1)
                            {
                                other[i] = get_net_idx(term.terms()[i].otherterm.net());
                            }
                        }
                    }
                }

                /* create a list of non zero elements. */
                for (UInt32 k = 0; k < iN; k++)
                {
                    terms_for_net_t t = m_terms[k];
                    /* pretty brutal */
                    var other = t.connected_net_idx();

                    t.nz.clear();

                    for (UInt32 i = 0; i < t.railstart; i++)
                    {
                        if (!t.nz.Contains((UInt32)other[i]))  //if (!plib::container::contains(t->m_nz, static_cast<unsigned>(other[i])))
                        {
                            t.nz.push_back((UInt32)other[i]);
                        }
                    }

                    t.nz.push_back(k);     // add diagonal

                    /* and sort */
                    t.nz.Sort();  //std::sort(t.m_nz.begin(), t.m_nz.end());
                }

                /* create a list of non zero elements right of the diagonal
                 * These list anticipate the population of array elements by
                 * Gaussian elimination.
                 */
                for (UInt32 k = 0; k < iN; k++)
                {
                    terms_for_net_t t = m_terms[k];
                    /* pretty brutal */
                    var other = t.connected_net_idx();

                    if (k == 0)
                    {
                        t.nzrd.clear();
                    }
                    else
                    {
                        t.nzrd = m_terms[k - 1].nzrd;
                        for (var jIdx = 0; jIdx < t.nzrd.Count;)    //for (var j = t.nzrd.begin(); j != t.nzrd.end(); )
                        {
                            var j = t.nzrd[jIdx];

                            if (j < k + 1)
                            {
                                t.nzrd.erase(jIdx);
                            }
                            else
                            {
                                ++jIdx;
                            }
                        }
                    }

                    for (UInt32 i = 0; i < t.railstart; i++)
                    {
                        if (!t.nzrd.Contains((UInt32)other[i]) && other[i] >= (int)(k + 1))  //if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(other[i])) && other[i] >= static_cast<int>(k + 1))
                        {
                            t.nzrd.push_back((UInt32)other[i]);
                        }
                    }

                    /* and sort */
                    t.nzrd.Sort();  //std::sort(t.m_nzrd.begin(), t.m_nzrd.end());
                }

                /* create a list of non zero elements below diagonal k
                 * This should reduce cache misses ...
                 */

                bool [,] touched = new bool [iN, iN];  //bool **touched = plib::palloc_array<bool *>(iN);
                //for (UInt32 k = 0; k < iN; k++)
                //    touched[k] = plib::palloc_array<bool>(iN);

                for (UInt32 k = 0; k < iN; k++)
                {
                    for (UInt32 j = 0; j < iN; j++)
                    {
                        touched[k, j] = false;
                    }

                    for (UInt32 j = 0; j < m_terms[k].nz.size(); j++)
                    {
                        touched[k, m_terms[k].nz[j]] = true;
                    }
                }

                m_ops = 0;
                for (UInt32 k = 0; k < iN; k++)
                {
                    m_ops++; // 1/A(k,k)
                    for (UInt32 row = k + 1; row < iN; row++)
                    {
                        if (touched[row, k])
                        {
                            m_ops++;
                            if (!m_terms[k].nzbd.Contains(row))  //if (!plib::container::contains(m_terms[k]->m_nzbd, row))
                            {
                                m_terms[k].nzbd.push_back(row);
                            }

                            for (UInt32 col = k + 1; col < iN; col++)
                            {
                                if (touched[k, col])
                                {
                                    touched[row, col] = true;
                                    m_ops            += 2;
                                }
                            }
                        }
                    }
                }

                log().verbose.op("Number of mults/adds for {0}: {1}", name(), m_ops);

#if false
                if ((0))
                {
                    for (unsigned k = 0; k < iN; k++)
                    {
                        pstring line = plib::pfmt("{1:3}")(k);
                        for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
                        {
                            line += plib::pfmt(" {1:3}")(m_terms[k]->m_nzrd[j]);
                        }
                        log().verbose("{1}", line);
                    }
                }
#endif

                /*
                 * save states
                 */
                for (UInt32 k = 0; k < iN; k++)
                {
                    string num = new plib.pfmt("{0}").op(k);

                    state().save(this, m_terms[k].last_V, "lastV." + num);
                    state().save(this, m_terms[k].DD_n_m_1, "m_DD_n_m_1." + num);
                    state().save(this, m_terms[k].h_n_m_1, "m_h_n_m_1." + num);

                    state().save(this, m_terms[k].go(), "GO" + num, m_terms[k].count());
                    state().save(this, m_terms[k].gt(), "GT" + num, m_terms[k].count());
                    state().save(this, m_terms[k].Idr(), "IDR" + num, m_terms[k].count());
                }

                //for (UInt32 k = 0; k < iN; k++)
                //    plib::pfree_array(touched[k]);
                //plib::pfree_array(touched);
                touched = null;
            }
Exemplo n.º 9
0
        //#define ENTRYY(n, m, s)    case (n * 100 + m): \
        //    { using xtype = devices::netlist_factory_truthtable_t<n, m>; \
        //        auto cs=s; \
        //        ret = plib::make_unique<xtype, host_arena>(desc.name, std::move(cs)); } \
        //        break

        //#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
        //                    ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s); \
        //                    ENTRYY(n, 7, s); ENTRYY(n, 8, s); ENTRYY(n, 9, s); \
        //                    ENTRYY(n, 10, s)


        public static truthtable_base_element_t truthtable_create(tt_desc desc, properties props)
        {
            truthtable_base_element_t ret = null;

            switch (desc.ni * 100 + desc.no)
            {
            //ENTRY(1, props);
            case (1 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_1>(desc.name, props); break;

            case (1 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_2>(desc.name, props); break;

            case (1 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_3>(desc.name, props); break;

            case (1 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_4>(desc.name, props); break;

            case (1 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_5>(desc.name, props); break;

            case (1 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_6>(desc.name, props); break;

            case (1 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_7>(desc.name, props); break;

            case (1 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_8>(desc.name, props); break;

            case (1 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_9>(desc.name, props); break;

            case (1 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_1, u32_const_10>(desc.name, props); break;

            //ENTRY(2, props);
            case (2 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_1>(desc.name, props); break;

            case (2 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_2>(desc.name, props); break;

            case (2 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_3>(desc.name, props); break;

            case (2 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_4>(desc.name, props); break;

            case (2 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_5>(desc.name, props); break;

            case (2 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_6>(desc.name, props); break;

            case (2 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_7>(desc.name, props); break;

            case (2 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_8>(desc.name, props); break;

            case (2 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_9>(desc.name, props); break;

            case (2 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_2, u32_const_10>(desc.name, props); break;

            //ENTRY(3, props);
            case (3 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_1>(desc.name, props); break;

            case (3 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_2>(desc.name, props); break;

            case (3 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_3>(desc.name, props); break;

            case (3 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_4>(desc.name, props); break;

            case (3 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_5>(desc.name, props); break;

            case (3 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_6>(desc.name, props); break;

            case (3 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_7>(desc.name, props); break;

            case (3 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_8>(desc.name, props); break;

            case (3 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_9>(desc.name, props); break;

            case (3 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_3, u32_const_10>(desc.name, props); break;

            //ENTRY(4, props);
            case (4 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_1>(desc.name, props); break;

            case (4 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_2>(desc.name, props); break;

            case (4 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_3>(desc.name, props); break;

            case (4 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_4>(desc.name, props); break;

            case (4 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_5>(desc.name, props); break;

            case (4 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_6>(desc.name, props); break;

            case (4 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_7>(desc.name, props); break;

            case (4 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_8>(desc.name, props); break;

            case (4 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_9>(desc.name, props); break;

            case (4 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_4, u32_const_10>(desc.name, props); break;

            //ENTRY(5, props);
            case (5 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_1>(desc.name, props); break;

            case (5 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_2>(desc.name, props); break;

            case (5 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_3>(desc.name, props); break;

            case (5 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_4>(desc.name, props); break;

            case (5 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_5>(desc.name, props); break;

            case (5 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_6>(desc.name, props); break;

            case (5 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_7>(desc.name, props); break;

            case (5 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_8>(desc.name, props); break;

            case (5 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_9>(desc.name, props); break;

            case (5 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_5, u32_const_10>(desc.name, props); break;

            //ENTRY(6, props);
            case (6 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_1>(desc.name, props); break;

            case (6 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_2>(desc.name, props); break;

            case (6 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_3>(desc.name, props); break;

            case (6 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_4>(desc.name, props); break;

            case (6 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_5>(desc.name, props); break;

            case (6 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_6>(desc.name, props); break;

            case (6 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_7>(desc.name, props); break;

            case (6 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_8>(desc.name, props); break;

            case (6 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_9>(desc.name, props); break;

            case (6 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_6, u32_const_10>(desc.name, props); break;

            //ENTRY(7, props);
            case (7 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_1>(desc.name, props); break;

            case (7 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_2>(desc.name, props); break;

            case (7 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_3>(desc.name, props); break;

            case (7 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_4>(desc.name, props); break;

            case (7 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_5>(desc.name, props); break;

            case (7 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_6>(desc.name, props); break;

            case (7 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_7>(desc.name, props); break;

            case (7 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_8>(desc.name, props); break;

            case (7 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_9>(desc.name, props); break;

            case (7 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_7, u32_const_10>(desc.name, props); break;

            //ENTRY(8, props);
            case (8 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_1>(desc.name, props); break;

            case (8 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_2>(desc.name, props); break;

            case (8 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_3>(desc.name, props); break;

            case (8 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_4>(desc.name, props); break;

            case (8 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_5>(desc.name, props); break;

            case (8 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_6>(desc.name, props); break;

            case (8 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_7>(desc.name, props); break;

            case (8 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_8>(desc.name, props); break;

            case (8 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_9>(desc.name, props); break;

            case (8 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_8, u32_const_10>(desc.name, props); break;

            //ENTRY(9, props);
            case (9 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_1>(desc.name, props); break;

            case (9 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_2>(desc.name, props); break;

            case (9 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_3>(desc.name, props); break;

            case (9 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_4>(desc.name, props); break;

            case (9 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_5>(desc.name, props); break;

            case (9 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_6>(desc.name, props); break;

            case (9 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_7>(desc.name, props); break;

            case (9 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_8>(desc.name, props); break;

            case (9 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_9>(desc.name, props); break;

            case (9 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_9, u32_const_10>(desc.name, props); break;

            //ENTRY(10, props);
            case (10 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_1>(desc.name, props); break;

            case (10 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_2>(desc.name, props); break;

            case (10 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_3>(desc.name, props); break;

            case (10 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_4>(desc.name, props); break;

            case (10 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_5>(desc.name, props); break;

            case (10 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_6>(desc.name, props); break;

            case (10 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_7>(desc.name, props); break;

            case (10 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_8>(desc.name, props); break;

            case (10 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_9>(desc.name, props); break;

            case (10 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_10, u32_const_10>(desc.name, props); break;

            //ENTRY(11, props);
            case (11 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_1>(desc.name, props); break;

            case (11 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_2>(desc.name, props); break;

            case (11 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_3>(desc.name, props); break;

            case (11 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_4>(desc.name, props); break;

            case (11 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_5>(desc.name, props); break;

            case (11 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_6>(desc.name, props); break;

            case (11 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_7>(desc.name, props); break;

            case (11 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_8>(desc.name, props); break;

            case (11 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_9>(desc.name, props); break;

            case (11 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_11, u32_const_10>(desc.name, props); break;

            //ENTRY(12, props);
            case (12 * 100 + 1): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_1>(desc.name, props); break;

            case (12 * 100 + 2): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_2>(desc.name, props); break;

            case (12 * 100 + 3): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_3>(desc.name, props); break;

            case (12 * 100 + 4): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_4>(desc.name, props); break;

            case (12 * 100 + 5): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_5>(desc.name, props); break;

            case (12 * 100 + 6): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_6>(desc.name, props); break;

            case (12 * 100 + 7): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_7>(desc.name, props); break;

            case (12 * 100 + 8): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_8>(desc.name, props); break;

            case (12 * 100 + 9): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_9>(desc.name, props); break;

            case (12 * 100 + 10): ret = new devices.netlist_factory_truthtable_t <u32_const_12, u32_const_10>(desc.name, props); break;

            default:
                string msg = new plib.pfmt("unable to create truthtable<{0},{2}>").op(desc.ni, desc.no);
                nl_assert_always(false, msg);
                break;
            }

            ret.m_desc        = desc.desc;
            ret.m_family_name = !desc.family.empty() ? desc.family : config.DEFAULT_LOGIC_FAMILY();

            return(ret);
        }
Exemplo n.º 10
0
            //~nld_solver()
            //{
            //    for (auto &s : m_mat_solvers)
            //    {
            //        plib::pfree(s);
            //    }
            //}


            public void post_start()
            {
                const bool use_specific = true;

                m_params.m_pivot    = m_pivot.op() ? 1 : 0;
                m_params.m_accuracy = m_accuracy.op();
                /* FIXME: Throw when negative */
                m_params.m_gs_loops        = (UInt32)m_gs_loops.op();
                m_params.m_nr_loops        = (UInt32)m_nr_loops.op();
                m_params.m_nr_recalc_delay = netlist_time.from_double(m_nr_recalc_delay.op());
                m_params.m_dynamic_lte     = m_dynamic_lte.op();
                m_params.m_gs_sor          = m_gs_sor.op();

                m_params.m_min_timestep = m_dynamic_min_ts.op();
                m_params.m_dynamic_ts   = (m_dynamic_ts.op() == true ? true : false);
                m_params.m_max_timestep = netlist_time.from_double(1.0 / m_freq.op()).as_double();

                if (m_params.m_dynamic_ts)
                {
                    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
                string p = "";  //plib::util::environment("NL_STATS", "");

                if (p != "")
                {
                    m_params.m_log_stats = plib.pstring_global.pstonum_bool(p);  //plib::pstonum<decltype(m_params.m_log_stats)>(p);
                }
                else
                {
                    m_params.m_log_stats = m_log_stats.op();
                }

                log().verbose.op("Scanning net groups ...");
                // determine net groups

                net_splitter splitter = new net_splitter();

                splitter.run(state());

                // setup the solvers
                log().verbose.op("Found {0} net groups in {1} nets\n", splitter.groups.size(), state().nets().size());
                foreach (var grp in splitter.groups)
                {
                    matrix_solver_t ms;
                    UInt32          net_count = (UInt32)grp.size();
                    string          sname     = new plib.pfmt("Solver_{0}").op(m_mat_solvers.size());

                    switch (net_count)
                    {
#if true
                    case 1:
                        if (use_specific)
                        {
                            ms = new matrix_solver_direct1_t(state(), sname, m_params);      //ms = plib::palloc<matrix_solver_direct1_t<double>>(state(), sname, &m_params);
                        }
                        else
                        {
                            ms = create_solver/*<double, 1>*/ (1, 1, sname);
                        }
                        break;

                    case 2:
                        if (use_specific)
                        {
                            ms = new matrix_solver_direct2_t(state(), sname, m_params);      //ms =  plib::palloc<matrix_solver_direct2_t<double>>(state(), sname, &m_params);
                        }
                        else
                        {
                            ms = create_solver/*<double, 2>*/ (2, 2, sname);
                        }
                        break;

#if false
                    case 3:
                        ms = create_solver <double, 3>(3, sname);
                        break;

                    case 4:
                        ms = create_solver <double, 4>(4, sname);
                        break;

                    case 5:
                        ms = create_solver <double, 5>(5, sname);
                        break;

                    case 6:
                        ms = create_solver <double, 6>(6, sname);
                        break;

                    case 7:
                        ms = create_solver <double, 7>(7, sname);
                        break;

                    case 8:
                        ms = create_solver <double, 8>(8, sname);
                        break;

                    case 9:
                        ms = create_solver <double, 9>(9, sname);
                        break;

                    case 10:
                        ms = create_solver <double, 10>(10, sname);
                        break;

                    case 11:
                        ms = create_solver <double, 11>(11, sname);
                        break;

                    case 12:
                        ms = create_solver <double, 12>(12, sname);
                        break;

                    case 15:
                        ms = create_solver <double, 15>(15, sname);
                        break;

                    case 31:
                        ms = create_solver <double, 31>(31, sname);
                        break;

                    case 35:
                        ms = create_solver <double, 35>(35, sname);
                        break;

                    case 43:
                        ms = create_solver <double, 43>(43, sname);
                        break;

                    case 49:
                        ms = create_solver <double, 49>(49, sname);
                        break;
#endif
#if false
                    case 87:
                        ms = create_solver <87, 87>(87, sname);
                        break;
#endif
#endif
                    default:
                        log().warning.op(nl_errstr_global.MW_1_NO_SPECIFIC_SOLVER, net_count);
                        if (net_count <= 8)
                        {
                            ms = create_solver/*<double, -8>*/ (-8, net_count, sname);
                        }
                        else if (net_count <= 16)
                        {
                            ms = create_solver/*<double, -16>*/ (-16, net_count, sname);
                        }
                        else if (net_count <= 32)
                        {
                            ms = create_solver/*<double, -32>*/ (-32, net_count, sname);
                        }
                        else
                        if (net_count <= 64)
                        {
                            ms = create_solver/*<double, -64>*/ (-64, net_count, sname);
                        }
                        else
                        if (net_count <= 128)
                        {
                            ms = create_solver/*<double, -128>*/ (-128, net_count, sname);
                        }
                        else
                        {
                            log().fatal.op(nl_errstr_global.MF_1_NETGROUP_SIZE_EXCEEDED_1, 128);
                            ms = null;     /* tease compilers */
                        }
                        break;
                    }

                    // FIXME ...
                    ms.setup(grp);

                    log().verbose.op("Solver {0}", ms.name());
                    log().verbose.op("       ==> {0} nets", grp.size());
                    log().verbose.op("       has {0} elements", ms.has_dynamic_devices() ? "dynamic" : "no dynamic");
                    log().verbose.op("       has {0} elements", ms.has_timestep_devices() ? "timestep" : "no timestep");

                    foreach (var n in grp)
                    {
                        log().verbose.op("Net {0}", n.name());
                        foreach (var pcore in n.core_terms)
                        {
                            log().verbose.op("   {0}", pcore.name());
                        }
                    }

                    m_mat_solvers.push_back(ms);
                    if (ms.has_timestep_devices())
                    {
                        m_mat_solvers_timestepping.push_back(ms);
                    }
                }
            }