1 /*$Id: e_node.h,v 26.133 2009/11/26 04:58:04 al Exp $ -*- C++ -*- 2 * Copyright (C) 2001 Albert Davis 3 * Author: Albert Davis <aldavis@gnu.org> 4 * 5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 * 02110-1301, USA. 21 *------------------------------------------------------------------ 22 * circuit node class 23 */ 24 //testing=script,sparse 2006.07.11 25 #ifndef E_NODE_H 26 #define E_NODE_H 27 #include "u_sim_data.h" 28 #include "e_base.h" 29 /*--------------------------------------------------------------------------*/ 30 class MODEL_LOGIC; 31 /*--------------------------------------------------------------------------*/ 32 enum { 33 OUT1 = 0, 34 OUT2 = 1, 35 IN1 = 2, 36 IN2 = 3, 37 NODES_PER_BRANCH = 4, 38 INVALID_NODE = -1 39 }; 40 #define qBAD (0) 41 #define qGOOD (OPT::transits) 42 /*--------------------------------------------------------------------------*/ 43 enum _LOGICVAL {lvSTABLE0,lvRISING,lvFALLING,lvSTABLE1,lvUNKNOWN}; 44 enum {lvNUM_STATES = lvUNKNOWN+1}; 45 /*--------------------------------------------------------------------------*/ 46 class INTERFACE LOGICVAL { 47 private: 48 _LOGICVAL _lv; 49 static const _LOGICVAL or_truth[lvNUM_STATES][lvNUM_STATES]; 50 static const _LOGICVAL xor_truth[lvNUM_STATES][lvNUM_STATES]; 51 static const _LOGICVAL and_truth[lvNUM_STATES][lvNUM_STATES]; 52 static const _LOGICVAL not_truth[lvNUM_STATES]; 53 public: LOGICVAL()54 LOGICVAL() :_lv(lvUNKNOWN) {} LOGICVAL(const LOGICVAL & p)55 LOGICVAL(const LOGICVAL& p) :_lv(p._lv) {} LOGICVAL(_LOGICVAL p)56 LOGICVAL(_LOGICVAL p) :_lv(p) {} ~LOGICVAL()57 ~LOGICVAL() {} 58 _LOGICVAL()59 operator _LOGICVAL()const {return static_cast<_LOGICVAL>(_lv);} 60 61 LOGICVAL& operator=(_LOGICVAL p) {_lv=p; return *this;} 62 LOGICVAL& operator=(const LOGICVAL& p) {_lv=p._lv; return *this;} 63 64 LOGICVAL& operator&=(LOGICVAL p) 65 {untested(); _lv = and_truth[_lv][p._lv]; return *this;} 66 LOGICVAL& operator|=(LOGICVAL p) 67 {_lv = or_truth[_lv][p._lv]; return *this;} 68 LOGICVAL operator^=(LOGICVAL p) 69 {untested(); _lv = xor_truth[_lv][p._lv]; return *this;} 70 LOGICVAL operator~()const {return not_truth[_lv];} 71 is_unknown()72 bool is_unknown()const {return _lv == lvUNKNOWN;} lv_future()73 bool lv_future()const {assert(_lv!=lvUNKNOWN); return _lv & 1;} lv_old()74 bool lv_old()const {assert(_lv!=lvUNKNOWN); return _lv & 2;} 75 is_rising()76 bool is_rising() const {return _lv == lvRISING;} is_falling()77 bool is_falling()const {return _lv == lvFALLING;} 78 79 LOGICVAL& set_in_transition(LOGICVAL newval); 80 }; 81 /*--------------------------------------------------------------------------*/ 82 class NODE : public CKT_BASE { 83 private: 84 int _user_number; 85 //int _flat_number; 86 //int _matrix_number; 87 protected: 88 explicit NODE(); 89 private: // inhibited 90 explicit NODE(const NODE& p); 91 public: 92 explicit NODE(const NODE* p); // u_nodemap.cc:49 (deep copy) 93 explicit NODE(const std::string& s, int n); ~NODE()94 ~NODE() {} 95 96 public: // raw data access (rvalues) user_number()97 int user_number()const {return _user_number;} 98 //int flat_number()const {itested();return _flat_number;} 99 public: // simple calculated data access (rvalues) matrix_number()100 int matrix_number()const {return _sim->_nm[_user_number];} m_()101 int m_()const {return matrix_number();} 102 public: // maniputation set_user_number(int n)103 NODE& set_user_number(int n) {_user_number = n; return *this;} 104 //NODE& set_flat_number(int n) {itested();_flat_number = n; return *this;} 105 //NODE& set_matrix_number(int n){untested();_matrix_number = n;return *this;} 106 public: // virtuals 107 double tr_probe_num(const std::string&)const; 108 XPROBE ac_probe_ext(const std::string&)const; 109 v0()110 double v0()const { 111 assert(m_() >= 0); 112 assert(m_() <= _sim->_total_nodes); 113 return _sim->_v0[m_()]; 114 } vt1()115 double vt1()const { 116 assert(m_() >= 0); 117 assert(m_() <= _sim->_total_nodes); 118 return _sim->_vt1[m_()]; 119 } vac()120 COMPLEX vac()const { 121 assert(m_() >= 0); 122 assert(m_() <= _sim->_total_nodes); 123 return _sim->_ac[m_()]; 124 } 125 //double vdc()const {untested();return _vdc[m_()];} 126 127 //double& i() {untested();return _i[m_()];} /* lvalues */ iac()128 COMPLEX& iac() { 129 assert(m_() >= 0); 130 assert(m_() <= _sim->_total_nodes); 131 return _sim->_ac[m_()]; 132 } 133 }; 134 extern NODE ground_node; 135 /*--------------------------------------------------------------------------*/ 136 class INTERFACE LOGIC_NODE : public NODE { 137 private: 138 const MODEL_LOGIC *_family; /* logic family */ 139 int _d_iter; /* iteration of last update - digital */ 140 int _a_iter; /* iteration of last update - analog */ 141 double _final_time; /* time logic transition attains final state */ 142 double _lastchange; /* time of last change */ 143 double _old_lastchange; /* in case it rejects a step */ 144 smode_t _mode; /* simulation mode (analog or digital)*/ 145 LOGICVAL _lv; /* "logic value" (real type is LOGICVAL) */ 146 LOGICVAL _old_lv; /* in case it rejects a step */ 147 int _quality; /* quality of digital mode */ 148 std::string _failure_mode; 149 150 // so it is not pure virtual 151 //const std::string long_label()const; 152 public: // virtuals 153 double tr_probe_num(const std::string&)const; 154 //XPROBE ac_probe_ext(const std::string&)const; 155 156 public: // raw data access (rvalues) lv()157 LOGICVAL lv()const {return _lv;} quality()158 int quality()const {return _quality;} failure_mode()159 const std::string& failure_mode()const {return _failure_mode;} d_iter()160 int d_iter()const {return _d_iter;} a_iter()161 int a_iter()const {return _a_iter;} final_time()162 double final_time()const {return _final_time;} last_change_time()163 double last_change_time()const {return _lastchange;} process()164 const MODEL_LOGIC* process()const {return _family;} old_last_change_time()165 double old_last_change_time()const {untested(); return _old_lastchange;} old_lv()166 const LOGICVAL old_lv()const {return _old_lv;} 167 168 public: // simple calculated data access (rvalues) lv_future()169 bool lv_future()const {return lv().lv_future();} is_unknown()170 bool is_unknown()const {return lv().is_unknown();} in_transit()171 bool in_transit()const {return final_time() < NEVER;} is_digital()172 bool is_digital()const {return _mode == moDIGITAL;} is_analog()173 bool is_analog()const {return _mode == moANALOG;} 174 double annotated_logic_value()const; 175 176 public: // calculated data access (rvalues) 177 bool just_reached_stable()const; 178 179 public: // raw data access (lvalues) set_quality(int q)180 void set_quality(int q) {_quality = q;} set_failure_mode(const std::string & f)181 void set_failure_mode(const std::string& f) {_failure_mode = f;} set_final_time(double t)182 void set_final_time(double t) {_final_time = t;} 183 set_d_iter()184 void set_d_iter() {_d_iter = _sim->iteration_tag();} set_last_change_time()185 void set_last_change_time() {_lastchange = _sim->_time0;} set_last_change_time(double t)186 void set_last_change_time(double t) {_lastchange = t;} set_lv(LOGICVAL v)187 void set_lv(LOGICVAL v) {_lv = v;} set_process(const MODEL_LOGIC * f)188 void set_process(const MODEL_LOGIC* f) {_family = f;} 189 store_old_last_change_time()190 void store_old_last_change_time() {_old_lastchange = last_change_time();} store_old_lv()191 void store_old_lv() {_old_lv = lv();} restore_lv()192 void restore_lv() {untested(); set_lv(old_lv());} set_mode(smode_t m)193 void set_mode(smode_t m) {_mode = m;} 194 195 public: // other internal set_bad_quality(const std::string & f)196 void set_bad_quality(const std::string& f) { 197 set_quality(qBAD); 198 set_failure_mode(f); 199 } 200 void set_good_quality(const std::string& f = "ok") { 201 set_quality(qGOOD); 202 set_failure_mode(f); 203 } 204 void dont_set_quality(const std::string& f = "don't know") { 205 set_failure_mode(f); 206 } improve_quality()207 void improve_quality() { 208 if (quality() < qGOOD) { 209 ++_quality; 210 } 211 } 212 213 public: // action, used by logic 214 void set_event(double delay, LOGICVAL v); 215 void force_initial_value(LOGICVAL v); 216 void propagate(); 217 double to_analog(const MODEL_LOGIC*f); 218 void to_logic(const MODEL_LOGIC*f); 219 220 private: // inhibited LOGIC_NODE(const LOGIC_NODE &)221 explicit LOGIC_NODE(const LOGIC_NODE&):NODE(){incomplete();unreachable();} 222 public: // general use 223 explicit LOGIC_NODE(); ~LOGIC_NODE()224 ~LOGIC_NODE() {} 225 226 public: // matrix set_a_iter()227 LOGIC_NODE& set_a_iter() {_a_iter = _sim->iteration_tag(); return *this;} 228 }; 229 /*--------------------------------------------------------------------------*/ 230 class INTERFACE node_t { 231 private: node_is_valid(int i)232 static bool node_is_valid(int i) { 233 if (i == INVALID_NODE) {untested(); 234 itested(); 235 }else if (i < 0) { 236 unreachable(); 237 }else if (i > NODE::_sim->_total_nodes) { 238 unreachable(); 239 }else{ 240 } 241 return i>=0 && i<=NODE::_sim->_total_nodes; 242 } to_internal(int n)243 static int to_internal(int n) { 244 assert(node_is_valid(n)); 245 assert(NODE::_sim->_nm); 246 return NODE::_sim->_nm[n]; 247 } 248 249 private: 250 NODE* _nnn; 251 int _ttt; // m == nm[t] if properly set up 252 int _m; // mapped, after reordering 253 254 public: m_()255 int m_()const {return _m;} 256 t_()257 int t_()const { 258 //assert(_nnn); 259 //assert(_ttt == _nnn->flat_number()); 260 return _ttt; 261 } // e_cardlist.cc:CARD_LIST::map_subckt_nodes:436 and 262 // e_node.h:node_t::map:263,265 only 263 e_()264 int e_()const { 265 assert(_nnn); 266 return ((_nnn) ? _nnn->user_number() : INVALID_NODE); 267 } n_()268 const NODE* n_()const {return _nnn;} n_()269 NODE* n_() {return _nnn;} 270 271 short_label()272 const std::string short_label()const {return ((n_()) ? (n_()->short_label()) : "?????");} 273 void set_to_ground(CARD*); 274 void new_node(const std::string&, const CARD*); 275 void new_model_node(const std::string& n, CARD* d); 276 void map_subckt_node(int* map_array, const CARD* d); is_grounded()277 bool is_grounded()const {return (e_() == 0);} is_connected()278 bool is_connected()const {return (e_() != INVALID_NODE);} 279 map()280 node_t& map() { 281 if (t_() != INVALID_NODE) { 282 assert(_nnn); 283 _m=to_internal(t_()); 284 }else{ 285 assert(_m == INVALID_NODE); 286 } 287 return *this; 288 } // e_compon.cc:COMPONENT::map_nodes:522 289 290 explicit node_t(); 291 node_t(const node_t&); 292 explicit node_t(NODE*); ~node_t()293 ~node_t() {} 294 295 private: // raw data access (lvalues) 296 LOGIC_NODE& data()const; 297 298 public: 299 //LOGIC_NODE& operator*()const {untested();return data();} 300 const LOGIC_NODE* operator->()const {return &data();} 301 LOGIC_NODE* operator->() {return &data();} 302 303 node_t& operator=(const node_t& p); 304 305 bool operator==(const node_t& p) {return _nnn==p._nnn && _ttt==p._ttt && _m==p._m;} 306 307 public: v0()308 double v0()const { 309 //assert(m_() >= 0); 310 if (m_() >= 0) { 311 assert(m_() <= NODE::_sim->_total_nodes); 312 assert(n_()); 313 //assert(n_()->m_() == m_()); 314 //assert(n_()->v0() == NODE::_sim->_v0[m_()]); 315 return NODE::_sim->_v0[m_()]; 316 }else{ 317 //BUG// in BJT model: should not get here but does. 318 return 0.; 319 } 320 } 321 vac()322 COMPLEX vac()const { 323 //assert(m_() >= 0); 324 if (m_() >= 0) { 325 assert(m_() <= NODE::_sim->_total_nodes); 326 assert(n_()); 327 //assert(n_()->m_() == m_()); 328 //assert(n_()->vac() == NODE::_ac[m_()]); 329 return NODE::_sim->_ac[m_()]; 330 }else{untested(); 331 //BUG// assume v0 BUG applies here too. 332 return 0.; 333 } 334 } 335 i()336 double& i() { 337 assert(m_() >= 0); 338 assert(m_() <= NODE::_sim->_total_nodes); 339 return NODE::_sim->_i[m_()]; 340 } 341 #if 0 342 COMPLEX& iac() {untested(); 343 assert(n_()); 344 assert(n_()->m_() == m_()); 345 assert(n_()->iac() == NODE::_ac[m_()]); 346 //return n_()->iac(); 347 return NODE::_sim->_ac[m_()]; 348 } 349 #endif 350 }; 351 /*--------------------------------------------------------------------------*/ 352 INTERFACE double volts_limited(const node_t& n1, const node_t& n2); 353 /*--------------------------------------------------------------------------*/ 354 /*--------------------------------------------------------------------------*/ 355 #endif 356