viminfo
[gnucap-felix.git] / lib / d_subckt.cc
blob26e75abf64c24a928865b4309067637e0c070899
1 /*$Id: d_subckt.cc,v 26.138 2013/04/24 03:03:11 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 * subcircuit stuff
23 * base class for other elements using internal subckts
24 * netlist syntax:
25 * device: Xxxxx <nodelist> <subckt-name> <args>
26 * model: .subckt <subckt-name> <nodelist>
27 * (device cards)
28 * .ends <subckt-name>
29 * storage note ...
30 * the .subckt always has a comment at the hook point, so a for loop works
31 * the expansion (attact to the X) has all comments removed
32 * - need to process the entire ring - for doesn't work
34 //testing=script 2006.07.17
35 #include "globals.h"
36 #include "d_subckt.h"
37 /*--------------------------------------------------------------------------*/
38 int DEV_SUBCKT::_count = -1;
39 int COMMON_SUBCKT::_count = -1;
40 int MODEL_SUBCKT::_count = -1;
41 static COMMON_SUBCKT Default_SUBCKT(CC_STATIC);
42 /*--------------------------------------------------------------------------*/
43 static DEV_SUBCKT p1;
44 static MODEL_SUBCKT p2;
45 static DISPATCHER<CARD>::INSTALL
46 d1(&device_dispatcher, "X|dev_subckt", &p1),
47 d2(&device_dispatcher, "subckt|macro", &p2);
48 /*--------------------------------------------------------------------------*/
49 bool COMMON_SUBCKT::operator==(const COMMON_COMPONENT& x)const
51 const COMMON_SUBCKT* p = dynamic_cast<const COMMON_SUBCKT*>(&x);
52 bool rv = p
53 && _params == p->_params
54 && COMMON_COMPONENT::operator==(x);
55 return rv;
57 /*--------------------------------------------------------------------------*/
58 bool COMMON_SUBCKT::param_is_printable(int i)const
60 assert(i < COMMON_SUBCKT::param_count());
61 if (i >= COMMON_COMPONENT::param_count()) {
62 return _params.is_printable(COMMON_SUBCKT::param_count() - 1 - i);
63 }else{
64 return COMMON_COMPONENT::param_is_printable(i);
67 /*--------------------------------------------------------------------------*/
68 std::string COMMON_SUBCKT::param_name(int i)const
70 assert(i < COMMON_SUBCKT::param_count());
71 if (i >= COMMON_COMPONENT::param_count()) {
72 return _params.name(COMMON_SUBCKT::param_count() - 1 - i);
73 }else{
74 return COMMON_COMPONENT::param_name(i);
77 /*--------------------------------------------------------------------------*/
78 std::string COMMON_SUBCKT::param_name(int i, int j)const
80 assert(i < COMMON_SUBCKT::param_count());
81 if (j == 0) {untested();
82 return param_name(i);
83 }else if (i >= COMMON_COMPONENT::param_count()) {untested();
84 return "";
85 }else{untested();
86 return COMMON_COMPONENT::param_name(i);
89 /*--------------------------------------------------------------------------*/
90 std::string COMMON_SUBCKT::param_value(int i)const
92 assert(i < COMMON_SUBCKT::param_count());
93 if (i >= COMMON_COMPONENT::param_count()) {
94 return _params.value(COMMON_SUBCKT::param_count() - 1 - i);
95 }else{
96 return COMMON_COMPONENT::param_value(i);
99 /*--------------------------------------------------------------------------*/
100 void COMMON_SUBCKT::precalc_first(const CARD_LIST* Scope)
102 assert(Scope);
103 COMMON_COMPONENT::precalc_first(Scope);
105 for (PARAM_LIST::iterator i = _params.begin(); i != _params.end(); ++i) {
106 i->second.e_val(NOT_INPUT,Scope);
108 _mfactor = _params.deep_lookup("m");
110 /*--------------------------------------------------------------------------*/
111 void COMMON_SUBCKT::precalc_last(const CARD_LIST* Scope)
113 assert(Scope);
114 COMMON_COMPONENT::precalc_last(Scope);
116 /*--------------------------------------------------------------------------*/
117 MODEL_SUBCKT::MODEL_SUBCKT()
118 :COMPONENT()
120 _n = _nodes;
121 new_subckt();
122 ++_count;
124 /*--------------------------------------------------------------------------*/
125 MODEL_SUBCKT::MODEL_SUBCKT(const MODEL_SUBCKT& p)
126 :COMPONENT(p)
128 for (int ii = 0; ii < max_nodes(); ++ii) {
129 _nodes[ii] = p._nodes[ii];
131 _n = _nodes;
132 assert(p.subckt()->is_empty()); // incomplete, but enough for now.
133 new_subckt();
134 ++_count;
136 /*--------------------------------------------------------------------------*/
137 MODEL_SUBCKT::~MODEL_SUBCKT()
139 --_count;
141 /*--------------------------------------------------------------------------*/
142 CARD* MODEL_SUBCKT::clone_instance()const
143 {itested();
144 DEV_SUBCKT* new_instance = dynamic_cast<DEV_SUBCKT*>(p1.clone());
145 new_instance->_parent = this;
146 return new_instance;
148 /*--------------------------------------------------------------------------*/
149 DEV_SUBCKT::DEV_SUBCKT()
150 :BASE_SUBCKT(),
151 _parent(NULL)
153 attach_common(&Default_SUBCKT);
154 _n = _nodes;
155 ++_count;
157 /*--------------------------------------------------------------------------*/
158 DEV_SUBCKT::DEV_SUBCKT(const DEV_SUBCKT& p)
159 :BASE_SUBCKT(p),
160 _parent(p._parent)
162 //strcpy(modelname, p.modelname); in common
163 for (int ii = 0; ii < max_nodes(); ++ii) {
164 _nodes[ii] = p._nodes[ii];
166 _n = _nodes;
167 ++_count;
169 /*--------------------------------------------------------------------------*/
170 void DEV_SUBCKT::expand()
172 BASE_SUBCKT::expand();
173 COMMON_SUBCKT* c = prechecked_cast<COMMON_SUBCKT*>(mutable_common());
174 assert(c);
175 if (!_parent) {
176 const CARD* model = find_looking_out(c->modelname());
177 if(!dynamic_cast<const MODEL_SUBCKT*>(model)) {
178 throw Exception_Type_Mismatch(long_label(), c->modelname(), "subckt");
179 }else{
180 _parent = prechecked_cast<const MODEL_SUBCKT*>(model);
182 }else{
183 assert(find_looking_out(c->modelname()) == _parent);
186 assert(_parent->subckt());
187 assert(_parent->subckt()->params());
188 PARAM_LIST* pl = const_cast<PARAM_LIST*>(_parent->subckt()->params());
189 assert(pl);
190 c->_params.set_try_again(pl);
192 renew_subckt(_parent, this, scope(), &(c->_params));
193 subckt()->expand();
195 /*--------------------------------------------------------------------------*/
196 void DEV_SUBCKT::precalc_first()
198 BASE_SUBCKT::precalc_first();
200 if (subckt()) {
201 COMMON_SUBCKT* c = prechecked_cast<COMMON_SUBCKT*>(mutable_common());
202 assert(c);
203 subckt()->attach_params(&(c->_params), scope());
204 subckt()->precalc_first();
205 }else{
207 assert(!is_constant()); /* because I have more work to do */
209 /*--------------------------------------------------------------------------*/
210 void DEV_SUBCKT::precalc_last()
212 BASE_SUBCKT::precalc_last();
214 COMMON_SUBCKT* c = prechecked_cast<COMMON_SUBCKT*>(mutable_common());
215 assert(c);
216 subckt()->attach_params(&(c->_params), scope());
217 subckt()->precalc_last();
219 assert(!is_constant()); /* because I have more work to do */
221 /*--------------------------------------------------------------------------*/
222 double DEV_SUBCKT::tr_probe_num(const std::string& x)const
223 {itested();
224 if (Umatch(x, "p ")) {untested();
225 double power = 0.;
226 assert(subckt());
227 for (CARD_LIST::const_iterator
228 ci = subckt()->begin(); ci != subckt()->end(); ++ci) {untested();
229 power += CARD::probe(*ci,"P");
231 return power;
232 }else if (Umatch(x, "pd ")) {untested();
233 double power = 0.;
234 assert(subckt());
235 for (CARD_LIST::const_iterator
236 ci = subckt()->begin(); ci != subckt()->end(); ++ci) {untested();
237 power += CARD::probe(*ci,"PD");
239 return power;
240 }else if (Umatch(x, "ps ")) {untested();
241 double power = 0.;
242 assert(subckt());
243 for (CARD_LIST::const_iterator
244 ci = subckt()->begin(); ci != subckt()->end(); ++ci) {untested();
245 power += CARD::probe(*ci,"PS");
247 return power;
248 }else{itested();
249 return COMPONENT::tr_probe_num(x);
251 /*NOTREACHED*/
253 /*--------------------------------------------------------------------------*/
254 /*--------------------------------------------------------------------------*/
255 // vim:ts=8:sw=2:noet: