bump to -rc12
[gnucap-felix.git] / lib / e_card.cc
blob0145821fb78396cc1249239eb2e1530acfa52819
1 /*$Id: e_card.cc 2016/09/17 $ -*- 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
24 #include "u_time_pair.h"
25 #include "e_cardlist.h"
26 #include "e_node.h"
27 #include "e_card.h"
28 #include "e_model.h"
29 #include "d_subckt.h"
30 #include "io_misc.h"
31 /*--------------------------------------------------------------------------*/
32 const int POOLSIZE = 4;
33 /*--------------------------------------------------------------------------*/
34 CARD::CARD()
35 :CKT_BASE(),
36 _evaliter(-100),
37 _subckt(0),
38 _owner(0),
39 _constant(false),
40 _comment(""),
41 _n(0),
42 _net_nodes(0),
43 tr_behaviour_del(0),
44 tt_behaviour_del(0),
45 tr_behaviour_rel(0),
46 tt_behaviour_rel(0)
49 /*--------------------------------------------------------------------------*/
50 CARD* CARD::clone()const
52 unreachable();
53 error(bDANGER, "CARD::clone, " + dev_type() +" " + long_label()
54 + " has no clone()\n");
56 return NULL;
58 /*--------------------------------------------------------------------------*/
59 CARD::CARD(const CARD& p)
60 :CKT_BASE(p),
61 _evaliter(-100),
62 _subckt(0), //BUG// isn't this supposed to copy????
63 _owner(0),
64 _constant(p._constant),
65 _comment(p._comment),
66 _n(0),
67 _net_nodes(p._net_nodes),
68 tr_behaviour_del(0),
69 tt_behaviour_del(0),
70 tr_behaviour_rel(0),
71 tt_behaviour_rel(0)
74 /*--------------------------------------------------------------------------*/
75 CARD::~CARD()
77 delete _subckt;
79 /*--------------------------------------------------------------------------*/
80 const std::string CARD::long_label()const
82 std::string buffer(short_label());
83 for (const CARD* brh = owner(); brh; brh = brh->owner()) {
84 buffer = brh->short_label() + '.' + buffer;
86 return buffer;
88 /*--------------------------------------------------------------------------*/
89 /* connects_to: does this part connect to this node?
90 * input: a node
91 * returns: how many times this part connects to it.
92 * does not traverse subcircuits
94 int CARD::connects_to(const node_t& node)const
95 {untested();
96 int count = 0;
97 if (is_device()) {untested();
98 for (uint_t ii = 0; ii < net_nodes(); ++ii) {untested();
99 if (node.n_() == _n[ii].n_()) {untested();
100 ++count;
101 }else{untested();
104 }else{untested();
106 return count;
108 /*--------------------------------------------------------------------------*/
109 CARD_LIST* CARD::scope()
111 if (owner()) {
112 return owner()->subckt(); // normal element, owner determines scope
113 }else{
114 return &(CARD_LIST::card_list); // root circuit
117 /*--------------------------------------------------------------------------*/
118 const CARD_LIST* CARD::scope()const
120 if (owner()) {
121 return owner()->subckt(); // normal element, owner determines scope
122 }else{
123 return &(CARD_LIST::card_list); // root circuit
126 /*--------------------------------------------------------------------------*/
127 /* find_in_my_scope: find in same scope as myself
128 * whatever is found will have the same owner as me.
129 * capable of finding me.
130 * throws exception if can't find.
132 CARD* CARD::find_in_my_scope(const std::string& name)
134 assert(name != "");
135 assert(scope());
137 trace0(("CARD::find_in_my_scope, looking for " + name).c_str() );
139 CARD_LIST::iterator i = scope()->find_(name);
140 if (i == scope()->end()) {
141 throw Exception_Cant_Find(long_label(), name,
142 ((owner()) ? owner()->long_label() : "(root)"));
143 }else{
145 return *i;
147 /*--------------------------------------------------------------------------*/
148 /* find_in_my_scope: find in same scope as myself
149 * whatever is found will have the same owner as me.
150 * capable of finding me.
151 * throws exception if can't find.
153 const CARD* CARD::find_in_my_scope(const std::string& name)const
155 assert(name != "");
156 assert(scope());
158 trace0(("CARD::find_in_my_scope looking for " + name).c_str() );
160 CARD_LIST::const_iterator i = scope()->find_(name);
161 if (i == scope()->end()) {
162 throw Exception_Cant_Find(long_label(), name,
163 ((owner()) ? owner()->long_label() : "(root)"));
164 }else{
166 return *i;
168 /*--------------------------------------------------------------------------*/
169 /* find_in_parent_scope: find in parent's scope
170 * parent is what my scope is a copy of.
171 * capable of finding my parent, who should be just like me.
172 * If there is no parent (I'm an original), use my scope.
173 * throws exception if can't find.
175 const CARD* CARD::find_in_parent_scope(const std::string& name)const
177 assert(name != "");
178 const CARD_LIST* p_scope = (scope()->parent()) ? scope()->parent() : scope();
180 CARD_LIST::const_iterator i = p_scope->find_(name);
181 if (i == p_scope->end()) {
182 throw Exception_Cant_Find(long_label(), name);
183 }else{
185 return *i;
187 /*--------------------------------------------------------------------------*/
188 /* find_looking_out: find in my or enclosing scope
189 * capable of finding me, or anything back to root.
190 * throws exception if can't find.
192 const CARD* CARD::find_looking_out(const std::string& name)const
194 try {
195 return find_in_parent_scope(name);
196 }catch (Exception_Cant_Find&) {
197 if (owner()) {
198 return owner()->find_looking_out(name);
199 }else if (makes_own_scope()) {
200 // probably a subckt or "module"
201 CARD_LIST::const_iterator i = CARD_LIST::card_list.find_(name);
202 if (i != CARD_LIST::card_list.end()) {
203 return *i;
204 }else{
205 throw;
207 }else{
208 throw;
212 /*--------------------------------------------------------------------------*/
213 TIME_PAIR CARD::tr_review()
215 return TIME_PAIR(NEVER,NEVER);
217 /*--------------------------------------------------------------------------*/
218 void CARD::new_subckt(PARAM_LIST_MAP* p)
220 assert(!_subckt);
221 delete _subckt;
222 _subckt = NULL;
223 _subckt = new CARD_LIST(this, p);
225 /*--------------------------------------------------------------------------*/
226 void CARD::new_subckt(const CARD* Model, PARAM_LIST* Params)
228 delete _subckt;
229 _subckt = NULL;
230 _subckt = new CARD_LIST(Model, this, scope(), Params);
232 /*--------------------------------------------------------------------------*/
233 void CARD::renew_subckt(const CARD* Model, PARAM_LIST* Params)
235 // trying to fix: is_first_expand is true too often!
236 bool frozen = 0;
237 const MODEL_CARD* m = dynamic_cast<const MODEL_CARD*>(Model);
238 if(m){
239 // not tested yet.
240 // frozen = m->frozen();
242 const BASE_SUBCKT* s = dynamic_cast<const BASE_SUBCKT*>(Model);
243 if(s){
244 frozen = s->frozen();
247 if (_sim->is_first_expand() && !frozen ) {
248 trace2("CARD::renew_subckt, first_expand", long_label(), *Params);
249 new_subckt(Model, Params);
250 }else{
251 assert(subckt());
252 trace2("CARD::renew_subckt, subsequent expand", long_label(), *Params);
253 subckt()->attach_params(Params, scope());
256 /*--------------------------------------------------------------------------*/
257 node_t& CARD::n_(unsigned i)const
259 return _n[i];
261 /*--------------------------------------------------------------------------*/
262 void CARD::set_param_by_name(std::string Name, std::string Value)
264 trace2("CARD::set_param_by_name", Name, Value);
265 //BUG// ugly linear search
266 for (int i = param_count() - 1; i >= 0; --i) {
267 for (int j = 0; param_name(i,j) != ""; ++j) { // multiple names
268 if (Umatch(Name, param_name(i,j) + ' ')) {
269 set_param_by_index(i, Value, 0/*offset*/);
270 return; //success
271 }else{
272 //keep looking
276 throw Exception_No_Match(Name);
278 /*--------------------------------------------------------------------------*/
279 /* set_dev_type: Attempt to change the type of an existing device.
280 * Usually, it just throws an exception, unless there is no change.
281 * Practical use is to override, so you can set things like NPN vs. PNP.
283 void CARD::set_dev_type(const std::string& New_Type)
285 if (!Umatch(New_Type, dev_type() + ' ')) {
286 //throw Exception_Cant_Set_Type(dev_type(), New_Type);
287 }else{
288 // it matches -- ok.
291 /*--------------------------------------------------------------------------*/
292 bool CARD::evaluated()const
294 if (_evaliter == _sim->iteration_tag()) {
295 return true;
296 }else{
297 _evaliter = _sim->iteration_tag();
298 return false;
301 /*--------------------------------------------------------------------------*/
302 /*--------------------------------------------------------------------------*/
303 // vim:ts=8:sw=2:noet: