viminfo
[gnucap-felix.git] / lib / e_cardlist.cc
blobb079d91aa8b99dd3b59c5aef2920eb6f33061e00
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)
10 * any later version.
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
20 * 02110-1301, USA.
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"
27 #include "e_node.h"
28 #include "u_nodemap.h"
29 #include "e_model.h"
30 /*--------------------------------------------------------------------------*/
31 #define trace_func_comp() trace0((__func__ + (":" + (**ci).long_label())).c_str())
32 /*--------------------------------------------------------------------------*/
33 CARD_LIST::CARD_LIST()
34 :_parent(NULL),
35 _nm(new NODE_MAP),
36 _params(NULL)
39 /*--------------------------------------------------------------------------*/
40 CARD_LIST::CARD_LIST(const CARD* model, CARD* owner,
41 const CARD_LIST* scope, PARAM_LIST* p)
42 :_parent(NULL),
43 _nm(new NODE_MAP),
44 _params(NULL)
46 assert(model);
47 assert(model->subckt());
48 assert(owner);
49 assert(!p || scope);
51 attach_params(p, scope);
52 shallow_copy(model->subckt());
53 set_owner(owner);
54 map_subckt_nodes(model, owner);
56 /*--------------------------------------------------------------------------*/
57 CARD_LIST::~CARD_LIST()
59 erase_all();
60 delete _nm;
61 if (!_parent) {
62 delete _params;
63 }else{
66 /*--------------------------------------------------------------------------*/
67 PARAM_LIST* CARD_LIST::params()
69 if (!_params) {
70 assert(!_parent);
71 _params = new PARAM_LIST;
72 }else{
74 return _params;
76 /*--------------------------------------------------------------------------*/
77 PARAM_LIST* CARD_LIST::params()const
79 if (_params) {
80 return _params;
81 }else{ //BUG//const
82 static PARAM_LIST empty_params;
83 return &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)
101 assert(ci != end());
102 delete *ci;
103 _cl.erase(ci);
104 return *this;
106 /*--------------------------------------------------------------------------*/
107 CARD_LIST& CARD_LIST::erase(CARD* c)
109 delete c;
110 _cl.remove(c);
111 return *this;
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()) {
120 delete _cl.back();
121 _cl.pop_back();
123 return *this;
125 /*--------------------------------------------------------------------------*/
126 CARD_LIST& CARD_LIST::set_owner(CARD* owner)
128 for (iterator ci=begin(); ci!=end(); ++ci) {
129 trace_func_comp();
130 (**ci).set_owner(owner);
132 return *this;
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) {
141 trace_func_comp();
142 (**ci).set_slave();
144 return *this;
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) {
154 trace_func_comp();
155 (**ci).precalc_first();
157 for (iterator ci=begin(); ci!=end(); ++ci) {
158 trace_func_comp();
159 (**ci).expand_first();
161 for (iterator ci=begin(); ci!=end(); ++ci) {
162 trace_func_comp();
163 (**ci).expand();
165 for (iterator ci=begin(); ci!=end(); ++ci) {
166 trace_func_comp();
167 (**ci).expand_last();
169 return *this;
171 /*--------------------------------------------------------------------------*/
172 CARD_LIST& CARD_LIST::precalc_first()
174 for (iterator ci=begin(); ci!=end(); ++ci) {
175 trace_func_comp();
176 (**ci).precalc_first();
178 return *this;
180 /*--------------------------------------------------------------------------*/
181 CARD_LIST& CARD_LIST::precalc_last()
183 for (iterator ci=begin(); ci!=end(); ++ci) {
184 trace_func_comp();
185 (**ci).precalc_last();
187 return *this;
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) {
195 trace_func_comp();
196 (**ci).map_nodes();
198 return *this;
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) {
207 trace_func_comp();
208 (**ci).tr_iwant_matrix();
210 return *this;
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) {
218 trace_func_comp();
219 (**ci).tr_begin();
221 return *this;
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) {
229 trace_func_comp();
230 (**ci).tr_restore();
232 return *this;
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) {
240 trace_func_comp();
241 (**ci).dc_advance();
243 return *this;
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) {
251 trace_func_comp();
252 (**ci).tr_advance();
254 return *this;
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) {
262 trace_func_comp();
263 (**ci).tr_regress();
265 return *this;
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) {
273 trace_func_comp();
274 if ((**ci).tr_needs_eval()) {
275 return true;
276 }else{itested();
279 untested();
280 return false;
282 /*--------------------------------------------------------------------------*/
283 /* tr_queue_eval: build evaluator queue
285 CARD_LIST& CARD_LIST::tr_queue_eval()
287 for (iterator ci=begin(); ci!=end(); ++ci) {
288 trace_func_comp();
289 (**ci).tr_queue_eval();
291 return *this;
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;
303 if (OPT::bypass) {
304 for (iterator ci=begin(); ci!=end(); ++ci) {
305 trace_func_comp();
306 if ((**ci).tr_needs_eval()) {
307 isconverged &= (**ci).do_tr();
308 }else{
311 }else{
312 for (iterator ci=begin(); ci!=end(); ++ci) {
313 trace_func_comp();
314 isconverged &= (**ci).do_tr();
317 return isconverged;
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();
329 trace_func_comp();
330 CARD* brh = *ci;
331 if (!brh->is_constant()) {itested();
332 brh->tr_load();
333 }else{itested();
336 }else{
337 for (iterator ci=begin(); ci!=end(); ++ci) {
338 trace_func_comp();
339 CARD* brh = *ci;
340 brh->tr_load();
343 return *this;
345 /*--------------------------------------------------------------------------*/
346 TIME_PAIR CARD_LIST::tr_review()
348 TIME_PAIR time_by;
349 for (iterator ci=begin(); ci!=end(); ++ci) {
350 trace_func_comp();
351 time_by.min((**ci).tr_review());
353 return time_by;
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) {
361 trace_func_comp();
362 (**ci).tr_accept();
364 return *this;
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) {
373 trace_func_comp();
374 (**ci).tr_unload();
376 return *this;
378 /*--------------------------------------------------------------------------*/
379 /* ac_iwant_matrix: allocate solution matrix
381 CARD_LIST& CARD_LIST::ac_iwant_matrix()
383 for (iterator ci=begin(); ci!=end(); ++ci) {
384 trace_func_comp();
385 (**ci).ac_iwant_matrix();
387 return *this;
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) {
395 trace_func_comp();
396 (**ci).ac_begin();
398 return *this;
400 /*--------------------------------------------------------------------------*/
401 CARD_LIST& CARD_LIST::do_ac()
403 for (iterator ci=begin(); ci!=end(); ++ci) {
404 trace_func_comp();
405 if (!(**ci).evaluated()) {
406 (**ci).do_ac();
407 }else{
410 return *this;
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) {
419 trace_func_comp();
420 (**ci).ac_load();
422 return *this;
424 /*--------------------------------------------------------------------------*/
425 void CARD_LIST::attach_params(PARAM_LIST* p, const CARD_LIST* scope)
427 if (p) {
428 assert(scope);
429 if (_params) {
430 delete _params;
431 _params = NULL;
432 }else{
434 _params = new PARAM_LIST;
435 _params->eval_copy(*p, scope);
436 }else{
439 /*--------------------------------------------------------------------------*/
440 void CARD_LIST::shallow_copy(const CARD_LIST* p)
442 assert(p);
443 _parent = p;
444 for (const_iterator ci = p->begin(); ci != p->end(); ++ci) {
445 trace_func_comp();
446 if ((**ci).is_device() || dynamic_cast<MODEL_CARD*>(*ci)) {
447 CARD* copy = (**ci).clone();
448 push_back(copy);
449 }else{
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)
457 assert(model);
458 assert(model->subckt());
459 assert(model->subckt()->nodes());
460 assert(owner);
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];
469 map[0] = 0;
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
479 int i=0;
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);
508 }else{
509 assert(dynamic_cast<MODEL_CARD*>(*ci));
513 /*--------------------------------------------------------------------------*/
514 /*--------------------------------------------------------------------------*/
515 // vim:ts=8:sw=2:noet: