//template <typename PP> static int prepro_expr(simple_iter sexpr, int prio) //static int prepro_expr(simple_iter<PP> &sexpr, int prio) { throw new emu_unimplemented(); #if false int val(0); bool has_val(false); pstring tok = sexpr.peek_ws(); if (tok == "(") { sexpr.next(); val = prepro_expr(sexpr, 255); if (sexpr.next() != ")") { sexpr.error("expected ')'"); } has_val = true; } while (!sexpr.eod()) { tok = sexpr.peek_ws(); if (tok == ")") { if (!has_val) { sexpr.error("Found ')' but have no value computed"); } else { return(val); } } else if (tok == "!") { if (prio < 3) { if (!has_val) { sexpr.error("parsing error!"); } else { return(val); } } sexpr.next(); val = !prepro_expr(sexpr, 3); has_val = true; } CHECKTOK2(*, 5) CHECKTOK2(/, 5) // NOLINT(clang-analyzer-core.DivideZero) CHECKTOK2(+, 6) CHECKTOK2(-, 6) CHECKTOK2(==, 10) CHECKTOK2(&&, 14) CHECKTOK2(||, 15) else { try { val = plib::pstonum <decltype(val)>(tok); } catch (pexception&e) { sexpr.error(e.text()); } has_val = true; sexpr.next(); } } if (!has_val) { sexpr.error("No value computed. Empty expression ?"); } return(val); #endif }
netlist_source_memregion_t(pstring name) : netlist::setup_t::source_t(), m_name(name)
//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; }