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)
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
24 #include "u_time_pair.h"
25 #include "e_cardlist.h"
31 /*--------------------------------------------------------------------------*/
32 const int POOLSIZE
= 4;
33 /*--------------------------------------------------------------------------*/
49 /*--------------------------------------------------------------------------*/
50 CARD
* CARD::clone()const
53 error(bDANGER
, "CARD::clone, " + dev_type() +" " + long_label()
54 + " has no clone()\n");
58 /*--------------------------------------------------------------------------*/
59 CARD::CARD(const CARD
& p
)
62 _subckt(0), //BUG// isn't this supposed to copy????
64 _constant(p
._constant
),
67 _net_nodes(p
._net_nodes
),
74 /*--------------------------------------------------------------------------*/
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
;
88 /*--------------------------------------------------------------------------*/
89 /* connects_to: does this part connect to this 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
97 if (is_device()) {untested();
98 for (uint_t ii
= 0; ii
< net_nodes(); ++ii
) {untested();
99 if (node
.n_() == _n
[ii
].n_()) {untested();
108 /*--------------------------------------------------------------------------*/
109 CARD_LIST
* CARD::scope()
112 return owner()->subckt(); // normal element, owner determines scope
114 return &(CARD_LIST::card_list
); // root circuit
117 /*--------------------------------------------------------------------------*/
118 const CARD_LIST
* CARD::scope()const
121 return owner()->subckt(); // normal element, owner determines scope
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
)
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)"));
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
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)"));
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
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
);
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
195 return find_in_parent_scope(name
);
196 }catch (Exception_Cant_Find
&) {
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()) {
212 /*--------------------------------------------------------------------------*/
213 TIME_PAIR
CARD::tr_review()
215 return TIME_PAIR(NEVER
,NEVER
);
217 /*--------------------------------------------------------------------------*/
218 void CARD::new_subckt(PARAM_LIST_MAP
* p
)
223 _subckt
= new CARD_LIST(this, p
);
225 /*--------------------------------------------------------------------------*/
226 void CARD::new_subckt(const CARD
* Model
, PARAM_LIST
* Params
)
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!
237 const MODEL_CARD
* m
= dynamic_cast<const MODEL_CARD
*>(Model
);
240 // frozen = m->frozen();
242 const BASE_SUBCKT
* s
= dynamic_cast<const BASE_SUBCKT
*>(Model
);
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
);
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
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*/);
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);
291 /*--------------------------------------------------------------------------*/
292 bool CARD::evaluated()const
294 if (_evaliter
== _sim
->iteration_tag()) {
297 _evaliter
= _sim
->iteration_tag();
301 /*--------------------------------------------------------------------------*/
302 /*--------------------------------------------------------------------------*/
303 // vim:ts=8:sw=2:noet: