commit 38a4958211d3701aa3f51309a5da6ccba0226857 Author: Felix Salfelder Date: Sun Feb 21 20:14:02 2016 +0100 faster queueing constant components are never queued, hence tr_queue_eval is redundant. this adds another container to CARD_LIST for the non-constant ones. making dc sweeps work involves some uglier hacking (on top of the pointer_hack). diff --git a/lib/e_cardlist.cc b/lib/e_cardlist.cc index 10c9392..9cedc03 100644 --- a/lib/e_cardlist.cc +++ b/lib/e_cardlist.cc @@ -217,9 +217,15 @@ CARD_LIST& CARD_LIST::precalc_first() /*--------------------------------------------------------------------------*/ CARD_LIST& CARD_LIST::precalc_last() { + _eq.clear(); for (iterator ci=begin(); ci!=end(); ++ci) { trace_func_comp(); (**ci).precalc_last(); + if(!OPT::prequeue){ itested(); + }else if((*ci)->is_constant()){ itested(); + }else{ itested(); + _eq.push_back(*ci); + } } return *this; } @@ -405,7 +411,13 @@ CARD_LIST& CARD_LIST::do_forall( void (CARD::*thing)( int ), int i ) */ CARD_LIST& CARD_LIST::tr_advance() { - for (iterator ci=begin(); ci!=end(); ++ci) { + std::list* Q; + if(!OPT::prequeue) { itested(); + Q = &_cl; + }else{ itested(); + Q = &_eq; + } + for (iterator ci=Q->begin(); ci!=Q->end(); ++ci) { trace_func_comp(); (**ci).tr_advance(); } @@ -468,9 +480,19 @@ bool CARD_LIST::tr_needs_eval()const */ CARD_LIST& CARD_LIST::tr_queue_eval() { - for (iterator ci=begin(); ci!=end(); ++ci) { + std::list* Q; + if(!OPT::prequeue) { itested(); + Q = &_cl; + }else{ itested(); + Q = &_eq; + } + for (iterator ci=Q->begin(); ci!=Q->end(); ++ci) { trace_func_comp(); - (**ci).tr_queue_eval(); + if((*ci)->is_constant() ){ + assert(!OPT::prequeue); + }else{ + (**ci).tr_queue_eval(); + } } return *this; } @@ -551,7 +573,13 @@ TIME_PAIR CARD_LIST::tr_review() { TIME_PAIR time_by(NEVER,NEVER); - for (iterator ci=begin(); ci!=end(); ++ci) { + std::list* Q; + if(!OPT::prequeue) { itested(); + Q = &_cl; + }else{ itested(); + Q = &_eq; + } + for (iterator ci=Q->begin(); ci!=Q->end(); ++ci) { trace_func_comp(); time_by.min((**ci).tr_review()); } @@ -814,6 +842,21 @@ void CARD_LIST::map_subckt_nodes(const CARD* model, const CARD* here) } } /*--------------------------------------------------------------------------*/ +void CARD_LIST::q_hack(CARD* x) +{ itested(); + +#ifndef NDEBUG + for (iterator i=card_list._eq.begin(); i!=card_list._eq.end(); ++i){ + if(*i == x){ unreachable(); + trace1("already toplevel queued", x->long_label()); + exit(1); + } + } +#endif + + card_list._eq.push_front(x); +} +/*--------------------------------------------------------------------------*/ ///ADP_NODE* CARD_LIST::new_adp_node{ /// assert(d); /// assert(d->scope()); diff --git a/lib/e_elemnt.cc b/lib/e_elemnt.cc index f21c147..e10e14f 100644 --- a/lib/e_elemnt.cc +++ b/lib/e_elemnt.cc @@ -197,7 +197,9 @@ void ELEMENT::tr_restore() } //assert(_time[0] == _sim->_time0); - if (_time[0] != _sim->_time0) { + if (is_constant()){ untested(); + + }else if (_time[0] != _sim->_time0) { error(bDANGER, "//BUG// %s restore time mismatch. t0=%.12f, s->t=%.12f\n", long_label().c_str(), _time[0], _sim->_time0); diff --git a/lib/u_opt1.cc b/lib/u_opt1.cc index 2f12fd1..0d11760 100644 --- a/lib/u_opt1.cc +++ b/lib/u_opt1.cc @@ -86,6 +86,7 @@ order_t OPT::order = oAUTO; smode_t OPT::mode = moMIXED; int OPT::transits = 2; bool OPT::dupcheck = false; +bool OPT::prequeue = getenv("GNUCAP_PREQ"); bool OPT::bypass = true; bool OPT::incmode = true; bool OPT::lcbypass = true; diff --git a/lib/u_opt2.cc b/lib/u_opt2.cc index 5f2e19d..9c595d3 100644 --- a/lib/u_opt2.cc +++ b/lib/u_opt2.cc @@ -152,6 +152,7 @@ bool OPT::set_values(CS& cmd) || cmd.warn(bWARNING, "need analog, digital, or mixed"))) || Get(cmd, "tr{ansits}", &transits) || Get(cmd, "dup{check}", &dupcheck) + || Get(cmd, "preq{ueue}", &prequeue) || Get(cmd, "byp{ass}", &bypass) || Get(cmd, "inc{mode}", &incmode) || Get(cmd, "lcb{ypass}", &lcbypass) diff --git a/src/e_card.h b/src/e_card.h index b359f39..53938d4 100644 --- a/src/e_card.h +++ b/src/e_card.h @@ -83,6 +83,7 @@ public: // dc-tran virtual bool tr_needs_eval()const {return false;} virtual void tr_queue_eval() {} // not const, would need mutable iteration_tag + virtual void tr_prequeue_eval() {} virtual bool do_tr() {return true;} virtual bool do_tr_last() {return true;} virtual void tr_load() {} diff --git a/src/e_cardlist.h b/src/e_cardlist.h index e238f9d..06fc224 100644 --- a/src/e_cardlist.h +++ b/src/e_cardlist.h @@ -51,9 +51,11 @@ private: mutable PARAM_LIST* _params; LANGUAGE* _language; std::list _cl; + std::list _eq; // eval queue const CARD* _owner; // stupid hack const CARD_LIST* _origin; // even more stupid hack public: + static void q_hack(CARD* x); // internal types typedef std::list::iterator iterator; typedef std::list::const_iterator const_iterator; diff --git a/src/e_subckt.h b/src/e_subckt.h index 69fb3e0..4a7fab0 100644 --- a/src/e_subckt.h +++ b/src/e_subckt.h @@ -77,6 +77,7 @@ protected: bool tr_needs_eval()const { assert(subckt()); return subckt()->tr_needs_eval();} +public: void tr_queue_eval() {assert(subckt()); subckt()->tr_queue_eval();} bool do_tr() { assert(subckt());set_converged(subckt()->do_tr());return converged();} diff --git a/src/s_dc.cc b/src/s_dc.cc index cc5ca51..09bc9ee 100644 --- a/src/s_dc.cc +++ b/src/s_dc.cc @@ -385,6 +385,13 @@ void DCOP::sweep() set_step_cause(scUSER); _converged = false; _ever_converged = false; + for (int ii = 0; ii < _n_sweeps; ++ii) {itested(); + if (!_zap[ii]) { itested(); + }else if (_zap[ii]->is_constant()) { itested(); + CARD_LIST::card_list.q_hack(_zap[ii]); + }else{ untested(); + } + } sweep_recursive(_n_sweeps-1); _sim->pop_voltages(); _sim->keep_voltages(); @@ -442,6 +449,11 @@ void DCOP::sweep_recursive(int Nest) incomplete(); } }else{ // leaf + for (int ii = 0; ii < _n_sweeps; ++ii) { + if (_zap[ii]) { + _zap[ii]->do_tr(); + } + } _converged = solve_with_homotopy(itl,_trace); _ever_converged |= _converged; ++::status.hidden_steps; @@ -543,9 +555,13 @@ void DCOP::first(int Nest) _val_by_user_request[Nest] = _start[Nest]; _sweepdamp[Nest] = 1; - if (ELEMENT* c = dynamic_cast(_zap[Nest])) { - c->set_constant(false); // because of extra precalc_last - // obsolete, once pointer hack is fixed + if (ELEMENT* c = dynamic_cast(_zap[Nest])) { itested(); + // because of extra precalc_last + // obsolete, once pointer hack is fixed + c->set_constant(false); + trace1("zapq", _zap[Nest]->long_label()); +// CARD_LIST::card_list.q_hack(_zap[Nest]); + }else{ untested(); } _reverse[Nest] = false; if (_reverse_in[Nest]) { diff --git a/src/u_opt.h b/src/u_opt.h index 7d24e3d..0e56c7f 100644 --- a/src/u_opt.h +++ b/src/u_opt.h @@ -156,6 +156,7 @@ public: static smode_t mode; // mixed-mode mode preference static int transits; // number of good transitions for digital static bool dupcheck; // check for duplicates on read + static bool prequeue; // prequeue model evaluation static bool bypass; // bypass model evaluation, if appropriate static bool incmode; // make incremental changes to the matrix static bool lcbypass; // bypass L and C evaluation when appropriate diff --git a/src/u_sim_data.h b/src/u_sim_data.h index 4de18d4..fa37964 100644 --- a/src/u_sim_data.h +++ b/src/u_sim_data.h @@ -137,6 +137,7 @@ public: std::vector _loadq; std::vector _acceptq; std::vector _tt_acceptq; + std::deque _pre_evalq; /* candidates for evaluation */ std::deque _evalq1; /* evaluate queues -- alternate between */ std::deque _evalq2; /* build one while other is processed */ std::deque _late_evalq; /* eval after everything else */