DESTDIR in uninstall target
[gnucap-felix.git] / apps / bmm_semi.cc
blob3f0aefbde3ae2d8cd4b0b5083697607f194c4a75
1 /*$Id: bmm_semi.cc,v 26.138 2013/04/24 02:44:30 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 * behavioral modeling
23 * Spice3 compatible "semiconductor resistor and capacitor"
25 //testing=script 2006.07.13
26 #include "globals.h"
27 #include "u_lang.h"
28 #include "e_model.h"
29 #include "bm.h"
30 /*--------------------------------------------------------------------------*/
31 class EVAL_BM_SEMI_BASE : public EVAL_BM_ACTION_BASE {
32 protected:
33 PARAMETER<double> _length;
34 PARAMETER<double> _width;
35 double _value;
36 private:
37 static double const _default_length;
38 static double const _default_width;
39 static double const _default_value;
40 protected:
41 explicit EVAL_BM_SEMI_BASE(const EVAL_BM_SEMI_BASE& p);
42 explicit EVAL_BM_SEMI_BASE(int c=0);
43 ~EVAL_BM_SEMI_BASE() {}
44 protected: // override virtual
45 bool operator==(const COMMON_COMPONENT&)const;
46 COMMON_COMPONENT* clone()const = 0;
47 void print_common_obsolete_callback(OMSTREAM&, LANGUAGE*)const;
49 void precalc_first(const CARD_LIST*);
50 void expand(const COMPONENT*);
51 void tr_eval(ELEMENT*)const;
52 std::string name()const {untested();return modelname().c_str();}
53 bool ac_too()const {untested();return false;}
54 bool parse_params_obsolete_callback(CS&);
56 /*--------------------------------------------------------------------------*/
57 class EVAL_BM_SEMI_CAPACITOR : public EVAL_BM_SEMI_BASE {
58 private:
59 explicit EVAL_BM_SEMI_CAPACITOR(const EVAL_BM_SEMI_CAPACITOR& p)
60 :EVAL_BM_SEMI_BASE(p) {}
61 public:
62 explicit EVAL_BM_SEMI_CAPACITOR(int c=0)
63 :EVAL_BM_SEMI_BASE(c) {}
64 ~EVAL_BM_SEMI_CAPACITOR() {}
65 private: // override virtual
66 bool operator==(const COMMON_COMPONENT&)const;
67 COMMON_COMPONENT* clone()const {return new EVAL_BM_SEMI_CAPACITOR(*this);}
68 void expand(const COMPONENT*);
69 void precalc_last(const CARD_LIST*);
71 /*--------------------------------------------------------------------------*/
72 class EVAL_BM_SEMI_RESISTOR : public EVAL_BM_SEMI_BASE {
73 private:
74 explicit EVAL_BM_SEMI_RESISTOR(const EVAL_BM_SEMI_RESISTOR& p)
75 :EVAL_BM_SEMI_BASE(p) {}
76 public:
77 explicit EVAL_BM_SEMI_RESISTOR(int c=0)
78 :EVAL_BM_SEMI_BASE(c) {}
79 ~EVAL_BM_SEMI_RESISTOR() {}
80 private: // override virtual
81 bool operator==(const COMMON_COMPONENT&)const;
82 COMMON_COMPONENT* clone()const {return new EVAL_BM_SEMI_RESISTOR(*this);}
83 void expand(const COMPONENT*);
84 void precalc_last(const CARD_LIST*);
86 /*--------------------------------------------------------------------------*/
87 /*--------------------------------------------------------------------------*/
88 class MODEL_SEMI_BASE : public MODEL_CARD {
89 public:
90 PARAMETER<double> _narrow;
91 PARAMETER<double> _defw;
92 PARAMETER<double> _tc1;
93 PARAMETER<double> _tc2;
94 private:
95 static double const _default_narrow;
96 static double const _default_defw;
97 static double const _default_tc1;
98 static double const _default_tc2;
99 protected:
100 explicit MODEL_SEMI_BASE();
101 explicit MODEL_SEMI_BASE(const MODEL_SEMI_BASE& p);
102 protected: // override virtual
103 void precalc_first();
104 //void precalc_last();
105 //CARD* clone()const //MODEL_CARD/pure
106 void set_param_by_index(int, std::string&, int);
107 bool param_is_printable(int)const;
108 std::string param_name(int)const;
109 std::string param_name(int,int)const;
110 std::string param_value(int)const;
111 int param_count()const {return (4 + MODEL_CARD::param_count());}
113 /*--------------------------------------------------------------------------*/
114 class MODEL_SEMI_CAPACITOR : public MODEL_SEMI_BASE {
115 public:
116 PARAMETER<double> _cj;
117 PARAMETER<double> _cjsw;
118 private:
119 static double const _default_cj;
120 static double const _default_cjsw;
121 private:
122 explicit MODEL_SEMI_CAPACITOR(const MODEL_SEMI_CAPACITOR& p);
123 public:
124 explicit MODEL_SEMI_CAPACITOR();
125 private: // override virtual
126 std::string dev_type()const {return "c";}
127 void precalc_first();
128 //void precalc_last();
129 COMMON_COMPONENT* new_common()const {return new EVAL_BM_SEMI_CAPACITOR;}
130 CARD* clone()const {return new MODEL_SEMI_CAPACITOR(*this);}
131 void set_param_by_index(int, std::string&, int);
132 bool param_is_printable(int)const;
133 std::string param_name(int)const;
134 std::string param_name(int,int)const;
135 std::string param_value(int)const;
136 int param_count()const {return (2 + MODEL_SEMI_BASE::param_count());}
138 /*--------------------------------------------------------------------------*/
139 class MODEL_SEMI_RESISTOR : public MODEL_SEMI_BASE {
140 public:
141 PARAMETER<double> _rsh;
142 private:
143 static double const _default_rsh;
144 private:
145 explicit MODEL_SEMI_RESISTOR(const MODEL_SEMI_RESISTOR& p);
146 public:
147 explicit MODEL_SEMI_RESISTOR();
148 private: // override virtual
149 std::string dev_type()const {return "r";}
150 void precalc_first();
151 //void precalc_last();
152 COMMON_COMPONENT* new_common()const {return new EVAL_BM_SEMI_RESISTOR;}
153 CARD* clone()const {return new MODEL_SEMI_RESISTOR(*this);}
154 void set_param_by_index(int, std::string&, int);
155 bool param_is_printable(int)const;
156 std::string param_name(int)const;
157 std::string param_name(int,int)const;
158 std::string param_value(int)const;
159 int param_count()const {return (1 + MODEL_SEMI_BASE::param_count());}
161 /*--------------------------------------------------------------------------*/
162 double const EVAL_BM_SEMI_BASE::_default_length = NOT_INPUT;
163 double const EVAL_BM_SEMI_BASE::_default_width = NOT_INPUT;
164 double const EVAL_BM_SEMI_BASE::_default_value = NOT_INPUT;
165 /*--------------------------------------------------------------------------*/
166 static MODEL_SEMI_RESISTOR p1;
167 static MODEL_SEMI_CAPACITOR p2;
168 static DISPATCHER<MODEL_CARD>::INSTALL
169 d1(&model_dispatcher, "r|res", &p1),
170 d2(&model_dispatcher, "c|cap", &p2);
171 /*--------------------------------------------------------------------------*/
172 EVAL_BM_SEMI_BASE::EVAL_BM_SEMI_BASE(int c)
173 :EVAL_BM_ACTION_BASE(c),
174 _length(_default_length),
175 _width(_default_width),
176 _value(_default_value)
179 /*--------------------------------------------------------------------------*/
180 EVAL_BM_SEMI_BASE::EVAL_BM_SEMI_BASE(const EVAL_BM_SEMI_BASE& p)
181 :EVAL_BM_ACTION_BASE(p),
182 _length(p._length),
183 _width(p._width),
184 _value(p._value)
187 /*--------------------------------------------------------------------------*/
188 bool EVAL_BM_SEMI_BASE::operator==(const COMMON_COMPONENT& x)const
190 const EVAL_BM_SEMI_BASE* p = dynamic_cast<const EVAL_BM_SEMI_BASE*>(&x);
191 bool rv = p
192 && _length == p->_length
193 && _width == p->_width
194 && EVAL_BM_ACTION_BASE::operator==(x);
195 if (rv) {
196 untested();
197 }else{
199 return rv;
201 /*--------------------------------------------------------------------------*/
202 void EVAL_BM_SEMI_BASE::print_common_obsolete_callback(OMSTREAM& o, LANGUAGE* lang)const
204 assert(lang);
205 o << modelname();
206 print_pair(o, lang, "l", _length);
207 print_pair(o, lang, "w", _width, _width.has_hard_value());
208 EVAL_BM_ACTION_BASE::print_common_obsolete_callback(o, lang);
210 /*--------------------------------------------------------------------------*/
211 void EVAL_BM_SEMI_BASE::expand(const COMPONENT* d)
213 EVAL_BM_ACTION_BASE::expand(d);
214 attach_model(d);
216 /*--------------------------------------------------------------------------*/
217 void EVAL_BM_SEMI_BASE::precalc_first(const CARD_LIST* Scope)
218 {itested();
219 assert(Scope);
220 EVAL_BM_ACTION_BASE::precalc_first(Scope);
221 _length.e_val(_default_length, Scope);
222 _width.e_val(_default_width, Scope);
224 /*--------------------------------------------------------------------------*/
225 void EVAL_BM_SEMI_BASE::tr_eval(ELEMENT* d)const
227 tr_finish_tdv(d, _value);
229 /*--------------------------------------------------------------------------*/
230 bool EVAL_BM_SEMI_BASE::parse_params_obsolete_callback(CS& cmd)
232 return ONE_OF
233 || Get(cmd, "l", &_length)
234 || Get(cmd, "w", &_width)
235 || EVAL_BM_ACTION_BASE::parse_params_obsolete_callback(cmd)
238 /*--------------------------------------------------------------------------*/
239 /*--------------------------------------------------------------------------*/
240 bool EVAL_BM_SEMI_CAPACITOR::operator==(const COMMON_COMPONENT& x)const
242 const EVAL_BM_SEMI_CAPACITOR*
243 p = dynamic_cast<const EVAL_BM_SEMI_CAPACITOR*>(&x);
244 bool rv = p
245 && EVAL_BM_SEMI_BASE::operator==(x);
246 if (rv) {
247 untested();
248 }else{
250 return rv;
252 /*--------------------------------------------------------------------------*/
253 void EVAL_BM_SEMI_CAPACITOR::expand(const COMPONENT* d)
255 EVAL_BM_SEMI_BASE::expand(d);
257 const MODEL_SEMI_CAPACITOR* m = dynamic_cast<const MODEL_SEMI_CAPACITOR*>(model());
258 if (!m) {
259 unreachable();
260 throw Exception_Model_Type_Mismatch(d->long_label(), modelname(), "semi-capacitor (C)");
261 }else{
264 /*--------------------------------------------------------------------------*/
265 void EVAL_BM_SEMI_CAPACITOR::precalc_last(const CARD_LIST* Scope)
267 assert(Scope);
268 EVAL_BM_SEMI_BASE::precalc_last(Scope);
270 const MODEL_SEMI_CAPACITOR* m = prechecked_cast<const MODEL_SEMI_CAPACITOR*>(model());
272 double width = (_width == NOT_INPUT) ? m->_defw : _width;
273 double eff_width = width - m->_narrow;
274 double eff_length = _length - m->_narrow;
275 _value = m->_cj * eff_length * eff_width + 2. * m->_cjsw * (eff_length + eff_width);
276 double tempdiff = (_temp_c - m->_tnom_c);
277 _value *= 1 + m->_tc1*tempdiff + m->_tc2*tempdiff*tempdiff;
279 if (eff_width <= 0.) {untested();
280 throw Exception_Precalc(modelname() + ": effective width is negative or zero\n");
281 }else{
283 if (eff_length <= 0.) {untested();
284 throw Exception_Precalc(modelname() + ": effective length is negative or zero\n");
285 }else{
288 /*--------------------------------------------------------------------------*/
289 bool EVAL_BM_SEMI_RESISTOR::operator==(const COMMON_COMPONENT& x)const
291 const EVAL_BM_SEMI_RESISTOR*
292 p = dynamic_cast<const EVAL_BM_SEMI_RESISTOR*>(&x);
293 bool rv = p
294 && EVAL_BM_SEMI_BASE::operator==(x);
295 if (rv) {
296 untested();
297 }else{
299 return rv;
301 /*--------------------------------------------------------------------------*/
302 void EVAL_BM_SEMI_RESISTOR::expand(const COMPONENT* d)
304 EVAL_BM_SEMI_BASE::expand(d);
306 const MODEL_SEMI_RESISTOR* m = dynamic_cast<const MODEL_SEMI_RESISTOR*>(model());
307 if (!m) {
308 unreachable();
309 throw Exception_Model_Type_Mismatch(d->long_label(), modelname(), "semi-resistor (R)");
310 }else{
313 /*--------------------------------------------------------------------------*/
314 void EVAL_BM_SEMI_RESISTOR::precalc_last(const CARD_LIST* Scope)
316 assert(Scope);
317 EVAL_BM_SEMI_BASE::precalc_last(Scope);
319 const MODEL_SEMI_RESISTOR* m = prechecked_cast<const MODEL_SEMI_RESISTOR*>(model());
321 double width = (_width == NOT_INPUT) ? m->_defw : _width;
322 double eff_width = width - m->_narrow;
323 double eff_length = _length - m->_narrow;
325 if (eff_width != 0.) {
326 _value = m->_rsh * eff_length / eff_width;
327 }else{itested();
328 _value = BIGBIG;
330 double tempdiff = (_temp_c - m->_tnom_c);
331 _value *= 1 + m->_tc1*tempdiff + m->_tc2*tempdiff*tempdiff;
333 if (eff_width <= 0.) {itested();
334 throw Exception_Precalc(modelname() + ": effective width is negative or zero\n");
335 }else{
337 if (eff_length <= 0.) {
338 throw Exception_Precalc(modelname() + ": effective length is negative or zero\n");
339 }else{
342 /*--------------------------------------------------------------------------*/
343 /*--------------------------------------------------------------------------*/
344 double const MODEL_SEMI_BASE::_default_narrow = 0.;
345 double const MODEL_SEMI_BASE::_default_defw = 1e-6;
346 double const MODEL_SEMI_BASE::_default_tc1 = 0.;
347 double const MODEL_SEMI_BASE::_default_tc2 = 0.;
348 /*--------------------------------------------------------------------------*/
349 MODEL_SEMI_BASE::MODEL_SEMI_BASE()
350 :MODEL_CARD(NULL),
351 _narrow(_default_narrow),
352 _defw(_default_defw),
353 _tc1(_default_tc1),
354 _tc2(_default_tc2)
357 /*--------------------------------------------------------------------------*/
358 MODEL_SEMI_BASE::MODEL_SEMI_BASE(const MODEL_SEMI_BASE& p)
359 :MODEL_CARD(p),
360 _narrow(p._narrow),
361 _defw(p._defw),
362 _tc1(p._tc1),
363 _tc2(p._tc2)
366 /*--------------------------------------------------------------------------*/
367 void MODEL_SEMI_BASE::set_param_by_index(int i, std::string& value, int offset)
369 switch (MODEL_SEMI_BASE::param_count() - 1 - i) {
370 case 0: _narrow = value; break;
371 case 1: _defw = value; break;
372 case 2: _tc1 = value; break;
373 case 3: _tc2 = value; break;
374 default: MODEL_CARD::set_param_by_index(i, value, offset); break;
377 /*--------------------------------------------------------------------------*/
378 bool MODEL_SEMI_BASE::param_is_printable(int i)const
380 switch (MODEL_SEMI_BASE::param_count() - 1 - i) {
381 case 0:
382 case 1:
383 case 2:
384 case 3: return true;
385 default: return MODEL_CARD::param_is_printable(i);
388 /*--------------------------------------------------------------------------*/
389 std::string MODEL_SEMI_BASE::param_name(int i)const
391 switch (MODEL_SEMI_BASE::param_count() - 1 - i) {
392 case 0: return "narrow";
393 case 1: return "defw";
394 case 2: return "tc1";
395 case 3: return "tc2";
396 default: return MODEL_CARD::param_name(i);
399 /*--------------------------------------------------------------------------*/
400 std::string MODEL_SEMI_BASE::param_name(int i, int j)const
402 if (j == 0) {untested();
403 return param_name(i);
404 }else if (i >= MODEL_CARD::param_count()) {
405 return "";
406 }else{
407 return MODEL_CARD::param_name(i, j);
410 /*--------------------------------------------------------------------------*/
411 std::string MODEL_SEMI_BASE::param_value(int i)const
413 switch (MODEL_SEMI_BASE::param_count() - 1 - i) {
414 case 0: return _narrow.string();
415 case 1: return _defw.string();
416 case 2: return _tc1.string();
417 case 3: return _tc2.string();
418 default: return MODEL_CARD::param_value(i);
421 /*--------------------------------------------------------------------------*/
422 void MODEL_SEMI_BASE::precalc_first()
424 MODEL_CARD::precalc_first();
426 const CARD_LIST* s = scope();
427 assert(s);
429 _narrow.e_val(_default_narrow, s);
430 _defw.e_val(_default_defw, s);
431 _tc1.e_val(_default_tc1, s);
432 _tc2.e_val(_default_tc2, s);
434 /*--------------------------------------------------------------------------*/
435 /*--------------------------------------------------------------------------*/
436 double const MODEL_SEMI_CAPACITOR::_default_cj = 0.;
437 double const MODEL_SEMI_CAPACITOR::_default_cjsw = 0.;
438 /*--------------------------------------------------------------------------*/
439 MODEL_SEMI_CAPACITOR::MODEL_SEMI_CAPACITOR()
440 :MODEL_SEMI_BASE(),
441 _cj(_default_cj),
442 _cjsw(_default_cjsw)
445 /*--------------------------------------------------------------------------*/
446 MODEL_SEMI_CAPACITOR::MODEL_SEMI_CAPACITOR(const MODEL_SEMI_CAPACITOR& p)
447 :MODEL_SEMI_BASE(p),
448 _cj(p._cj),
449 _cjsw(p._cjsw)
452 /*--------------------------------------------------------------------------*/
453 void MODEL_SEMI_CAPACITOR::set_param_by_index(int i, std::string& value, int offset)
455 switch (MODEL_SEMI_CAPACITOR::param_count() - 1 - i) {
456 case 0: _cj = value; break;
457 case 1: _cjsw = value; break;
458 default: MODEL_SEMI_BASE::set_param_by_index(i, value, offset); break;
461 /*--------------------------------------------------------------------------*/
462 bool MODEL_SEMI_CAPACITOR::param_is_printable(int i)const
464 switch (MODEL_SEMI_CAPACITOR::param_count() - 1 - i) {
465 case 0:
466 case 1: return true;
467 default: return MODEL_SEMI_BASE::param_is_printable(i);
470 /*--------------------------------------------------------------------------*/
471 std::string MODEL_SEMI_CAPACITOR::param_name(int i)const
473 switch (MODEL_SEMI_CAPACITOR::param_count() - 1 - i) {
474 case 0: return "cj";
475 case 1: return "cjsw";
476 default: return MODEL_SEMI_BASE::param_name(i);
479 /*--------------------------------------------------------------------------*/
480 std::string MODEL_SEMI_CAPACITOR::param_name(int i, int j)const
482 if (j == 0) {
483 return param_name(i);
484 }else if (i >= MODEL_SEMI_BASE::param_count()) {
485 return "";
486 }else{
487 return MODEL_SEMI_BASE::param_name(i, j);
490 /*--------------------------------------------------------------------------*/
491 std::string MODEL_SEMI_CAPACITOR::param_value(int i)const
493 switch (MODEL_SEMI_CAPACITOR::param_count() - 1 - i) {
494 case 0: return _cj.string();
495 case 1: return _cjsw.string();
496 default: return MODEL_SEMI_BASE::param_value(i);
499 /*--------------------------------------------------------------------------*/
500 void MODEL_SEMI_CAPACITOR::precalc_first()
502 MODEL_SEMI_BASE::precalc_first();
504 const CARD_LIST* s = scope();
505 assert(s);
507 _cj.e_val(_default_cj, s);
508 _cjsw.e_val(_default_cjsw, s);
510 /*--------------------------------------------------------------------------*/
511 /*--------------------------------------------------------------------------*/
512 double const MODEL_SEMI_RESISTOR::_default_rsh = NOT_INPUT;
513 /*--------------------------------------------------------------------------*/
514 MODEL_SEMI_RESISTOR::MODEL_SEMI_RESISTOR()
515 :MODEL_SEMI_BASE(),
516 _rsh(_default_rsh)
519 /*--------------------------------------------------------------------------*/
520 MODEL_SEMI_RESISTOR::MODEL_SEMI_RESISTOR(const MODEL_SEMI_RESISTOR& p)
521 :MODEL_SEMI_BASE(p),
522 _rsh(p._rsh)
525 /*--------------------------------------------------------------------------*/
526 void MODEL_SEMI_RESISTOR::set_param_by_index(int i, std::string& value, int offset)
528 switch (MODEL_SEMI_RESISTOR::param_count() - 1 - i) {
529 case 0: _rsh = value; break;
530 default: MODEL_SEMI_BASE::set_param_by_index(i, value, offset); break;
533 /*--------------------------------------------------------------------------*/
534 bool MODEL_SEMI_RESISTOR::param_is_printable(int i)const
536 switch (MODEL_SEMI_RESISTOR::param_count() - 1 - i) {
537 case 0: return true;
538 default: return MODEL_SEMI_BASE::param_is_printable(i);
541 /*--------------------------------------------------------------------------*/
542 std::string MODEL_SEMI_RESISTOR::param_name(int i)const
544 switch (MODEL_SEMI_RESISTOR::param_count() - 1 - i) {
545 case 0: return "rsh";
546 default: return MODEL_SEMI_BASE::param_name(i);
549 /*--------------------------------------------------------------------------*/
550 std::string MODEL_SEMI_RESISTOR::param_name(int i, int j)const
552 if (j == 0) {
553 return param_name(i);
554 }else if (i >= MODEL_SEMI_BASE::param_count()) {
555 return "";
556 }else{
557 return MODEL_SEMI_BASE::param_name(i, j);
560 /*--------------------------------------------------------------------------*/
561 std::string MODEL_SEMI_RESISTOR::param_value(int i)const
563 switch (MODEL_SEMI_RESISTOR::param_count() - 1 - i) {
564 case 0: return _rsh.string();
565 default: return MODEL_SEMI_BASE::param_value(i);
568 /*--------------------------------------------------------------------------*/
569 void MODEL_SEMI_RESISTOR::precalc_first()
571 MODEL_SEMI_BASE::precalc_first();
573 const CARD_LIST* par_scope = scope();
574 assert(par_scope);
576 _rsh.e_val(_default_rsh, par_scope);
578 /*--------------------------------------------------------------------------*/
579 /*--------------------------------------------------------------------------*/
580 // vim:ts=8:sw=2:noet: