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)
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 *------------------------------------------------------------------
23 * Spice3 compatible "semiconductor resistor and capacitor"
25 //testing=script 2006.07.13
30 /*--------------------------------------------------------------------------*/
31 class EVAL_BM_SEMI_BASE
: public EVAL_BM_ACTION_BASE
{
33 PARAMETER
<double> _length
;
34 PARAMETER
<double> _width
;
37 static double const _default_length
;
38 static double const _default_width
;
39 static double const _default_value
;
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
{
59 explicit EVAL_BM_SEMI_CAPACITOR(const EVAL_BM_SEMI_CAPACITOR
& p
)
60 :EVAL_BM_SEMI_BASE(p
) {}
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
{
74 explicit EVAL_BM_SEMI_RESISTOR(const EVAL_BM_SEMI_RESISTOR
& p
)
75 :EVAL_BM_SEMI_BASE(p
) {}
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
{
90 PARAMETER
<double> _narrow
;
91 PARAMETER
<double> _defw
;
92 PARAMETER
<double> _tc1
;
93 PARAMETER
<double> _tc2
;
95 static double const _default_narrow
;
96 static double const _default_defw
;
97 static double const _default_tc1
;
98 static double const _default_tc2
;
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
{
116 PARAMETER
<double> _cj
;
117 PARAMETER
<double> _cjsw
;
119 static double const _default_cj
;
120 static double const _default_cjsw
;
122 explicit MODEL_SEMI_CAPACITOR(const MODEL_SEMI_CAPACITOR
& p
);
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
{
141 PARAMETER
<double> _rsh
;
143 static double const _default_rsh
;
145 explicit MODEL_SEMI_RESISTOR(const MODEL_SEMI_RESISTOR
& p
);
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
),
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
);
192 && _length
== p
->_length
193 && _width
== p
->_width
194 && EVAL_BM_ACTION_BASE::operator==(x
);
201 /*--------------------------------------------------------------------------*/
202 void EVAL_BM_SEMI_BASE::print_common_obsolete_callback(OMSTREAM
& o
, LANGUAGE
* lang
)const
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
);
216 /*--------------------------------------------------------------------------*/
217 void EVAL_BM_SEMI_BASE::precalc_first(const CARD_LIST
* 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
)
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
);
245 && EVAL_BM_SEMI_BASE::operator==(x
);
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());
260 throw Exception_Model_Type_Mismatch(d
->long_label(), modelname(), "semi-capacitor (C)");
264 /*--------------------------------------------------------------------------*/
265 void EVAL_BM_SEMI_CAPACITOR::precalc_last(const CARD_LIST
* 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");
283 if (eff_length
<= 0.) {untested();
284 throw Exception_Precalc(modelname() + ": effective length is negative or zero\n");
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
);
294 && EVAL_BM_SEMI_BASE::operator==(x
);
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());
309 throw Exception_Model_Type_Mismatch(d
->long_label(), modelname(), "semi-resistor (R)");
313 /*--------------------------------------------------------------------------*/
314 void EVAL_BM_SEMI_RESISTOR::precalc_last(const CARD_LIST
* 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
;
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");
337 if (eff_length
<= 0.) {
338 throw Exception_Precalc(modelname() + ": effective length is negative or zero\n");
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()
351 _narrow(_default_narrow
),
352 _defw(_default_defw
),
357 /*--------------------------------------------------------------------------*/
358 MODEL_SEMI_BASE::MODEL_SEMI_BASE(const MODEL_SEMI_BASE
& p
)
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
) {
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()) {
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();
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()
445 /*--------------------------------------------------------------------------*/
446 MODEL_SEMI_CAPACITOR::MODEL_SEMI_CAPACITOR(const MODEL_SEMI_CAPACITOR
& p
)
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
) {
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
) {
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
483 return param_name(i
);
484 }else if (i
>= MODEL_SEMI_BASE::param_count()) {
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();
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()
519 /*--------------------------------------------------------------------------*/
520 MODEL_SEMI_RESISTOR::MODEL_SEMI_RESISTOR(const MODEL_SEMI_RESISTOR
& p
)
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
) {
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
553 return param_name(i
);
554 }else if (i
>= MODEL_SEMI_BASE::param_count()) {
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();
576 _rsh
.e_val(_default_rsh
, par_scope
);
578 /*--------------------------------------------------------------------------*/
579 /*--------------------------------------------------------------------------*/
580 // vim:ts=8:sw=2:noet: