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