2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
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)
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.
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
21 *------------------------------------------------------------------
22 * logic model and device.
24 * device: mxxxx out gnd vdd in1 in2 ... family gatetype
25 * model: .model mname LOGIC <args>
27 //testing=script,sparse 2006.07.17
32 /*--------------------------------------------------------------------------*/
33 int DEV_LOGIC::_count
= -1;
34 int COMMON_LOGIC::_count
= -1;
35 int MODEL_LOGIC::_count
= -1; // there is one in e_node.cc, and the dispatcher
36 static LOGIC_NONE
Default_LOGIC(CC_STATIC
);
37 /*--------------------------------------------------------------------------*/
39 static DISPATCHER
<CARD
>::INSTALL
40 d1(&device_dispatcher
, "U|logic", &p1
);
41 /*--------------------------------------------------------------------------*/
42 static MODEL_LOGIC
p2(&p1
);
43 static DISPATCHER
<MODEL_CARD
>::INSTALL
44 d2(&model_dispatcher
, "logic", &p2
);
45 /*--------------------------------------------------------------------------*/
46 DEV_LOGIC::DEV_LOGIC()
51 _oldgatemode(moUNKNOWN
),
54 attach_common(&Default_LOGIC
);
58 /*--------------------------------------------------------------------------*/
59 DEV_LOGIC::DEV_LOGIC(const DEV_LOGIC
& p
)
64 _oldgatemode(moUNKNOWN
),
67 assert(max_nodes() == PORTS_PER_GATE
);
68 for (uint_t ii
= 0; ii
< max_nodes(); ++ii
) {
69 nodes
[ii
] = p
.nodes
[ii
];
74 /*--------------------------------------------------------------------------*/
75 void DEV_LOGIC::expand()
78 const COMMON_LOGIC
* c
= prechecked_cast
<const COMMON_LOGIC
*>(common());
83 const MODEL_LOGIC
* m
= dynamic_cast<const MODEL_LOGIC
*>(c
->model());
85 throw Exception_Model_Type_Mismatch(long_label(), c
->modelname(), "logic family (LOGIC)");
89 std::string
subckt_name(c
->modelname()+c
->name()+::to_string(c
->incount
));
91 const CARD
* model
= find_looking_out(subckt_name
);
93 if(!dynamic_cast<const BASE_SUBCKT
*>(model
)) {untested();
94 error(((!_sim
->is_first_expand()) ? (bDEBUG
) : (bWARNING
)),
95 long_label() + ": " + subckt_name
+ " is not a subckt, forcing digital\n");
97 _gatemode
= OPT::mode
;
98 renew_subckt(model
, scope()->params());
101 }catch (Exception_Cant_Find
&) {
102 error(((!_sim
->is_first_expand()) ? (bDEBUG
) : (bWARNING
)),
103 long_label() + ": can't find subckt: \"" + subckt_name
+ "\", forcing digital\n");
106 assert(!is_constant()); /* is a BUG */
108 /*--------------------------------------------------------------------------*/
109 void DEV_LOGIC::tr_iwant_matrix()
112 subckt()->tr_iwant_matrix();
115 tr_iwant_matrix_passive();
117 /*--------------------------------------------------------------------------*/
118 void DEV_LOGIC::tr_begin()
122 _gatemode
= moDIGITAL
;
123 _n
[OUTNODE
]->set_mode(_gatemode
);
124 _oldgatemode
= _gatemode
;
126 _gatemode
= (OPT::mode
==moMIXED
) ? moANALOG
: OPT::mode
;
127 _n
[OUTNODE
]->set_mode(_gatemode
);
128 _oldgatemode
= _gatemode
;
129 subckt()->tr_begin();
132 /*--------------------------------------------------------------------------*/
133 void DEV_LOGIC::tr_restore()
135 ELEMENT::tr_restore();
136 if (!subckt()) {untested();
137 _gatemode
= moDIGITAL
;
139 _gatemode
= (OPT::mode
==moMIXED
) ? moANALOG
: OPT::mode
;
140 subckt()->tr_restore();
143 /*--------------------------------------------------------------------------*/
144 void DEV_LOGIC::dc_advance()
146 ELEMENT::dc_advance();
148 if (_gatemode
!= _oldgatemode
) {untested();
150 _n
[OUTNODE
]->set_mode(_gatemode
);
151 _oldgatemode
= _gatemode
;
155 case moUNKNOWN
: unreachable(); break;
156 case moMIXED
: unreachable(); break;
159 subckt()->dc_advance();
162 if (_n
[OUTNODE
]->in_transit()) {
163 //q_eval(); evalq is not used for DC
164 _n
[OUTNODE
]->propagate();
170 /*--------------------------------------------------------------------------*/
171 /* tr_advance: the first to run on a new time step.
172 * It sets up preconditions for the new time.
174 void DEV_LOGIC::tr_advance()
176 ELEMENT::tr_advance();
178 if (_gatemode
!= _oldgatemode
) {
180 _n
[OUTNODE
]->set_mode(_gatemode
);
181 _oldgatemode
= _gatemode
;
185 case moUNKNOWN
: unreachable(); break;
186 case moMIXED
: unreachable(); break;
189 subckt()->tr_advance();
192 if (_n
[OUTNODE
]->in_transit() || _n
[OUTNODE
]->final_time_a() < NEVER
) {
194 if (_sim
->_time0
>= _n
[OUTNODE
]->final_time()) {
195 _n
[OUTNODE
]->propagate();
196 }else{ // untested();
198 } else if ( _n
[OUTNODE
]->final_time_a() < NEVER
) { untested();
204 void DEV_LOGIC::tr_regress()
206 ELEMENT::tr_regress();
208 if (_gatemode
!= _oldgatemode
) {itested();
210 _n
[OUTNODE
]->set_mode(_gatemode
);
211 _oldgatemode
= _gatemode
;
215 case moUNKNOWN
: unreachable(); break;
216 case moMIXED
: unreachable(); break;
217 case moANALOG
: itested();
219 subckt()->tr_regress();
221 case moDIGITAL
: itested();
222 if (_n
[OUTNODE
]->in_transit()) {itested();
224 if (_sim
->_time0
>= _n
[OUTNODE
]->final_time()) {itested();
225 _n
[OUTNODE
]->propagate();
233 /*--------------------------------------------------------------------------*/
235 * in digital mode ... DC always returns true, to queue it.
236 * tran always returns false, already queued by tr_advance if needed
238 bool DEV_LOGIC::tr_needs_eval()const
241 case moUNKNOWN
: unreachable(); break;
242 case moMIXED
: unreachable(); break;
244 //assert(!is_q_for_eval());
245 if (_sim
->analysis_is_restore()) {untested();
246 }else if (_sim
->analysis_is_static()) {
249 return (_sim
->analysis_is_static() || _sim
->analysis_is_restore());
252 assert(!is_q_for_eval());
254 return subckt()->tr_needs_eval();
259 /*--------------------------------------------------------------------------*/
260 void DEV_LOGIC::tr_queue_eval()
263 case moUNKNOWN
: unreachable(); break;
264 case moMIXED
: unreachable(); break;
265 case moDIGITAL
: ELEMENT::tr_queue_eval(); break;
266 case moANALOG
: assert(subckt()); subckt()->tr_queue_eval(); break;
269 /*--------------------------------------------------------------------------*/
270 bool DEV_LOGIC::tr_eval_digital()
272 assert(_gatemode
== moDIGITAL
);
273 if (_sim
->analysis_is_restore()) {untested();
274 }else if (_sim
->analysis_is_static()) {
277 if (_sim
->analysis_is_static() || _sim
->analysis_is_restore()) {
280 assert(_sim
->analysis_is_tran_dynamic());
283 const COMMON_LOGIC
* c
= prechecked_cast
<const COMMON_LOGIC
*>(common());
285 const MODEL_LOGIC
* m
= prechecked_cast
<const MODEL_LOGIC
*>(c
->model());
288 _y
[0].f1
= _n
[OUTNODE
]->to_analog(m
);
292 _m0
.c0
= _y
[0].f1
/ -m
->rs
;
293 set_converged(conv_check());
297 trace1(long_label(), _y
[0].f1
);
300 /*--------------------------------------------------------------------------*/
301 bool DEV_LOGIC::do_tr()
304 case moUNKNOWN
: unreachable(); break;
305 case moMIXED
: unreachable(); break;
306 case moDIGITAL
: set_converged(tr_eval_digital()); break;
307 case moANALOG
: assert(subckt()); set_converged(subckt()->do_tr()); break;
311 /*--------------------------------------------------------------------------*/
312 void DEV_LOGIC::tt_advance()
315 subckt()->tt_advance();
316 ELEMENT::tt_advance();
318 /*--------------------------------------------------------------------------*/
319 void DEV_LOGIC::tr_load()
322 case moUNKNOWN
: unreachable(); break;
323 case moMIXED
: unreachable(); break;
324 case moDIGITAL
: tr_load_passive(); break;
325 case moANALOG
: assert(subckt()); subckt()->tr_load(); break;
328 /*--------------------------------------------------------------------------*/
329 TIME_PAIR
DEV_LOGIC::tr_review()
331 // not calling ELEMENT::tr_review();
334 //digital mode queues events explicitly in tr_accept
337 case moUNKNOWN
: unreachable(); break;
338 case moMIXED
: unreachable(); break;
339 case moDIGITAL
: _time_by
.reset(); break;
340 case moANALOG
: assert(subckt()); _time_by
= subckt()->tr_review(); break;
344 /*--------------------------------------------------------------------------*/
345 /* tr_accept: This runs after everything has passed "review".
346 * It sets up and queues transitions, and sometimes determines logic states.
348 void DEV_LOGIC::tr_accept()
350 assert(_gatemode
== moDIGITAL
|| _gatemode
== moANALOG
);
351 const COMMON_LOGIC
* c
= prechecked_cast
<const COMMON_LOGIC
*>(common());
353 const MODEL_LOGIC
* m
= prechecked_cast
<const MODEL_LOGIC
*>(c
->model());
357 if(_sim
->_time0
<= _tr_last_acc
) {
359 error(bWARNING
, "tr accepting twice %s time0 %E\n", long_label().c_str(), _sim
->_time0
);
364 _tr_last_acc
= _sim
->_time0
;
366 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
367 /* Check quality and get node info to local array. */
368 /* side effect --- generate digital values for analog nodes */
369 assert(PORTS_PER_GATE
== max_nodes());
371 _n
[OUTNODE
]->to_logic(m
);
372 _quality
= _n
[OUTNODE
]->quality(); /* the worst quality on this device */
373 _failuremode
= _n
[OUTNODE
]->failure_mode(); /* what is wrong with it? */
374 _lastchangenode
= OUTNODE
; /* which node changed most recently */
375 int lastchangeiter
=_n
[OUTNODE
]->d_iter();/* iteration # when it changed */
376 trace1("DEV_LOGIC::tr_accept", long_label());
377 trace3("DEV_LOGIC::tr_accept", _n
[OUTNODE
]->failure_mode(), OUTNODE
, _n
[OUTNODE
]->quality());
379 for (uint_t ii
= BEGIN_IN
; ii
< net_nodes(); ++ii
) {
381 if (_n
[ii
]->quality() < _quality
) {
382 _quality
= _n
[ii
]->quality();
383 _failuremode
= _n
[ii
]->failure_mode();
386 if (_n
[ii
]->d_iter() >= lastchangeiter
) {
387 lastchangeiter
= _n
[ii
]->d_iter();
388 _lastchangenode
= ii
;
391 trace2(_n
[ii
]->failure_mode().c_str(), ii
, _n
[ii
]->quality());
393 /* If _lastchangenode == OUTNODE, no new changes, bypass may be ok.
394 * Otherwise, an input changed. Need to evaluate.
395 * If all quality are good, can evaluate as digital.
396 * Otherwise need to evaluate as analog.
398 trace4("DEV_LOGIC::tr_accept", _failuremode
, _lastchangenode
, lastchangeiter
, _quality
);
400 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
402 if (_gatemode
== moDIGITAL
) {untested();
403 error(bTRACE
, "%s:%u:%g switch to analog, %s\n", long_label().c_str(),
404 _sim
->iteration_tag(), _sim
->_time0
, _failuremode
.c_str());
405 _oldgatemode
= _gatemode
;
406 _gatemode
= moANALOG
;
409 assert(_gatemode
== moANALOG
);
411 assert(want_digital());
412 if (_gatemode
== moANALOG
) {
413 error(bTRACE
, "%s:%u:%g switch to digital\n",
414 long_label().c_str(), _sim
->iteration_tag(), _sim
->_time0
);
415 _oldgatemode
= _gatemode
;
416 _gatemode
= moDIGITAL
;
419 assert(_gatemode
== moDIGITAL
);
420 if (_sim
->analysis_is_restore()) {untested();
421 }else if (_sim
->analysis_is_static()) {
424 if (!_sim
->_bypass_ok
425 || _lastchangenode
!= OUTNODE
426 || _sim
->analysis_is_static()
427 || _sim
->analysis_is_restore()) {
429 LOGICVAL future_state
= c
->logic_eval(&_n
[BEGIN_IN
]);
431 trace6("hmmm0", long_label(), _sim
->_bypass_ok
, _lastchangenode
!= OUTNODE
,
432 _sim
->analysis_is_static(), _sim
->analysis_is_restore(), future_state
);
433 if ((_n
[OUTNODE
]->is_unknown()) &&
434 (_sim
->analysis_is_static() || _sim
->analysis_is_restore())) {
435 _n
[OUTNODE
]->force_initial_value(future_state
);
436 /* This happens when initial DC is digital.
437 * Answers could be wrong if order in netlist is reversed
439 }else if (future_state
!= _n
[OUTNODE
]->lv()) {
440 // assert(future_state != lvUNKNOWN);
441 switch (future_state
) {
442 case lvSTABLE0
: /*nothing*/ break;
443 case lvRISING
: future_state
=lvSTABLE0
; break;
444 case lvFALLING
: future_state
=lvSTABLE1
; break;
445 case lvSTABLE1
: /*nothing*/ break;
446 case lvUNKNOWN
: unreachable(); future_state
=lvSTABLE1
; break;
448 /* This handling of rising and falling may seem backwards.
449 * These states occur when the value has been contaminated
450 * by another pending action. The "old" value is the
451 * value without this contamination.
452 * This code is planned for replacement as part of VHDL/Verilog
453 * conversion, so the kluge stays in for now.
455 assert(future_state
.lv_old() == future_state
.lv_future());
456 if (_n
[OUTNODE
]->lv() == lvUNKNOWN
457 || future_state
.lv_future() != _n
[OUTNODE
]->lv_future()) {
458 trace5( "hmmm", future_state
, long_label(), _n
[OUTNODE
]->lv(),
459 _n
[BEGIN_IN
]->lv(), _n
[BEGIN_IN
]->lv_future());
460 if (_sim
->analysis_is_static()) {
461 _n
[OUTNODE
]->set_event(-1e99
, future_state
);
463 _n
[OUTNODE
]->set_event(m
->delay
, future_state
);
465 _sim
->new_event(_n
[OUTNODE
]->final_time());
466 //assert(future_state == _n[OUTNODE].lv_future());
467 if (_lastchangenode
== OUTNODE
) {
469 error(bDANGER
, "%s:%u:%g non-event state change: failuremode: %s\n",
470 long_label().c_str(), _sim
->iteration_tag(), _sim
->_time0
, _failuremode
.c_str());
481 /*--------------------------------------------------------------------------*/
482 void DEV_LOGIC::tr_unload()
485 subckt()->tr_unload();
490 /*--------------------------------------------------------------------------*/
491 void DEV_LOGIC::ac_iwant_matrix()
494 subckt()->ac_iwant_matrix();
498 /*--------------------------------------------------------------------------*/
499 void DEV_LOGIC::ac_begin()
501 if (subckt()) {untested();
502 subckt()->ac_begin();
504 error(bWARNING
, long_label() + ": no logic in AC analysis\n");
507 /*--------------------------------------------------------------------------*/
508 double DEV_LOGIC::tr_probe_num(const std::string
& what
)const
510 return _n
[OUTNODE
]->tr_probe_num(what
);
512 /*--------------------------------------------------------------------------*/
513 XPROBE
DEV_LOGIC::ac_probe_ext(const std::string
& what
)const
515 return _n
[OUTNODE
]->ac_probe_ext(what
);
517 /*--------------------------------------------------------------------------*/
518 bool DEV_LOGIC::want_analog()const
521 ((OPT::mode
== moANALOG
) || (OPT::mode
== moMIXED
&& _quality
!= qGOOD
));
523 /*--------------------------------------------------------------------------*/
524 bool DEV_LOGIC::want_digital()const
527 ((OPT::mode
== moDIGITAL
) || (OPT::mode
== moMIXED
&& _quality
== qGOOD
));
529 /*--------------------------------------------------------------------------*/
530 bool COMMON_LOGIC::operator==(const COMMON_COMPONENT
& x
)const
532 const COMMON_LOGIC
* p
= dynamic_cast<const COMMON_LOGIC
*>(&x
);
534 && incount
== p
->incount
535 && COMMON_COMPONENT::operator==(x
);
541 /*--------------------------------------------------------------------------*/
542 /*--------------------------------------------------------------------------*/
543 // vim:ts=8:sw=2:noet: