1 /*$Id: e_cardlist.cc,v 26.137 2010/04/10 02:37:33 al Exp $ -*- C++ -*-
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 * Base class for "cards" in the circuit description file
23 * This file contains functions that process a list of cards
25 //testing=script 2006.07.10
26 #include "u_time_pair.h"
28 #include "u_nodemap.h"
30 /*--------------------------------------------------------------------------*/
31 #define trace_func_comp() trace0((__func__ + (":" + (**ci).long_label())).c_str())
32 /*--------------------------------------------------------------------------*/
33 CARD_LIST::CARD_LIST()
39 /*--------------------------------------------------------------------------*/
40 CARD_LIST::CARD_LIST(const CARD
* model
, CARD
* owner
,
41 const CARD_LIST
* scope
, PARAM_LIST
* p
)
47 assert(model
->subckt());
51 attach_params(p
, scope
);
52 shallow_copy(model
->subckt());
54 map_subckt_nodes(model
, owner
);
56 /*--------------------------------------------------------------------------*/
57 CARD_LIST::~CARD_LIST()
66 /*--------------------------------------------------------------------------*/
67 PARAM_LIST
* CARD_LIST::params()
71 _params
= new PARAM_LIST
;
76 /*--------------------------------------------------------------------------*/
77 PARAM_LIST
* CARD_LIST::params()const
82 static PARAM_LIST empty_params
;
86 /*--------------------------------------------------------------------------*/
87 CARD_LIST::iterator
CARD_LIST::find_again(const std::string
& short_name
,
88 CARD_LIST::iterator Begin
)
90 return notstd::find_ptr(Begin
, end(), short_name
);
92 /*--------------------------------------------------------------------------*/
93 CARD_LIST::const_iterator
CARD_LIST::find_again(const std::string
& short_name
,
94 CARD_LIST::const_iterator Begin
)const
96 return notstd::find_ptr(Begin
, end(), short_name
);
98 /*--------------------------------------------------------------------------*/
99 CARD_LIST
& CARD_LIST::erase(iterator ci
)
106 /*--------------------------------------------------------------------------*/
107 CARD_LIST
& CARD_LIST::erase(CARD
* c
)
113 /*--------------------------------------------------------------------------*/
114 /* erase_all: empty the list, destroy contents
115 * Beware: something else may be pointing to them, leaving dangling ptr.
117 CARD_LIST
& CARD_LIST::erase_all()
119 while (!_cl
.empty()) {
125 /*--------------------------------------------------------------------------*/
126 CARD_LIST
& CARD_LIST::set_owner(CARD
* owner
)
128 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
130 (**ci
).set_owner(owner
);
134 /*--------------------------------------------------------------------------*/
135 /* set_slave: set a whole circuit to "slave" mode.
136 * Only useful for subckts.
138 CARD_LIST
& CARD_LIST::set_slave()
140 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
146 /*--------------------------------------------------------------------------*/
147 /* expand: expand (flatten) a list of components (subckts)
148 * Scan component list. Expand each subckt: create actual elements
149 * for flat representation to use for simulation.
151 CARD_LIST
& CARD_LIST::expand()
153 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
155 (**ci
).precalc_first();
157 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
159 (**ci
).expand_first();
161 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
165 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
167 (**ci
).expand_last();
171 /*--------------------------------------------------------------------------*/
172 CARD_LIST
& CARD_LIST::precalc_first()
174 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
176 (**ci
).precalc_first();
180 /*--------------------------------------------------------------------------*/
181 CARD_LIST
& CARD_LIST::precalc_last()
183 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
185 (**ci
).precalc_last();
189 /*--------------------------------------------------------------------------*/
190 /* map_nodes: create mapping between user node names and internal numbers
192 CARD_LIST
& CARD_LIST::map_nodes()
194 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
200 /*--------------------------------------------------------------------------*/
201 /* tr_iwant_matrix: allocate solution matrix
202 * also sets some flags for mixed-mode
204 CARD_LIST
& CARD_LIST::tr_iwant_matrix()
206 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
208 (**ci
).tr_iwant_matrix();
212 /*--------------------------------------------------------------------------*/
213 /* tr_begin: first pass on a new transient simulation (initial DC)
215 CARD_LIST
& CARD_LIST::tr_begin()
217 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
223 /*--------------------------------------------------------------------------*/
224 /* tr_restore: first pass on restarting a transient simulation
226 CARD_LIST
& CARD_LIST::tr_restore()
228 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
234 /*--------------------------------------------------------------------------*/
235 /* dc_advance: first pass on a new step in a dc sweep
237 CARD_LIST
& CARD_LIST::dc_advance()
239 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
245 /*--------------------------------------------------------------------------*/
246 /* tr_advance: first pass on a new time step
248 CARD_LIST
& CARD_LIST::tr_advance()
250 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
256 /*--------------------------------------------------------------------------*/
257 /* tr_regress: throw away the last result and try again, first pass on redo
259 CARD_LIST
& CARD_LIST::tr_regress()
261 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
267 /*--------------------------------------------------------------------------*/
268 /* tr_needs_eval: determine if anything needs to be evaluated
270 bool CARD_LIST::tr_needs_eval()const
272 for (const_iterator ci
=begin(); ci
!=end(); ++ci
) {
274 if ((**ci
).tr_needs_eval()) {
282 /*--------------------------------------------------------------------------*/
283 /* tr_queue_eval: build evaluator queue
285 CARD_LIST
& CARD_LIST::tr_queue_eval()
287 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
289 (**ci
).tr_queue_eval();
293 /*--------------------------------------------------------------------------*/
294 /* tr_eval: evaluate a list of models
295 * evaluates a list (or sublist), checks convergence, etc.
296 * does not load the matrix
297 * argument is the head of the netlist.
298 * recursively called to evaluate subcircuits
300 bool CARD_LIST::do_tr()
302 bool isconverged
= true;
304 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
306 if ((**ci
).tr_needs_eval()) {
307 isconverged
&= (**ci
).do_tr();
312 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
314 isconverged
&= (**ci
).do_tr();
319 /*--------------------------------------------------------------------------*/
320 /* tr_load: load list of models to the matrix
321 * recursively called to load subcircuits
322 * Called only when either !OPT::traceload or !SIM::inc_mode
324 CARD_LIST
& CARD_LIST::tr_load()
326 if (CKT_BASE::_sim
->is_inc_mode()) {itested();
327 assert(!OPT::traceload
);
328 for (iterator ci
=begin(); ci
!=end(); ++ci
) {itested();
331 if (!brh
->is_constant()) {itested();
337 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
345 /*--------------------------------------------------------------------------*/
346 TIME_PAIR
CARD_LIST::tr_review()
349 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
351 time_by
.min((**ci
).tr_review());
355 /*--------------------------------------------------------------------------*/
356 /* tr_accept: final acceptance of a time step, before moving on
358 CARD_LIST
& CARD_LIST::tr_accept()
360 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
366 /*--------------------------------------------------------------------------*/
367 /* tr_unload: remove a list of models from the matrix
368 * recursively called to unload subcircuits
370 CARD_LIST
& CARD_LIST::tr_unload()
372 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
378 /*--------------------------------------------------------------------------*/
379 /* ac_iwant_matrix: allocate solution matrix
381 CARD_LIST
& CARD_LIST::ac_iwant_matrix()
383 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
385 (**ci
).ac_iwant_matrix();
389 /*--------------------------------------------------------------------------*/
390 /* ac_begin: first pass on a new ac simulation
392 CARD_LIST
& CARD_LIST::ac_begin()
394 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
400 /*--------------------------------------------------------------------------*/
401 CARD_LIST
& CARD_LIST::do_ac()
403 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
405 if (!(**ci
).evaluated()) {
412 /*--------------------------------------------------------------------------*/
413 /* ac_load: load list of models to the matrix
414 * recursively called to load subcircuits
416 CARD_LIST
& CARD_LIST::ac_load()
418 for (iterator ci
=begin(); ci
!=end(); ++ci
) {
424 /*--------------------------------------------------------------------------*/
425 void CARD_LIST::attach_params(PARAM_LIST
* p
, const CARD_LIST
* scope
)
434 _params
= new PARAM_LIST
;
435 _params
->eval_copy(*p
, scope
);
439 /*--------------------------------------------------------------------------*/
440 void CARD_LIST::shallow_copy(const CARD_LIST
* p
)
444 for (const_iterator ci
= p
->begin(); ci
!= p
->end(); ++ci
) {
446 if ((**ci
).is_device() || dynamic_cast<MODEL_CARD
*>(*ci
)) {
447 CARD
* copy
= (**ci
).clone();
453 /*--------------------------------------------------------------------------*/
454 // set up the map of external to expanded node numbers
455 void CARD_LIST::map_subckt_nodes(const CARD
* model
, const CARD
* owner
)
458 assert(model
->subckt());
459 assert(model
->subckt()->nodes());
461 //assert(owner->subckt());
462 //assert(owner->subckt() == this);
463 trace0(model
->long_label().c_str());
464 trace0(owner
->long_label().c_str());
466 int num_nodes_in_subckt
= model
->subckt()->nodes()->how_many();
467 int* map
= new int[num_nodes_in_subckt
+1];
470 // self test: verify that port node numbering is correct
471 for (int port
= 0; port
< model
->net_nodes(); ++port
) {
472 assert(model
->n_(port
).e_() <= num_nodes_in_subckt
);
473 //assert(model->n_(port).e_() == port+1);
474 trace3("ports", port
, model
->n_(port
).e_(), owner
->n_(port
).t_());
477 // take care of the "port" nodes (external connections)
478 // map them to what the calling circuit wants
480 for (i
=1; i
<= model
->net_nodes(); ++i
) {
481 map
[i
] = owner
->n_(i
-1).t_();
482 trace3("ports", i
, map
[i
], owner
->n_(i
-1).t_());
485 // get new node numbers, and assign them to the remaining
486 for (assert(i
==model
->net_nodes() + 1); i
<= num_nodes_in_subckt
; ++i
) {
487 // for each remaining node in card_list
488 map
[i
] = CKT_BASE::_sim
->newnode_subckt();
489 trace2("internal", i
, map
[i
]);
493 // "map" now contains a translation list,
494 // from subckt local numbers to matrix index numbers
496 // The node list (_nm) in an instance of a subckt does not exist.
497 // Device nodes (type node_t) points to the NODE in the parent.
498 // Mapping is done in node_t.
500 // scan the list, map the nodes
501 for (CARD_LIST::iterator ci
= begin(); ci
!= end(); ++ci
) {
502 // for each card in card_list
503 if ((**ci
).is_device()) {
504 for (int ii
= 0; ii
< (**ci
).net_nodes(); ++ii
) {
505 // for each connection node in card
506 (**ci
).n_(ii
).map_subckt_node(map
, owner
);
509 assert(dynamic_cast<MODEL_CARD
*>(*ci
));
513 /*--------------------------------------------------------------------------*/
514 /*--------------------------------------------------------------------------*/
515 // vim:ts=8:sw=2:noet: