bump to -rc12
[gnucap-felix.git] / src / spice-wrapper.cc
blob1bec48957f617f54fe07584dbe8cdebd8b8b0a3a
1 /* -*- C++ -*-
2 * Copyright (C) 2007 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This file is distributed as is, completely without warranty or
8 * service support. The author and its employees are not liable for
9 * the condition or performance of the software.
11 * The author owns the copyright but shall not be liable for any
12 * infringement of copyright or other proprietary rights brought by
13 * third parties against the users of the software.
15 * The author hereby disclaims all implied warranties.
17 * This author grants the users the right to modify, copy, and
18 * redistribute this file, for any purpose, both within the user's
19 * organization and externally.
21 //testing=script 2008.11.28
22 // code style comment: Use of "reinterpret_cast" is always bad style.
23 /*--------------------------------------------------------------------------*/
24 // spice includes
25 extern "C" {
26 #define _complex CompleX
27 #define NODE NodE
28 #define public PubliC
29 #define bool BooL
30 #define main MaiN
31 #include "capabil.h"
32 #include "const.h"
33 #include "iferrmsg.h"
34 #include "devdefs.h"
35 #include "ftedefs.h"
36 #include "optdefs.h"
37 #ifdef JSPICE3
38 #include "uflags.h"
39 #include "inpdefs.h"
40 #include "tskdefs.h"
41 #endif
42 #undef main
43 #undef bool
44 #undef public
45 #undef NODE
46 #undef _complex
48 #undef eq
49 #undef OPT
50 #undef LINEAR
51 #undef STRING
52 #undef BOOLEAN
54 #undef VT_BOOL
55 #undef VT_NUM
56 #undef VT_REAL
57 #undef VT_STRING
58 #undef VT_LIST
60 /*--------------------------------------------------------------------------*/
61 // gnucap includes
62 //#include "globals.h"
63 #include "u_xprobe.h"
64 #include "e_paramlist.h"
65 #include "e_storag.h"
66 #include "e_model.h"
67 #include "d_subckt.h"
69 /*--------------------------------------------------------------------------*/
70 // customization -- must be last
71 #include "wrapper.h"
72 #if !defined(UNCONNECTED_NODES)
73 #define UNCONNECTED_NODES uDISALLOW
74 #if (MIN_NET_NODES != MAX_NET_NODES)
75 #error "What should I do with the unconnected nodes?"
76 #endif
77 #endif
78 #if !defined(VALUE_NAME)
79 #define VALUE_NAME "#"
80 #endif
81 #if !defined(TAIL_SIZE)
82 #define TAIL_SIZE 1
83 #endif
84 #if !defined(IS_VALID)
85 #define IS_VALID {return MODEL_CARD::is_valid(d);}
86 #endif
87 /*--------------------------------------------------------------------------*/
88 extern SPICEdev info;
89 const int SPICE_INVALID_NODE = 0;
90 const uint_t SPICE_UNCONNECTED_NODE = -2;
91 const int OFFSET = 1;
92 enum {uGROUND=1, uFLOAT=2, uDISALLOW=3};
93 const uint_t MATRIX_NODES = (MAX_NET_NODES + INTERNAL_NODES);
94 class DEV_SPICE;
95 class MODEL_SPICE;
96 static COMMON_PARAMLIST Default_Params(CC_STATIC);
97 /*--------------------------------------------------------------------------*/
98 /* function mapping: see devdefs.h
99 * DEVparam DEV_SPICE::parse_spice
100 * DEVmodParam MODEL_SPICE::parse_params
101 * DEVload DEV_SPICE::do_tr
102 * DEVsetup MODEL_SPICE::precalc, DEV_SPICE::expand
103 * DEVunsetup not used -- spice baggage -- just zeros some nodes
104 * DEVpzSetup not used -- pole-zero
105 * DEVtemperature DEV_SPICE::internal_precalc
106 * DEVtrunc DEV_SPICE::tr_review
107 * DEVfindBranch not used -- current probes for current controlled source
108 * DEVacLoad DEV_SPICE::do_ac
109 * DEVaccept not used -- sets break points //BUG// need for: isrc, ltra, tra, vsrc, cpl, txl
110 * DEVdestroy not used -- spice baggage -- deletes a list
111 * DEVmodDelete not used -- spice baggage -- delete one model
112 * DEVdelete not used -- spice baggage -- delete one instance
113 * DEVsetic not used -- "getic" -- initial conditions //BUG// need this
114 * DEVask DEV_SPICE::print_args, DEV_SPICE::tr_probe_num
115 * DEVmodAsk MODEL_SPICE::print_params, MODEL_SPICE::print_calculated
116 * DEVpzLoad not used -- pole zero -- should use for AC
117 * DEVconvTest DEV_SPICE::do_tr
118 * DEVsenSetup not used -- sensitivity
119 * DEVsenLoad not used -- sensitivity
120 * DEVsenUpdate not used -- sensitivity
121 * DEVsenAcLoad not used -- sensitivity
122 * DEVsenPrint not used -- sensitivity
123 * DEVsenTrunc not used -- sensitivity
124 * DEVdisto not used -- distortion
125 * DEVnoise not used -- noise
127 /*--------------------------------------------------------------------------*/
128 union SPICE_MODEL_DATA {
129 mutable GENmodel _gen;// generic -- use this one
130 MODEL _full; // determines size
131 char _space; // char pointer for fill_n
133 SPICE_MODEL_DATA() {
134 std::fill_n(&_space, sizeof(MODEL), '\0');
136 SPICE_MODEL_DATA(const SPICE_MODEL_DATA& p)
137 : _full(p._full) {
140 /*--------------------------------------------------------------------------*/
141 class MODEL_SPICE : public MODEL_CARD{
142 private:
143 static int _count;
144 static CKTcircuit _ckt;
145 public:
146 SPICE_MODEL_DATA _spice_model;
147 std::string _key;
148 std::string _level;
149 PARAM_LIST _params;
150 protected:
151 explicit MODEL_SPICE(const MODEL_SPICE& p); // for clone
152 public:
153 explicit MODEL_SPICE(const DEV_SPICE* p); // for dispatcher
154 ~MODEL_SPICE();
155 public: // override virtual
156 MODEL_CARD* clone()const {return new MODEL_SPICE(*this);}
157 bool is_valid(const COMPONENT* d)const IS_VALID
158 //void expand();
159 void precalc_first();
161 public: // type
162 void set_dev_type(const std::string& nt);
163 std::string dev_type()const { return _key;}
165 public: // parameters
166 bool param_is_printable(int)const;
167 std::string param_name(int)const;
168 std::string param_name(int i, int j)const;
169 std::string param_value(int)const;
170 void set_param_by_name(std::string Name, std::string Value);
171 void set_param_by_index(int, std::string&, int);
172 int param_count_dont_print()const {return MODEL_CARD::param_count();}
173 int param_count()const { return (static_cast<int>(_params.size()) + MODEL_CARD::param_count());}
175 void Set_param_by_name(std::string Name, std::string Value);
177 public: // not virtual
178 static int count() {untested(); return _count;}
179 static CKTcircuit* ckt() {return &_ckt;}
180 static void init_ckt();
182 /*--------------------------------------------------------------------------*/
183 class DEV_SPICE : public STORAGE {
184 private:
185 static int _count;
186 public:
187 private:
188 union {
189 mutable GENinstance _spice_instance;
190 INSTANCE _inst;
191 char _inst_space;
193 std::string _modelname;
194 const MODEL_SPICE* _model;
195 const SPICE_MODEL_DATA* _spice_model;
196 node_t _nodes[MATRIX_NODES];
197 COMPLEX* _matrix[MATRIX_NODES+OFFSET]; // For tran, real is now, imag is saved.
198 COMPLEX _matrix_core[MATRIX_NODES+OFFSET][MATRIX_NODES+OFFSET];
199 public:
200 double _i0[MATRIX_NODES+OFFSET]; // right side - current offsets or ac real part
201 double _i1[MATRIX_NODES+OFFSET]; // right side - saved ......... or ac imag part
202 double _v1[MATRIX_NODES+OFFSET]; // input voltages
203 double* (_states[8]); // array of 8 pointers
204 double* _states_1;
205 int _num_states;
206 int _maxEqNum;
207 private:
208 explicit DEV_SPICE(const DEV_SPICE& p);
209 public:
210 explicit DEV_SPICE();
211 ~DEV_SPICE();
212 protected: // override virtual
213 char id_letter()const {untested();return SPICE_LETTER[0];}
214 bool print_type_in_spice()const {return true;}
215 std::string value_name()const {return VALUE_NAME;}
216 uint_t max_nodes()const {return MAX_NET_NODES;}
217 uint_t min_nodes()const {return MIN_NET_NODES;}
218 uint_t matrix_nodes()const {return MATRIX_NODES;}
219 uint_t net_nodes()const {return _net_nodes;}
220 uint_t int_nodes()const {return INTERNAL_NODES;}
221 CARD* clone()const {return new DEV_SPICE(*this);}
222 //void precalc_first(); //ELEMENT
223 void expand();
224 void precalc_last();
225 //void map_nodes(); //ELEMENT
226 void internal_precalc();
228 void tr_iwant_matrix() {tr_iwant_matrix_extended();}
229 void tr_begin() {STORAGE::tr_begin(); internal_precalc();}
230 void tr_restore() {STORAGE::tr_restore(); internal_precalc();}
231 void dc_advance() {STORAGE::dc_advance(); internal_precalc();}
232 void tr_advance();
233 void tr_regress();
234 bool tr_needs_eval()const;
235 //void tr_queue_eval(); //ELEMENT
236 bool do_tr();
237 void tr_load();
238 TIME_PAIR tr_review();
239 void tr_accept();
240 void tr_unload();
241 hp_float_t tr_involts()const {unreachable();return NOT_VALID;}
242 //double tr_input()const //ELEMENT
243 hp_float_t tr_involts_limited()const {unreachable();return NOT_VALID;}
244 //double tr_input_limited()const //ELEMENT
245 double tr_amps()const {itested();return NOT_VALID;}
246 double tr_probe_num(const std::string&)const;
248 void ac_iwant_matrix() {ac_iwant_matrix_extended();}
249 void ac_begin();
250 void do_ac();
251 void ac_load();
252 COMPLEX ac_involts()const {unreachable();return NOT_VALID;}
253 COMPLEX ac_amps()const {unreachable();return NOT_VALID;}
254 XPROBE ac_probe_ext(const std::string&)const {itested(); return XPROBE(NOT_VALID, mtNONE);}
255 uint_t tail_size()const {return TAIL_SIZE;}
256 public: // type
257 void set_dev_type(const std::string& nt);
258 std::string dev_type()const {return _modelname;}
259 public: // ports
260 // bool port_exists(int i)const //COMPONENT
261 std::string port_name(uint_t i)const {itested();
262 assert(i < MAX_NET_NODES);
263 return port_names[i];
265 // const std::string& port_value(int i)const; //COMPONENT
266 //void set_port_by_name(std::string& name, std::string& value);
267 //void set_port_by_index(int index, std::string& value);
268 private: // parameters
269 //bool Param_exists(int i)const; // {return Param_name(i) != "";}
270 //bool Param_is_printable(int)const;
271 //std::string Param_name(int)const;
272 //std::string Param_name(int i, int j)const {return STORAGE::Param_name(i, j);}
273 //std::string Param_value(int)const;
274 void set_param_by_name(std::string Name, std::string Value);
275 void Set_param_by_name(std::string Name, std::string Value);
276 void Set_param_by_index(int, std::string&, int);
277 int param_count_dont_print()const {return common()->COMMON_COMPONENT::param_count();}
278 private:
279 CKTcircuit* ckt()const {return MODEL_SPICE::ckt();}
280 void init_ckt() {MODEL_SPICE::init_ckt();}
281 void update_ckt()const;
282 void localize_ckt()const;
283 int* spice_nodes()const {return &(_spice_instance.GENnode1);}
284 #ifndef NDEBUG
285 private:
286 unsigned _trouble;
287 #endif
289 /*--------------------------------------------------------------------------*/
290 /*--------------------------------------------------------------------------*/
291 CKTcircuit MODEL_SPICE::_ckt;
293 * used as intended, copy-out, matters: CKTnoncon, CKTtroubleElt
295 * used as intended, func specific: CKTmode, CKTcurrentAnalysis
297 * used as intended, localized, matters: CKTstates, CKTdelta, CKTdeltaOld,
298 * CKTag(broken), CKTorder(broken), CKTrhs, CKTrhsOld, CKTirhs,
299 * CKTtimePoints(broken,ltra?)
301 * used as intended, updated, matters: CKTtime, CKTtemp, CKTomega
303 * used as intended, constant, matters: CKTnomTemp, CKTabstol,
304 * CKTreltol, CKTvoltTol, CKTgmin, CKTsrcFact(broken),
305 * CKTdefaultMosL, CKTdefaultMosW, CKTdefaultMosAD, CKTdefaultMosAS,
307 * used almost as intended, matters, probably ok:
308 * CKTbypass: false to disable
309 * CKTintegrateMethod: used only by Jspice -- set to 0 to disable
310 * CKTsenInfo: used by sens, NULL to disable
311 * CKTfixLimit(mos1236): 1 for Spice-2 mode
312 * CKTbadMos3(mos3): false for Spice-3 mode
314 * misused: (not used by spice devs, use to pass gnucap stuff through)
315 * CKTstat: the device (type DEV_SPICE)
316 * CKTmaxEqNum: use as counter for internal nodes, pass to CKTmkVolt
318 * need to handle (ind): CKThead(ind,load)
319 * need to handle (cpl,txl): CKTnodes(cpl,txl),
321 * need to handle ([iv]src):
322 * CKTbreak([iv]src,accept), CKTfinalTime([iv]src,load), CKTstep([iv]src,load),
324 * need to handle (ltra):
325 * CKTminBreak(ltra,tra,accept), CKTtrtol(ltra,trunc),
326 * CKTmaxStep(ltra,temp), CKTtimeListSize(ltra,Jspice,accept),
327 * CKTtimeIndex(ltra), CKTsizeIncr(ltra), CKTtryToCompact(ltra)
329 * used by "predictor": CKTagp, CKTpred, CKTsols
330 * used by "sens": CKTirhsOld, CKTrhsOp
331 * used by noise&distortion: CKTcurJob
333 * not used: CKTvt, CKTmaxOrder, CKTmatrix, CKTniState, CKTrhsSpare,
334 * CKTirhsSpare, CKTsenRhs, CKTseniRhs, CKTlastNode, CKTnumStates,
335 * CKTdcMaxIter, CKTdcTrcvMaxIter, CKTtranMaxIter, CKTbreakSize, CKTsaveDelta,
336 * CKTbreaks, CKTpivotAbsTol, CKTpivotRelTol, CKTchgtol, CKTlteReltol, CKTlteAbstol,
337 * CKTdelmin, CKTinitTime, CKTdiagGmin, CKTnumSrcSteps, CKTnumGminSteps, CKThadNodeset,
338 * CKTnoOpIter, CKTisSetup, CKTdeltaList, CKTkeepOpInfo, CKTtroubleNode
340 #define assert_ckt_initialized(ckt) { \
341 assert(ckt); \
342 assert((ckt)->CKTnomTemp == OPT::tnom_c + CONSTCtoK); \
343 assert(((ckt)->CKTcurrentAnalysis == DOING_DCOP) == CKT_BASE::_sim->command_is_op()); \
344 assert(((ckt)->CKTcurrentAnalysis == DOING_TRCV) == CKT_BASE::_sim->command_is_dc()); \
345 assert(((ckt)->CKTcurrentAnalysis == DOING_AC ) == CKT_BASE::_sim->analysis_is_ac()); \
346 assert(((ckt)->CKTcurrentAnalysis == DOING_TRAN) == CKT_BASE::_sim->analysis_is_tran()); \
347 assert((ckt)->CKTbypass == false); \
348 assert((ckt)->CKTabstol == OPT::abstol); \
349 assert((ckt)->CKTreltol == OPT::reltol); \
350 assert((ckt)->CKTvoltTol == OPT::vntol); \
351 assert((ckt)->CKTsrcFact == 1.); \
352 assert((ckt)->CKTdefaultMosL == OPT::defl); \
353 assert((ckt)->CKTdefaultMosW == OPT::defw); \
354 assert((ckt)->CKTdefaultMosAD == OPT::defad); \
355 assert((ckt)->CKTdefaultMosAS == OPT::defas); \
358 void MODEL_SPICE::init_ckt()
360 assert(ckt());
361 ckt()->CKTtime = _sim->_time0;
362 ckt()->CKTtemp = _sim->_temp_c + CONSTCtoK; //manage by update
363 ckt()->CKTnomTemp = OPT::tnom_c + CONSTCtoK;
364 ckt()->CKTintegrateMethod = 0; // disable
365 if (_sim->command_is_op()) {
366 ckt()->CKTcurrentAnalysis = DOING_DCOP;
367 }else if (_sim->command_is_dc()) {
368 ckt()->CKTcurrentAnalysis = DOING_TRCV;
369 }else if (_sim->command_is_ac()) {
370 ckt()->CKTcurrentAnalysis = DOING_AC;
371 }else if (_sim->analysis_is_tran()) {
372 ckt()->CKTcurrentAnalysis = DOING_TRAN;
373 }else{ // probably probe
374 ckt()->CKTcurrentAnalysis = 0;
376 ckt()->CKTmode = 0; // wrong but safe
377 ckt()->CKTbypass = false; // manage this elsewhere
378 ckt()->CKTabstol = OPT::abstol;
379 ckt()->CKTreltol = OPT::reltol;
380 ckt()->CKTvoltTol = OPT::vntol;
381 ckt()->CKTgmin = OPT::gmin;
382 ckt()->CKTsrcFact = 1.; // source stepping kluge
383 ckt()->CKTdefaultMosL = OPT::defl;
384 ckt()->CKTdefaultMosW = OPT::defw;
385 ckt()->CKTdefaultMosAD = OPT::defad;
386 ckt()->CKTdefaultMosAS = OPT::defas;
387 ckt()->CKTfixLimit = false; // limiting kluge 1 == spice2
388 #ifndef JSPICE3
389 ckt()->CKTbadMos3 = false; // 1 = spice2 compat
390 ckt()->CKTsenInfo = NULL; // used as flag to print sens info
391 #endif
392 #ifdef NGSPICE_17
393 ckt()->CKTdefaultMosM = 1.;
394 ckt()->CKTcopyNodesets = false;
395 #endif
396 assert_ckt_initialized(ckt());
399 #define assert_ckt_up_to_date(ckt) { \
400 assert_ckt_initialized(ckt); \
401 assert((ckt)->CKTtime == CKT_BASE::_sim->_time0); \
402 assert((ckt)->CKTtemp == CKT_BASE::_sim->_temp_c + CONSTCtoK); \
405 void DEV_SPICE::update_ckt()const
407 assert_ckt_initialized(ckt());
408 ckt()->CKTgmin = OPT::gmin;
409 ckt()->CKTstat = NULL; // mark as not localized
410 ckt()->CKTtime = _sim->_time0;
411 ckt()->CKTdelta = NOT_VALID; // localized
412 ckt()->CKTtemp = _sim->_temp_c + CONSTCtoK;
413 ckt()->CKTmode = 0;
414 ckt()->CKTomega = _sim->_jomega.imag();
415 assert_ckt_up_to_date(ckt());
418 #define assert_ckt_localized(ckt) { \
419 assert_ckt_up_to_date(ckt); \
420 assert((ckt)->CKTstat); \
421 DEV_SPICE* d = reinterpret_cast<DEV_SPICE*>((ckt)->CKTstat);\
422 assert(d); \
423 assert(dynamic_cast<DEV_SPICE*>(d)); \
424 assert((ckt)->CKTdelta == d->_dt); \
425 if (d->_dt == 0) {untested(); \
426 assert((ckt)->CKTag[0] == 0); \
427 assert((ckt)->CKTorder == 1); \
428 }else if (d->_time[1] != 0 && d->_method_a == mTRAP) { \
429 assert(conchk((ckt)->CKTag[0], 2 / d->_dt)); \
430 assert((ckt)->CKTorder == 2); \
431 }else{ \
432 assert(conchk((ckt)->CKTag[0], 1 / d->_dt)); \
433 assert((ckt)->CKTorder == 1); \
435 assert((ckt)->CKTag[0] == (ckt)->CKTag[0]); \
436 assert((ckt)->CKTrhs == d->_i0); \
437 assert((ckt)->CKTrhsOld == d->_v1); \
438 assert((ckt)->CKTirhs == d->_i1); \
439 assert((ckt)->CKTtimePoints == d->_time); \
442 void DEV_SPICE::localize_ckt()const
444 assert_ckt_up_to_date(ckt());
445 ckt()->CKTstat = reinterpret_cast<STATistics*>(const_cast<DEV_SPICE*>(this));
446 assert(OPT::_keep_time_steps <= 8);
447 for (uint_t ii=0; ii<8; ++ii) {
448 ckt()->CKTstates[ii] = _states[ii];
450 //assert(ckt()->CKTtime == _time[0]); //BUG// can fail in ac
451 ckt()->CKTdelta = _dt;
452 for (uint_t ii=0; ii<OPT::_keep_time_steps-1; ++ii) {
453 ckt()->CKTdeltaOld[ii] = _time[ii] - _time[ii+1];
455 assert(_dt == NOT_VALID || conchk(ckt()->CKTdelta, ckt()->CKTdeltaOld[0]));
457 //ckt()->CKTag[0] = tr_c_to_g(1, ckt()->CKTag[0]);
458 // defer fixing this -- GEAR not here
459 if (_dt == 0) {untested();
460 ckt()->CKTag[1] = ckt()->CKTag[0] = 0;
461 ckt()->CKTorder = 1;
462 }else if (_time[1] != 0 && _method_a == mTRAP) {
463 ckt()->CKTag[0] = 2 / _dt;
464 ckt()->CKTag[1] = 1;
465 ckt()->CKTorder = 2;
466 }else{
467 ckt()->CKTag[0] = 1 / _dt;
468 ckt()->CKTag[1] = -1 / _dt;
469 ckt()->CKTorder = 1;
471 ckt()->CKTrhs = const_cast<double*>(_i0);
472 ckt()->CKTrhsOld = const_cast<double*>(_v1);
473 ckt()->CKTirhs = const_cast<double*>(_i1);
474 ckt()->CKTmode = 0;
475 ckt()->CKTtimePoints = const_cast<double*>(_time);
476 assert_ckt_localized(ckt());
479 #define assert_model_raw() { \
480 assert(_spice_model._gen.GENmodType == 0); \
481 assert(_spice_model._gen.GENnextModel == NULL); \
482 assert(_spice_model._gen.GENinstances == NULL); \
484 #define assert_model_unlocalized() { \
485 assert(_model->_spice_model._gen.GENinstances == NULL);\
486 assert(_spice_model); \
487 assert(_spice_model->_gen.GENmodType == 0); \
488 assert(_spice_model->_gen.GENnextModel == NULL); \
489 assert(_spice_model->_gen.GENinstances == NULL); \
490 assert(_spice_model->_gen.GENmodName); \
492 #define assert_model_localized() { \
493 assert(_spice_model); \
494 assert(_spice_model->_gen.GENmodType == 0); \
495 assert(_spice_model->_gen.GENnextModel == NULL); \
496 assert(_spice_model->_gen.GENinstances); \
497 assert(_spice_model->_gen.GENmodName); \
499 #define assert_instance() { \
500 assert(_spice_instance.GENnextInstance == NULL); \
501 assert(_spice_instance.GENname == NULL); \
503 /*--------------------------------------------------------------------------*/
504 /*--------------------------------------------------------------------------*/
505 /*--------------------------------------------------------------------------*/
506 struct IFVA {
507 IFvalue* _v;
508 int _type;
509 IFVA(IFvalue* v, int t) :_v(v), _type(t) {assert(v);}
511 void operator=(const std::string& s)
513 CS cmd(CS::_STRING, s);
514 assert(_v);
515 int datatype = _type;
516 if (datatype & IF_SET) {
517 if (datatype & IF_VECTOR) {untested();
518 incomplete();
519 }else{
521 switch (datatype & 0xff) {
522 case IF_FLAG: _v->iValue = true; break;
523 case IF_INTEGER: cmd >> _v->iValue; break;
524 case IF_REAL: cmd >> _v->rValue; break;
525 case IF_COMPLEX:untested();
526 //cmd >> _v->cValue;
527 incomplete();
528 break;
529 case IF_NODE:untested(); incomplete(); break;
530 case IF_STRING:
532 //assert(!(_v->sValue));
533 //BUG//memory leak -- this is never deleted
534 _v->sValue = new char[s.length()+1];
535 strcpy(_v->sValue, s.c_str());
536 break;
538 case IF_INSTANCE: untested(); incomplete(); break;
539 case IF_PARSETREE:untested(); incomplete(); break;
540 default: unreachable(); break;
542 }else{untested();
546 /*--------------------------------------------------------------------------*/
547 /*--------------------------------------------------------------------------*/
548 MODEL_SPICE::MODEL_SPICE(const DEV_SPICE* p)
549 :MODEL_CARD(p),
550 _spice_model(),
551 _key(),
552 _level(),
553 _params()
555 assert_model_raw();
557 /*--------------------------------------------------------------------------*/
558 MODEL_SPICE::MODEL_SPICE(const MODEL_SPICE& p)
559 :MODEL_CARD(p),
560 _spice_model(p._spice_model),
561 _key(p._key),
562 _level(p._level),
563 _params(p._params)
565 assert_model_raw();
567 /*--------------------------------------------------------------------------*/
568 MODEL_SPICE::~MODEL_SPICE()
570 --_count;
572 /*--------------------------------------------------------------------------*/
573 void MODEL_SPICE::Set_param_by_name(std::string Name, std::string new_value)
575 assert_model_raw();
576 assert(info.DEVpublic.numModelParms);
577 assert(info.DEVpublic.modelParms);
578 assert(info.DEVmodParam);
580 int num_params = *(info.DEVpublic.numModelParms);
581 for (int i = 0; i < num_params; ++i) {
582 IFparm Parms = info.DEVpublic.modelParms[i];
583 if (Name == Parms.keyword) {
584 IFvalue Value;
585 IFVA v(&Value, Parms.dataType);
586 v = new_value;
587 int ok = info.DEVmodParam(Parms.id, &Value, &_spice_model._gen);
588 assert(ok == OK);
589 return;
590 }else{
593 if (Name != "level") {
594 throw Exception_No_Match(Name);
595 }else{
598 /*--------------------------------------------------------------------------*/
599 void MODEL_SPICE::set_param_by_name(std::string Name, std::string Value)
601 if (OPT::case_insensitive) {
602 notstd::to_lower(&Name);
603 }else{
605 _params.set(Name, Value);
606 Set_param_by_name(Name, ::to_string(_params[Name].e_val(1,scope())));
609 /*--------------------------------------------------------------------------*/
610 void MODEL_SPICE::precalc_first()
612 MODEL_CARD::precalc_first();
614 Set_param_by_name(_key, "1");
616 // push down parameters into raw spice data
617 for (PARAM_LIST::iterator i = _params.begin(); i != _params.end(); ++i) {
618 if (i->second.has_hard_value()) {
619 try {
620 Set_param_by_name(i->first, ::to_string(i->second.e_val(1,scope())));
621 }catch (Exception_No_Match&) {
622 error(bTRACE, long_label() + ": bad parameter: " + i->first + ", ignoring\n");
624 }else{
628 init_ckt();
629 if (info.DEVsetup) {
630 assert_model_raw();
631 int ok = info.DEVsetup(NULL, &_spice_model._gen, ckt(), NULL);
632 assert(ok == OK);
633 }else{untested();
636 /*--------------------------------------------------------------------------*/
637 void MODEL_SPICE::set_dev_type(const std::string& new_type)
639 assert_model_raw();
641 //_spice_model._gen.set_mod_name(short_label());
642 std::string s = short_label();
643 char* p = new char[s.length()+1]; //BUG//memory leak
644 s.copy(p, std::string::npos);
645 p[s.length()] = '\0';
646 _spice_model._gen.GENmodName = p;
648 _key = new_type;
649 if (OPT::case_insensitive) {
650 notstd::to_lower(&_key);
651 }else{
654 /*--------------------------------------------------------------------------*/
655 bool MODEL_SPICE::param_is_printable(int i)const
657 assert(i < MODEL_SPICE::param_count());
658 if (i >= MODEL_CARD::param_count()) {
659 return _params.is_printable(MODEL_SPICE::param_count() - 1 - i);
660 }else{
661 return MODEL_CARD::param_is_printable(i);
664 /*--------------------------------------------------------------------------*/
665 std::string MODEL_SPICE::param_name(int i)const
667 assert(i < MODEL_SPICE::param_count());
668 if (i >= MODEL_CARD::param_count()) {
669 return _params.name(MODEL_SPICE::param_count() - 1 - i);
670 }else{
671 return MODEL_CARD::param_name(i);
674 /*--------------------------------------------------------------------------*/
675 std::string MODEL_SPICE::param_name(int i, int j)const
676 {untested();
677 assert(i < MODEL_SPICE::param_count());
678 if (j == 0) {untested();
679 return param_name(i);
680 }else if (i >= MODEL_CARD::param_count()) {untested();
681 return "";
682 }else{untested();
683 return MODEL_CARD::param_name(i);
686 /*--------------------------------------------------------------------------*/
687 std::string MODEL_SPICE::param_value(int i)const
689 assert(i < MODEL_SPICE::param_count());
690 if (i >= MODEL_CARD::param_count()) {
691 return _params.value(MODEL_SPICE::param_count() - 1 - i);
692 }else{
693 return MODEL_CARD::param_value(i);
696 /*--------------------------------------------------------------------------*/
697 void MODEL_SPICE::set_param_by_index(int, std::string&, int)
698 {untested();
699 unreachable();
701 /*--------------------------------------------------------------------------*/
702 /*--------------------------------------------------------------------------*/
703 DEV_SPICE::DEV_SPICE()
704 :STORAGE(),
705 _inst(),
706 _modelname(""),
707 _model(NULL),
708 _spice_model(NULL),
709 _nodes(),
710 _matrix(),
711 _matrix_core(),
712 _i0(),
713 _i1(),
714 _v1(),
715 _states_1(NULL),
716 _num_states(0),
717 _maxEqNum(0)
719 attach_common(&Default_Params);
720 std::fill_n(&_inst_space, sizeof(INSTANCE), '\0');
721 assert_instance();
724 int* node = spice_nodes();
725 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
726 node[ii] = SPICE_INVALID_NODE;
729 _n = _nodes;
730 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
731 assert(!(_n[ii].n_()));
734 for (uint_t ii = 0; ii < matrix_nodes()+OFFSET; ++ii) {
735 _matrix[ii] = _matrix_core[ii];
736 assert(_matrix[ii]);
739 assert(OPT::_keep_time_steps <= 8);
740 for (uint_t ii=0; ii<8; ++ii) {
741 _states[ii] = NULL;
744 ++_count;
745 assert_instance();
747 /*--------------------------------------------------------------------------*/
748 DEV_SPICE::DEV_SPICE(const DEV_SPICE& p)
749 :STORAGE(p),
750 _inst(p._inst),
751 _modelname(p._modelname),
752 _model(p._model),
753 _spice_model(p._spice_model),
754 _nodes(),
755 _matrix(),
756 _matrix_core(),
757 _i0(),
758 _i1(),
759 _v1(),
760 _states_1(NULL),
761 _num_states(p._num_states),
762 _maxEqNum(p._maxEqNum)
764 assert_instance();
767 int* node = spice_nodes();
768 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
769 assert(node[ii] == SPICE_INVALID_NODE);
772 _n = _nodes;
773 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
774 _n[ii] = p._n[ii];
777 for (uint_t ii = 0; ii < matrix_nodes()+OFFSET; ++ii) {
778 _matrix[ii] = _matrix_core[ii];
779 assert(_matrix[ii]);
782 assert(OPT::_keep_time_steps <= 8);
783 for (uint_t ii=0; ii<8; ++ii) {
784 _states[ii] = NULL;
787 ++_count;
788 assert_instance();
790 /*--------------------------------------------------------------------------*/
791 DEV_SPICE::~DEV_SPICE()
793 assert_instance();
795 --_count;
797 if (_states[0]) {
798 // regular instances
799 for (uint_t ii=0; ii<OPT::_keep_time_steps; ++ii) {
800 assert(_states[ii]);
801 delete [] _states[ii];
803 assert(_states_1);
804 delete [] _states_1;
805 }else{
806 // prototype
807 assert(OPT::_keep_time_steps <= 8);
808 for (uint_t ii=0; ii<8; ++ii) {
809 assert(!_states[ii]);
811 assert(!_states_1);
812 assert(!_spice_model);
815 /*--------------------------------------------------------------------------*/
816 void DEV_SPICE::set_dev_type(const std::string& new_type)
818 _modelname = new_type;
820 /*--------------------------------------------------------------------------*/
821 void DEV_SPICE::Set_param_by_name(std::string Name, std::string new_value)
823 assert_instance();
824 assert(info.DEVpublic.numInstanceParms);
825 assert(info.DEVpublic.instanceParms);
826 assert(info.DEVparam);
828 int num_params = *(info.DEVpublic.numInstanceParms);
829 for (int i = 0; i < num_params; ++i) {
830 IFparm Parms = info.DEVpublic.instanceParms[i];
831 if (Name == Parms.keyword) {
832 Set_param_by_index(i, new_value, 0);
833 return;
834 }else{
837 mutable_common()->COMMON_COMPONENT::Set_param_by_name(Name, new_value);
839 /*--------------------------------------------------------------------------*/
840 void DEV_SPICE::set_param_by_name(std::string Name, std::string Value)
842 if (OPT::case_insensitive) {
843 notstd::to_lower(&Name);
844 }else{
846 COMPONENT::set_param_by_name(Name, Value);
847 COMMON_PARAMLIST* c = dynamic_cast<COMMON_PARAMLIST*>(mutable_common());
848 assert(c);
849 Set_param_by_name(Name, ::to_string(c->_params[Name].e_val(1,scope())));
851 /*--------------------------------------------------------------------------*/
852 void DEV_SPICE::Set_param_by_index(int i, std::string& new_value, int offset)
854 assert_instance();
855 assert(info.DEVpublic.numInstanceParms);
856 assert(info.DEVpublic.instanceParms);
857 assert(info.DEVparam);
859 int num_params = *(info.DEVpublic.numInstanceParms);
860 if (i < num_params) {
861 IFparm Parms = info.DEVpublic.instanceParms[i];
862 IFvalue Value;
863 IFVA v(&Value, Parms.dataType);
864 v = new_value;
865 #ifdef JSPICE3
866 int ok = info.DEVparam(ckt(), Parms.id, &Value, &_spice_instance, NULL);
867 #else
868 int ok = info.DEVparam(Parms.id, &Value, &_spice_instance, NULL);
869 #endif
870 assert(ok == OK);
871 }else{untested();
872 STORAGE::set_param_by_index(i-num_params, new_value, offset+num_params);
874 assert_instance();
876 /*--------------------------------------------------------------------------*/
877 void DEV_SPICE::expand()
879 assert_instance();
880 assert(info.DEVsetup);
882 STORAGE::expand();
884 init_ckt();
886 { //-------- fix up external nodes
887 int* node = spice_nodes();
888 for (uint_t ii = 0; ii < net_nodes(); ++ii) {
889 node[ii] = ii+OFFSET;
891 if (UNCONNECTED_NODES == uGROUND) {
892 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {itested();
893 node[ii] = ii+OFFSET;
895 }else if (UNCONNECTED_NODES == uFLOAT) {
896 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {untested();
897 node[ii] = SPICE_UNCONNECTED_NODE;
899 }else{
900 assert(UNCONNECTED_NODES == uDISALLOW);
901 assert(min_nodes() == max_nodes());
902 assert(net_nodes() == max_nodes());
904 ckt()->CKTmaxEqNum = max_nodes();
906 for (uint_t ii = max_nodes(); ii < matrix_nodes(); ++ii) {
907 node[ii] = 0;
911 { //------- attach model, set up matrix pointers
912 _model = dynamic_cast<const MODEL_SPICE*>(find_model(_modelname));
913 if (!_model) {
914 throw Exception_Model_Type_Mismatch(long_label(), _modelname, DEVICE_TYPE);
915 }else{
916 SMPmatrix* matrix = reinterpret_cast<SMPmatrix*>(_matrix);
917 _num_states = 0;
919 _spice_instance.GENmodPtr = &(_model->_spice_model._gen);
920 _spice_model = &(_model->_spice_model);
921 SPICE_MODEL_DATA spice_model_copy(*_spice_model);
922 spice_model_copy._gen.GENinstances = &_spice_instance;
923 //-------------
924 int ok = info.DEVsetup(matrix, &(spice_model_copy._gen), ckt(), &_num_states);
925 // memory pointer setup, and sets _num_states
926 // undesired side effects: sets values, messes up model
927 //-------------
928 assert(ok == OK);
929 _maxEqNum = ckt()->CKTmaxEqNum;
930 trace1("expand", ckt()->CKTmaxEqNum);
931 assert_model_unlocalized();
935 //-------- allocate state vectors
936 if (!_states[0]) {
937 for (uint_t ii=0; ii<OPT::_keep_time_steps; ++ii) {
938 assert(!_states[ii]);
939 _states[ii] = new double[_num_states];
941 _states_1 = new double[_num_states];
942 }else{
944 for (uint_t ii=0; ii<OPT::_keep_time_steps; ++ii) {
945 assert(_states[ii]);
946 std::fill_n(_states[ii], _num_states, 0);
948 assert(_states_1);
949 std::fill_n(_states_1, _num_states, 0);
951 //std::fill_n(_i1, matrix_nodes()+OFFSET, 0);
952 //std::fill_n(_v1, matrix_nodes()+OFFSET, 0);
954 //-------- fix up internal nodes
955 if (_sim->is_first_expand()) {
956 int start_internal = 0;
957 if (UNCONNECTED_NODES == uGROUND) {
958 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {itested();
959 _n[ii].set_to_ground(this);
961 start_internal = max_nodes();
962 }else{
963 assert(UNCONNECTED_NODES == uDISALLOW || UNCONNECTED_NODES == uFLOAT);
964 start_internal = net_nodes();
966 assert(start_internal != 0);
968 int* node = spice_nodes(); // treat as array
969 char fake_name[] = "a";
970 for (uint_t ii = start_internal; ii < matrix_nodes(); ++ii) {
971 if (node[ii] >= start_internal+OFFSET) {
972 // real internal node
973 _n[ii].new_model_node("." + short_label() + '_' + fake_name, this);
974 trace3("new int", node[ii], _n[ii].t_(), short_label());
975 assert(_n[ii].n_());
976 }else if (node[ii] >= 0+OFFSET) {
977 // collapsed to an external node
978 trace2("collapse", node[ii], _n[ii].t_());
979 _n[ii] = _n[node[ii]-OFFSET];
980 assert(_n[ii].n_());
981 }else{
982 // not assigned
983 trace2("not used", node[ii], _n[ii].t_());
984 assert(!_n[ii].n_());
986 ++(*fake_name);
989 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
990 trace2((_n[ii].n_()) ? (_n[ii].n_()->short_label().c_str()) : ("NULL"), ii, node[ii]);
993 // This could be one loop, but doing it this way gives more info.
994 for (uint_t ii = 0; ii < min_nodes(); ++ii) {
995 assert(_n[ii].n_());
997 for (uint_t ii = min_nodes(); ii < net_nodes(); ++ii) {
998 assert(_n[ii].n_());
1000 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {itested();
1001 //assert(_n[ii].n_());
1003 for (uint_t ii = max_nodes(); ii < matrix_nodes(); ++ii) {
1004 assert(_n[ii].n_() || !node[ii]);
1006 }else{untested();
1008 assert_model_unlocalized();
1009 assert_instance();
1011 /*--------------------------------------------------------------------------*/
1012 void DEV_SPICE::precalc_last()
1014 assert(_model);
1015 assert_instance();
1016 assert(info.DEVsetup);
1018 STORAGE::precalc_last();
1019 init_ckt();
1021 // push down parameters into spice data
1022 COMMON_PARAMLIST* c = dynamic_cast<COMMON_PARAMLIST*>(mutable_common());
1023 assert(c);
1024 for (PARAM_LIST::iterator i = c->_params.begin(); i != c->_params.end(); ++i) {
1025 if (i->second.has_hard_value()) {
1026 try {
1027 Set_param_by_name(i->first, ::to_string(i->second.e_val(1,scope())));
1028 }catch (Exception_No_Match&) {
1029 error(bTRACE, long_label() + ": bad parameter: " + i->first + ", ignoring\n");
1031 }else{
1035 int* node = spice_nodes(); // treat as array //
1036 int node_stash[MATRIX_NODES]; //
1037 notstd::copy_n(node, matrix_nodes(), node_stash); // save the real nodes
1039 { //-------- fix up external nodes, again ........
1040 // put the originals back, so DEVsetup can mess them up the same as last time
1041 int* node = spice_nodes();
1042 for (uint_t ii = 0; ii < net_nodes(); ++ii) {
1043 node[ii] = ii+OFFSET;
1045 if (UNCONNECTED_NODES == uGROUND) {
1046 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {itested();
1047 node[ii] = ii+OFFSET;
1049 }else if (UNCONNECTED_NODES == uFLOAT) {
1050 for (uint_t ii = net_nodes(); ii < max_nodes(); ++ii) {untested();
1051 node[ii] = SPICE_UNCONNECTED_NODE;
1053 }else{
1054 assert(UNCONNECTED_NODES == uDISALLOW);
1055 assert(min_nodes() == max_nodes());
1056 assert(net_nodes() == max_nodes());
1058 ckt()->CKTmaxEqNum = max_nodes();
1060 for (uint_t ii = max_nodes(); ii < matrix_nodes(); ++ii) {
1061 node[ii] = 0;
1066 SMPmatrix* matrix = reinterpret_cast<SMPmatrix*>(_matrix);
1067 int num_states_garbage = 0;
1069 assert(_spice_model == &(_model->_spice_model));
1070 SPICE_MODEL_DATA spice_model_copy(*_spice_model);
1071 spice_model_copy._gen.GENinstances = &_spice_instance;
1073 int ok = info.DEVsetup(matrix, &(spice_model_copy._gen), ckt(), &num_states_garbage);
1075 assert(ok == OK);
1076 assert(num_states_garbage == _num_states);
1077 trace3("precalc", _maxEqNum, ckt()->CKTmaxEqNum, (_maxEqNum == ckt()->CKTmaxEqNum));
1078 assert(_maxEqNum == ckt()->CKTmaxEqNum);
1079 notstd::copy_n(node_stash, matrix_nodes(), node); // put back real nodes
1080 // hopefully, the matrix pointers are the same as last time!
1082 assert(!is_constant());
1083 assert_model_unlocalized();
1084 assert_instance();
1086 /*--------------------------------------------------------------------------*/
1087 void DEV_SPICE::internal_precalc()
1089 update_ckt();
1091 if (info.DEVtemperature) {
1092 assert_instance();
1094 assert_model_unlocalized();
1095 _spice_model->_gen.GENinstances = &_spice_instance;
1096 assert_model_localized();
1098 // ELEMENT::precalc(); .. don't call .. more analysis needed
1099 //-----
1100 int ok = info.DEVtemperature(&(_spice_model->_gen), ckt());
1101 assert(ok == OK);
1102 //-----
1103 set_converged();
1104 _spice_model->_gen.GENinstances = NULL;
1106 assert(!is_constant());
1107 assert_instance();
1108 }else{
1110 assert_model_unlocalized();
1112 /*--------------------------------------------------------------------------*/
1113 void DEV_SPICE::tr_advance()
1115 STORAGE::tr_advance();
1116 update_ckt();
1118 double* t = _states[OPT::_keep_time_steps-1];
1119 for (uint_t ii = OPT::_keep_time_steps-1; ii > 0; --ii) {
1120 _states[ii] = _states[ii-1];
1122 _states[0] = t;
1123 notstd::copy_n(_states[1], _num_states, _states[0]);
1125 /*--------------------------------------------------------------------------*/
1126 void DEV_SPICE::tr_regress()
1128 ELEMENT::tr_regress();
1129 update_ckt();
1131 /*--------------------------------------------------------------------------*/
1132 bool DEV_SPICE::tr_needs_eval()const
1134 if (is_q_for_eval()) {
1135 return false;
1136 }else if (!converged()) {
1137 return true;
1138 }else if (_sim->is_advance_iteration()) {
1139 return true;
1140 }else if (_time[1] == 0) {
1141 //BUG// needed for ngspice jfet, but not for spice3f5 jfet
1142 return true;
1143 }else{
1144 int* node = spice_nodes();
1145 // check the node voltages, reference to ground
1146 for (uint_t ii=0; ii<matrix_nodes(); ++ii) {
1147 if ((node[ii] != SPICE_INVALID_NODE)
1148 && !conchk(_v1[node[ii]], _n[ii].v0(), 0, OPT::reltol*OPT::bypasstol)) {
1149 return true;
1150 }else{
1153 // check the node voltages, reference to each other
1154 for (uint_t ii=0; ii<matrix_nodes(); ++ii) {
1155 for (uint_t jj=0; jj<ii; ++jj) {
1156 if ((node[ii] != SPICE_INVALID_NODE) && (node[jj] != SPICE_INVALID_NODE)
1157 && !conchk((_v1[node[ii]] - _v1[node[jj]]),
1158 (_n[ii].v0() - _n[jj].v0()),
1159 0, OPT::reltol*OPT::bypasstol)) {
1160 return true;
1161 }else{
1165 return false;
1168 /*--------------------------------------------------------------------------*/
1169 // MODEINITFLOAT = normal iteration
1170 // MODEINITPRED = 1st iter at a new time point
1171 // MODEINITTRAN = 1st iter at 1st time pt after initial DC
1172 // MODEINITFIX = like FLOAT, but honor options like "off"
1173 // MODEINITJCT = initial guess
1174 // MODEINITSMSIG = like FLOAT, but setup for small signal, don't load arrays
1175 /*--------------------------------------------------------------------------*/
1176 bool DEV_SPICE::do_tr()
1178 assert_instance();
1179 assert(info.DEVload);
1180 assert(_num_states >= 0);
1182 localize_ckt();
1184 assert_model_unlocalized();
1185 _spice_model->_gen.GENinstances = &_spice_instance;
1186 assert_model_localized();
1188 if (_sim->analysis_is_tran_dynamic()) {
1189 if ((_time[1] == 0) && _sim->is_first_iteration()) {
1190 ckt()->CKTmode = MODETRAN | MODEINITTRAN;
1191 }else{
1192 ckt()->CKTmode = MODETRAN | MODEINITFLOAT;
1194 }else{
1195 if (_sim->analysis_is_tran_static()) {
1196 ckt()->CKTmode = MODETRANOP;
1197 }else if (_sim->analysis_is_tran_restore()) {
1198 ckt()->CKTmode = MODETRAN;
1199 }else if (_sim->command_is_dc()) {
1200 ckt()->CKTmode = MODEDCTRANCURVE;
1201 }else if (_sim->command_is_op()) {
1202 ckt()->CKTmode = MODEDCOP;
1203 }else{unreachable();
1204 ckt()->CKTmode = 0;
1206 if (_sim->uic_now()) {
1207 ckt()->CKTmode |= MODEINITFIX;
1208 ckt()->CKTmode |= MODEUIC;
1209 }else if (_sim->is_initial_step()) {
1210 ckt()->CKTmode |= MODEINITJCT;
1211 }else{
1212 ckt()->CKTmode |= MODEINITFLOAT;
1216 { // copy in
1217 int* node = spice_nodes();
1218 assert(ckt()->CKTrhsOld == _v1);
1219 std::fill_n(_v1, matrix_nodes()+OFFSET, 0);
1220 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
1221 if (node[ii] != SPICE_INVALID_NODE) {
1222 _v1[node[ii]] = _n[ii].v0();
1223 }else{
1227 { // clear for copy out
1228 ckt()->CKTtroubleElt = NULL;
1229 ckt()->CKTnoncon = 0;
1231 assert(ckt()->CKTrhs == _i0);
1232 std::fill_n(_i0, matrix_nodes()+OFFSET, 0);
1234 for (uint_t ii = 0; ii < matrix_nodes()+OFFSET; ++ii) {
1235 for (uint_t jj = 0; jj < matrix_nodes()+OFFSET; ++jj) {
1236 _matrix[ii][jj].real(0.);
1241 // do the work -- it might also do convergence checking, might not
1242 //-----
1243 info.DEVload(&(_spice_model->_gen), ckt());
1244 //-----
1245 // convergence check -- gnucap method
1246 unsigned trouble = ckt()->CKTnoncon;
1247 double ramptol = 1e12*OPT::gmin;
1248 ramptol=1;
1249 set_converged(!trouble);
1250 for (int ii = 0; ii < _num_states; ++ii) {
1251 if(converged()){
1252 bool c = conchk(_states[0][ii], _states_1[ii], OPT::abstol*ramptol);
1253 if(!c) trouble = 10;
1254 set_converged(c);
1256 trace3("", ii, _states_1[ii], _states[0][ii]);
1257 _states_1[ii] = _states[0][ii];
1259 for (uint_t ii = 0; converged() && ii < matrix_nodes()+OFFSET; ++ii) {
1260 bool c = conchk(_i0[ii], _i1[ii], OPT::abstol*ramptol);
1261 if(!c) trouble = 20;
1262 set_converged(c);
1264 for (uint_t ii = 0; converged() && ii < matrix_nodes()+OFFSET; ++ii) {
1265 for (uint_t jj = 0; converged() && jj < matrix_nodes()+OFFSET; ++jj) {
1266 bool c = conchk(_matrix[ii][jj].real(), _matrix[ii][jj].imag(), OPT::abstol*ramptol);
1267 if(!c) trouble = 30;
1268 set_converged(c);
1271 #ifndef NDEBUG
1272 _trouble = trouble;
1273 #endif
1275 // convergence check -- Spice method
1276 // not sure if it is worth the effort
1277 if (converged() && info.DEVconvTest) {
1278 ckt()->CKTnoncon = 0;
1279 ckt()->CKTrhs = _v1; // Spice overlaps _i0 with _v1 as CKTrhs
1280 info.DEVconvTest(&(_spice_model->_gen), ckt());
1281 set_converged(ckt()->CKTnoncon == 0);
1282 }else{
1283 // either no separate test or already failed
1286 bool needs_load = !converged();
1287 for (uint_t ii = 0; !needs_load && ii < matrix_nodes()+OFFSET; ++ii) {
1288 needs_load = !conchk(_i0[ii], _i1[ii], 0, OPT::reltol*OPT::loadtol);
1290 for (uint_t ii = 0; !needs_load && ii < matrix_nodes()+OFFSET; ++ii) {
1291 for (uint_t jj = 0; !needs_load && jj < matrix_nodes()+OFFSET; ++jj) {
1292 needs_load = !conchk(_matrix[ii][jj].real(), _matrix[ii][jj].imag(),
1293 0, OPT::reltol*OPT::loadtol);
1297 if (needs_load) {
1298 q_load();
1299 }else{
1302 assert_model_localized();
1303 _spice_model->_gen.GENinstances = NULL;
1304 assert_model_unlocalized();
1305 return converged();
1307 /*--------------------------------------------------------------------------*/
1308 void DEV_SPICE::tr_load()
1310 #ifndef NDEBUG
1311 if (_loaditer == _sim->iteration_tag()) {untested();
1312 error(bDANGER, long_label() + " internal error: double load\n");
1314 _loaditer = _sim->iteration_tag();
1315 #endif
1317 int ihit[MATRIX_NODES+OFFSET];
1318 int jhit[MATRIX_NODES+OFFSET];
1320 std::fill_n(ihit, matrix_nodes()+OFFSET, 0);
1321 std::fill_n(jhit, matrix_nodes()+OFFSET, 0);
1323 int* node = spice_nodes();
1324 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
1325 int ni = node[ii];
1326 if (ni && !ihit[ni]) {
1327 ihit[ni] = 1;
1328 int nii = ni-OFFSET;
1329 trace4("", ii, ni, _i0[ni], _i1[ni]);
1330 tr_load_source_point(_n[ii], &(_i0[ni]), &(_i1[ni]));
1331 for (uint_t jj = 0; jj < matrix_nodes(); ++jj) {
1332 int nj = node[jj];
1333 if (nj && jhit[nj] != ni) {
1334 jhit[nj] = ni;
1335 int njj = nj-OFFSET;
1336 trace2("", jj, nj);
1337 trace2("", _matrix[nii][njj].real(), _matrix[nii][njj].imag());
1338 tr_load_point(_n[ii], _n[jj], &reinterpret_cast<double(&)[2]>(_matrix[nii][njj])[0] , &reinterpret_cast<double(&)[2]>(_matrix[nii][njj])[1]);
1339 }else{
1340 trace2("skip", jj, nj);
1343 }else{
1344 trace2("=========skip", ii, ni);
1348 /*--------------------------------------------------------------------------*/
1349 void DEV_SPICE::tr_unload()
1350 {untested();incomplete();
1352 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {untested();
1353 for (uint_t jj = 0; jj < matrix_nodes(); ++jj) {untested();
1354 _matrix[ii][jj].real(0);
1357 _sim->mark_inc_mode_bad();
1358 tr_load();
1360 /*--------------------------------------------------------------------------*/
1361 TIME_PAIR DEV_SPICE::tr_review()
1363 // not calling STORAGE::tr_review();
1365 if (info.DEVtrunc) {
1366 localize_ckt();
1367 assert_instance();
1368 //q_accept();
1370 assert_model_unlocalized();
1371 _spice_model->_gen.GENinstances = &_spice_instance;
1372 assert_model_localized();
1374 ckt()->CKTtroubleElt = NULL;
1375 double timestep = NEVER;
1376 //-----
1377 info.DEVtrunc(&(_spice_model->_gen), ckt(), &timestep);
1378 //-----
1380 _time_by._error_estimate = tr_review_check_and_convert(timestep);
1381 _time_by._event = NEVER;
1383 _spice_model->_gen.GENinstances = NULL;
1384 assert_model_unlocalized();
1385 return _time_by;
1386 }else{
1387 return TIME_PAIR(NEVER,NEVER);
1390 /*--------------------------------------------------------------------------*/
1391 void DEV_SPICE::tr_accept()
1393 assert_model_unlocalized();
1394 _spice_model->_gen.GENinstances = &_spice_instance;
1395 assert_model_localized();
1397 //STORAGE::tr_accept(); // doesn't do anything
1399 if (_sim->analysis_is_dcop() || _sim->analysis_is_ac()) {
1400 localize_ckt();
1402 // don't copy in
1403 assert(ckt()->CKTrhsOld == _v1);
1404 // _v1 already has correct values
1405 // _n[ii].v0() is not correct -- may have been cleared
1407 ckt()->CKTmode = MODEINITSMSIG;
1408 info.DEVload(&(_spice_model->_gen), ckt());
1409 }else{itested();
1411 assert_model_localized();
1412 _spice_model->_gen.GENinstances = NULL;
1413 assert_model_unlocalized();
1415 /*--------------------------------------------------------------------------*/
1416 double DEV_SPICE::tr_probe_num(const std::string& x)const
1418 localize_ckt();
1419 assert_ckt_up_to_date(ckt());
1420 assert_instance();
1422 // all of the "states" in state array
1423 int num_probe_states = std::min(_num_states, int(sizeof(state_names)/sizeof(std::string)));
1424 for (int ii=0; ii<num_probe_states && state_names[ii]!=""; ++ii) {
1425 if (Umatch(x, state_names[ii] + ' ')) {
1426 return _states[0][ii];
1427 }else{
1431 #ifndef NDEBUG
1432 if (Umatch(x, "trouble ")) {
1433 return _trouble;
1435 #endif
1437 if (info.DEVask) {
1438 // data that Spice has, through "ask"
1439 assert(info.DEVpublic.numInstanceParms);
1440 assert(info.DEVpublic.instanceParms);
1442 for (int ii=0; ii<(*(info.DEVpublic.numInstanceParms)); ++ii) {
1443 IFparm Parms = info.DEVpublic.instanceParms[ii];
1444 int datatype = Parms.dataType;
1445 if (datatype & IF_ASK && Umatch(x, std::string(Parms.keyword) + ' ')) {
1446 IFvalue v;
1447 int ok = info.DEVask(ckt(), &_spice_instance, Parms.id, &v, NULL);
1448 if (ok == OK) {
1449 switch (datatype & 0xff) {
1450 case IF_FLAG:
1451 case IF_INTEGER:
1452 return v.iValue;
1453 case IF_REAL:
1454 return v.rValue;
1455 case IF_COMPLEX:
1456 case IF_STRING:
1457 default:
1458 // make believe it is not a match
1459 incomplete();
1460 break; // break switch, continue loop
1462 }else{untested();
1463 // match, but not useful here.
1464 assert(errMsg);
1465 free(errMsg);
1466 errMsg = NULL;
1467 assert(errRtn);
1468 errRtn = NULL;
1469 // maybe there is more than one match, so continue loop
1471 }else{
1472 // really not a match, keep looking
1475 }else{untested();
1476 // no DEVask .. can't do anything.
1478 return STORAGE::tr_probe_num(x);
1480 /*--------------------------------------------------------------------------*/
1481 void DEV_SPICE::ac_begin()
1483 STORAGE::ac_begin();
1484 internal_precalc();
1485 tr_accept();
1487 /*--------------------------------------------------------------------------*/
1488 void DEV_SPICE::do_ac()
1490 if (info.DEVacLoad || info.DEVpzLoad) {
1491 assert_instance();
1492 assert(_num_states >= 0);
1494 assert_model_unlocalized();
1495 _spice_model->_gen.GENinstances = &_spice_instance;
1496 assert_model_localized();
1498 localize_ckt();
1499 ckt()->CKTmode = MODEAC;
1500 ckt()->CKTomega = _sim->_jomega.imag();
1502 // clear for copy out
1503 ckt()->CKTtroubleElt = NULL;
1504 std::fill_n(_i0, matrix_nodes()+OFFSET, 0);
1505 std::fill_n(_i1, matrix_nodes()+OFFSET, 0);
1506 for (uint_t ii = 0; ii < matrix_nodes()+OFFSET; ++ii) {
1507 for (uint_t jj = 0; jj < matrix_nodes()+OFFSET; ++jj) {
1508 _matrix[ii][jj] = 0;
1512 if (info.DEVpzLoad) {
1513 info.DEVpzLoad(&(_spice_model->_gen), ckt(), reinterpret_cast<SPcomplex*>(&_sim->_jomega));
1514 }else if (info.DEVacLoad) {
1515 info.DEVacLoad(&(_spice_model->_gen), ckt());
1516 }else{unreachable();
1517 // nothing
1520 assert_model_localized();
1521 _spice_model->_gen.GENinstances = NULL;
1522 assert_model_unlocalized();
1523 }else{untested();
1524 // there is no acLoad function
1527 /*--------------------------------------------------------------------------*/
1528 void DEV_SPICE::ac_load()
1530 if (info.DEVacLoad) {
1531 assert_ckt_up_to_date(ckt());
1533 int ihit[MATRIX_NODES+OFFSET];
1534 int jhit[MATRIX_NODES+OFFSET];
1536 std::fill_n(ihit, matrix_nodes()+OFFSET, 0);
1537 std::fill_n(jhit, matrix_nodes()+OFFSET, 0);
1539 int* node = spice_nodes();
1540 for (uint_t ii = 0; ii < matrix_nodes(); ++ii) {
1541 int ni = node[ii];
1542 if (ni && !ihit[ni]) {
1543 ihit[ni] = 1;
1544 int nii = ni-OFFSET;
1545 trace3("", ii, ni, nii);
1546 ac_load_source_point(_n[ii], COMPLEX(_i0[ni], _i1[ni]));
1547 for (uint_t jj = 0; jj < matrix_nodes(); ++jj) {
1548 int nj = node[jj];
1549 if (nj && jhit[nj] != ni) {
1550 jhit[nj] = ni;
1551 int njj = nj-OFFSET;
1552 trace3("", jj, nj, njj);
1553 trace2("", _matrix[nii][njj].real(), _matrix[nii][njj].imag());
1554 ac_load_point(_n[ii], _n[jj], _matrix[nii][njj]);
1555 }else{
1556 trace2("skip", jj, nj);
1559 }else{
1560 trace2("=========skip", ii, ni);
1563 }else{
1564 // there is no acLoad function
1567 /*--------------------------------------------------------------------------*/
1568 /*--------------------------------------------------------------------------*/
1569 extern "C" {
1570 // needed to satisfy references. Supposedly unreachable. Stubs.
1571 char *errMsg = NULL;
1572 char *errRtn = NULL;
1573 char* tmalloc(int size) {itested(); return static_cast<char*>(calloc(size,1));}
1574 char* trealloc(char*, int) {untested();incomplete(); return NULL;} //DEVnoise
1575 void txfree(char *ptr) {
1576 if (ptr) {itested();
1577 free(ptr);
1578 }else{untested();
1582 static class FT_CURCKT : public circ {
1583 TSKtask junk;
1584 public:
1585 FT_CURCKT() {
1586 junk.jobs = NULL;
1587 ci_curTask = reinterpret_cast<char*>(&junk);
1588 //::ft_curckt = this;
1590 } stupid_ft_circ_pointer_to_pointer_hack;
1592 circ *ft_curckt = &stupid_ft_circ_pointer_to_pointer_hack;
1594 IFuid CKTnodName(CKTcircuit*,int) {incomplete();return IFuid();} //DEVsenPrint
1596 double D1i2F1(double, double, double) {incomplete(); return NOT_VALID;} //DEVdisto
1597 double D1i3F1(double, double, double, double, double, double) {incomplete(); return NOT_VALID;}
1598 double D1iF12(double, double, double, double, double) {incomplete(); return NOT_VALID;}
1599 double D1i2F12(double, double, double, double, double, double, double, double, double,
1600 double) {incomplete(); return NOT_VALID;}
1601 double D1n2F1(double, double, double) {incomplete(); return NOT_VALID;}
1602 double D1n3F1(double, double, double, double, double, double) {incomplete(); return NOT_VALID;}
1603 double D1nF12(double, double, double, double, double) {incomplete(); return NOT_VALID;}
1604 double D1n2F12(double, double, double, double, double, double, double, double, double,
1605 double) {incomplete(); return NOT_VALID;}
1606 double DFn2F1(double, double, double, double, double, double, double, double, double,
1607 double, double, double) {incomplete(); return NOT_VALID;}
1608 double DFi2F1(double, double, double, double, double, double, double, double, double,
1609 double, double, double) {incomplete(); return NOT_VALID;}
1610 double DFi3F1(double, double, double, double, double, double, double, double, double,
1611 double, double, double, double, double, double, double, double, double,
1612 double, double, double, double, double, double, double, double, double,
1613 double) {incomplete(); return NOT_VALID;}
1614 double DFn3F1(double, double, double, double, double, double, double, double, double,
1615 double, double, double, double, double, double, double, double, double,
1616 double, double, double, double, double, double, double, double, double,
1617 double) {incomplete(); return NOT_VALID;}
1618 double DFnF12(double, double, double, double, double, double, double, double,
1619 double, double, double, double, double, double, double, double,
1620 double, double) {incomplete(); return NOT_VALID;}
1621 double DFiF12(double, double, double, double, double, double, double, double,
1622 double, double, double, double, double, double, double, double,
1623 double, double) {incomplete(); return NOT_VALID;}
1624 struct DpassStr; //DEVdisto
1625 double DFn2F12(DpassStr*) {incomplete(); return NOT_VALID;}
1626 double DFi2F12(DpassStr*) {incomplete(); return NOT_VALID;}
1627 struct Dderivs;
1628 void AtanDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1629 void CosDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1630 void CubeDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1631 void DivDeriv(Dderivs*, Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1632 void EqualDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1633 void ExpDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1634 void InvDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1635 void MultDeriv(Dderivs*, Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1636 void PlusDeriv(Dderivs*, Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1637 void PowDeriv(Dderivs*, Dderivs*, double) {incomplete();} //DEVdisto
1638 void SqrtDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1639 void TanDeriv(Dderivs*, Dderivs*) {incomplete();} //DEVdisto
1640 void TimesDeriv(Dderivs*, Dderivs*, double) {incomplete();} //DEVdisto
1641 #ifdef JSPICE3
1642 double Nintegrate(double, double, double, GENERIC*) {incomplete(); return NOT_VALID;} //DEVnoise
1643 #else
1644 double Nintegrate(double, double, double, Ndata*) {incomplete(); return NOT_VALID;} //DEVnoise
1645 #endif
1646 void NevalSrc(double*, double*, CKTcircuit*, int, int, int, double) {incomplete();} //DEVnoise
1647 void NevalSrc2(double*, double*, CKTcircuit*, int, int, int, double, double) {incomplete();}
1648 //------------------------------------------------
1649 // should be constants, but spice wants them to be variables.
1650 double CONSTroot2(sqrt(2.));
1651 double CONSTvt0(P_CELSIUS0*P_K_Q);
1652 double CONSTKoverQ(P_K_Q);
1653 double CONSTe(M_E);
1654 //------------------------------------------------
1655 // ngspice baggage
1656 int ARCHme = 0;
1657 // jspice baggage
1658 IFsimulator *ft_sim;
1659 //------------------------------------------------
1660 //------------------------------------------------
1661 int IFerror(int flags, char* format, IFuid* names) /* output an error or warning message */
1662 {itested();
1663 static struct mesg {
1664 const char *string;
1665 long flag;
1666 } msgs[] = {
1667 { "Warning", ERR_WARNING } ,
1668 { "Fatal error", ERR_FATAL } ,
1669 { "Panic", ERR_PANIC } ,
1670 { "Note", ERR_INFO } ,
1671 { NULL, 0 }
1674 struct mesg *m;
1675 char buf[10000], *s, *bptr;
1676 int nindex = 0;
1678 for (m = msgs; m->flag; m++) {
1679 if (flags & m->flag) {
1680 error(bDANGER, "%s: ", m->string);
1681 }else{
1685 for (s = format, bptr = buf; *s; s++) {
1686 if (*s == '%' && (s == format || *(s-1) != '%') && *(s+1) == 's') {
1687 if (names[nindex]) {
1688 strcpy(bptr, reinterpret_cast<char*>(names[nindex]));
1689 }else{
1690 strcpy(bptr, "(null)");
1692 bptr += strlen(bptr);
1693 s++;
1694 nindex++;
1695 } else {
1696 *bptr++ = *s;
1699 *bptr = '\0';
1700 switch (flags) {
1701 case ERR_WARNING:error(bWARNING,buf); break;
1702 case ERR_FATAL: error(bDANGER, buf); throw Exception("");
1703 case ERR_PANIC: error(bDANGER, buf); throw Exception("");
1704 case ERR_INFO: error(bTRACE, buf); break;
1705 default: error(bDANGER, buf); break;
1707 return 0;
1709 void internalerror(char *message)
1710 {untested();
1711 error(bDANGER, "internal error: %s\n", message);
1714 #ifdef NGSPICE_17
1715 int CKTinst2Node(void*, void*, int, CKTnode**, IFuid*)
1716 {untested();incomplete();
1717 return 10;
1719 #endif
1720 #ifdef JSPICE3
1721 static IFfrontEnd fe = {
1722 NULL, //int ((*IFnewUid)()); /* create a new UID in the circuit */ noise, urcsetup
1723 NULL, //int ((*IFpauseTest)()); /* should we stop now? */ noisean.c only
1724 NULL, //double ((*IFseconds)()); /* what time is it? */ bjtdisto unused ifdef only (unused)
1725 IFerror, //int ((*IFerror)()); /* output an error or warning message */ temp, setup
1726 NULL,
1727 NULL,
1728 NULL,
1729 NULL,
1730 NULL
1732 #else
1733 static IFfrontEnd fe = {
1734 NULL, //int ((*IFnewUid)()); /* create a new UID in the circuit */ noise, urcsetup
1735 NULL, //int ((*IFdelUid)()); /* create a new UID in the circuit */ not used
1736 NULL, //int ((*IFpauseTest)()); /* should we stop now? */ noisean.c only
1737 NULL, //double ((*IFseconds)()); /* what time is it? */ bjtdisto unused ifdef only (unused)
1738 IFerror, //int ((*IFerror)()); /* output an error or warning message */ temp, setup
1739 NULL, //int ((*OUTpBeginPlot)()); /* start pointwise output plot */ noisean.c only
1740 NULL, //int ((*OUTpData)()); /* data for pointwise plot */ noisean.c only
1741 NULL, //int ((*OUTwBeginPlot)()); /* start windowed output plot */ not used
1742 NULL, //int ((*OUTwReference)()); /* independent vector for windowed plot */ not used
1743 NULL, //int ((*OUTwData)()); /* data for windowed plot */ not used
1744 NULL, //int ((*OUTwEnd)()); /* signal end of windows */ not used
1745 NULL, //int ((*OUTendPlot)()); /* end of plot */ not used
1746 NULL, //int ((*OUTbeginDomain)()); /* start nested domain */ not used
1747 NULL, //int ((*OUTendDomain)()); /* end nested domain */ not used
1748 NULL //int ((*OUTattributes)()); /* specify output attributes of node */ noisean.c only
1750 #endif
1751 IFfrontEnd* SPfrontEnd = &fe;
1752 //------------------------------------------------
1753 //------------------------------------------------
1754 int CKTsetBreak(CKTcircuit* ckt, double time)
1755 {untested();
1756 if (time < ckt->CKTminBreak) {untested();
1757 ckt->CKTminBreak = time;
1758 }else{untested();
1760 return OK;
1762 //------------------------------------------------
1763 void CKTterr(int qcap, CKTcircuit* ckt,double *time_step)
1765 assert_ckt_localized(ckt);
1767 std::valarray<FPOLY1> q(OPT::_keep_time_steps);
1769 for (uint_t ii = 0; ii < OPT::_keep_time_steps; ++ii) {
1770 assert(ckt->CKTstates[ii]);
1771 q[ii].x = NOT_VALID;
1772 q[ii].f0 = ckt->CKTstates[ii][qcap];
1773 q[ii].f1 = NOT_VALID;
1776 DEV_SPICE* d = reinterpret_cast<DEV_SPICE*>(ckt->CKTstat);
1777 assert(d);
1778 assert(dynamic_cast<DEV_SPICE*>(d));
1780 *time_step = std::min(d->tr_review_trunc_error(&q[0]), *time_step);
1782 //------------------------------------------------
1783 int NIintegrate(CKTcircuit* ckt,double* geq,double* ceq,double cap,int qcap)
1784 { //-- used by DEVload (not DC)
1785 assert_ckt_localized(ckt);
1787 METHOD method;
1788 if (ckt->CKTorder == 1) {
1789 method = mEULER;
1790 }else{
1791 assert(ckt->CKTtimePoints[1] != 0.);
1792 assert(ckt->CKTorder == 2);
1793 method = mTRAP;
1796 std::valarray<FPOLY1> q(OPT::_keep_time_steps);
1797 std::valarray<FPOLY1> i(OPT::_keep_time_steps);
1799 for (uint_t ii = 0; ii < OPT::_keep_time_steps; ++ii) {
1800 assert(ckt->CKTstates[ii]);
1801 q[ii].x = NOT_VALID;
1802 q[ii].f0 = ckt->CKTstates[ii][qcap];
1803 q[ii].f1 = cap;
1804 trace3("", ii, q[ii].f0, q[ii].f1);
1805 i[ii].x = NOT_VALID;
1806 i[ii].f0 = ckt->CKTstates[ii][qcap+1];
1807 i[ii].f1 = q[ii].f1 * ckt->CKTag[0];
1808 trace3("", ii, i[ii].f0, i[ii].f1);
1809 assert(q[ii].f0 == q[ii].f0);
1810 assert(q[ii].f1 == q[ii].f1);
1811 assert(i[ii].f0 == i[ii].f0);
1812 assert(i[ii].f1 == i[ii].f1);
1815 i[0] = differentiate(&q[0], &i[0], ckt->CKTtimePoints, method);
1816 assert(i[0].f0 == i[0].f0);
1817 assert(i[0].f1 == i[0].f1);
1818 trace2("", i[0].f0, i[0].f1);
1820 ckt->CKTstates[0][qcap+1] = i[0].f0;
1822 assert(ckt->CKTdelta != 0. || (ckt->CKTag[0] == 0. && i[0].f0 == 0.));
1823 *ceq = i[0].f0 - q[0].f0 * ckt->CKTag[0];
1824 *geq = i[0].f1;
1825 assert(*ceq == *ceq);
1826 assert(*geq == *geq);
1827 trace2("", *ceq, *geq);
1828 return OK;
1830 //------------------------------------------------
1831 //------------------------------------------------
1832 int CKTmkVolt(CKTcircuit* ckt, CKTnode** n, IFuid, char*)
1833 { // get a new node number. -- used by DEVsetup
1834 assert_ckt_initialized(ckt);
1835 assert(n);
1836 static CKTnode n_static; // always used only on next line
1837 *n = &n_static; // so reuse static structure
1838 (*n)->number = ((ckt->CKTmaxEqNum)++)+OFFSET;
1839 trace1(__FUNCTION__, (*n)->number);
1840 // local number (- == internal) only number is used
1841 return OK;
1843 int CKTmkCur(CKTcircuit* ckt, CKTnode** n, IFuid i, char* c)
1844 {untested();
1845 return CKTmkVolt(ckt, n, i, c);
1847 //------------------------------------------------
1848 int CKTdltNNum(void*,int)
1849 {untested(); // complement to CKTmkVolt. -- used by DEVunsetup
1850 // deletes what was new in CKTmkVolt
1851 // Nothing, because of no alloc there.
1852 return OK;
1854 //------------------------------------------------
1855 //------------------------------------------------
1856 double* SMPmakeElt(SMPmatrix* mm, int r, int c)
1857 { // returns a pointer m[r][c] -- used by DEVsetup
1858 //trace2("", r, c);
1859 assert(mm);
1860 if (r == 0 || c == 0) {
1861 static double trash;
1862 trash = 0;
1863 return &trash;
1864 }else{
1865 assert(r >= 0+OFFSET);
1866 assert(r < int(MATRIX_NODES)+OFFSET);
1867 assert(c >= 0+OFFSET);
1868 assert(c < int(MATRIX_NODES)+OFFSET);
1869 COMPLEX** m = reinterpret_cast<COMPLEX**>(mm);
1870 assert(m);
1871 assert(m[r-OFFSET]);
1872 return reinterpret_cast<double*>(&(m[r-OFFSET][c-OFFSET]));
1875 //------------------------------------------------
1876 #ifdef JSPICE3
1877 int IFnewUid(GENERIC*,IFuid*,IFuid,char*,int,GENERIC**) {incomplete(); return 0;}
1878 int INPpName(char*,IFvalue*,GENERIC*,int,GENERIC*) {incomplete(); return 0;}
1879 char *INPdevErr(char *) {incomplete(); return NULL;}
1880 char *INPerror(int) {incomplete(); return NULL;}
1881 spREAL *spGetElement(char* s, int r, int c) {return SMPmakeElt(s,r,c);}
1882 char *INPerrCat(char *, char *) {incomplete(); return NULL;}
1883 int INPgndInsert(GENERIC*,char**,INPtables*,GENERIC**) {incomplete(); return 0;}
1884 char * INPdevParse(char**,GENERIC*,int,GENERIC*,double*,int*,INPtables*) {incomplete(); return NULL;}
1885 char *INPgetMod(GENERIC*,char*,INPmodel**,INPtables*) {incomplete(); return NULL;}
1886 int INPgetTok(char**,char**,int) {incomplete(); return 0;}
1887 int INPlookMod(char*) {incomplete(); return 0;}
1888 int INPtermInsert(GENERIC*,char**,INPtables*,GENERIC**) {incomplete(); return 0;}
1889 int INPinsert(char**,INPtables*) {incomplete(); return 0;}
1890 char *copy(char*) {incomplete(); return NULL;}
1891 int NIsum(CKTcircuit*,double*,int) {incomplete(); return 0;}
1892 double INPevaluate(char**,int*,int) {incomplete(); return NOT_VALID;}
1893 IFvalue *INPgetValue(GENERIC*,char**,int,INPtables*) {incomplete(); return NULL;}
1894 #endif
1896 /*--------------------------------------------------------------------------*/
1897 /*--------------------------------------------------------------------------*/
1898 // Verify that the layout of complex is as Spice assumes.
1899 // This is not guaranteed by the standard, but is believed to always be true.
1900 static struct COMPLEX_TEST {
1901 COMPLEX_TEST() {
1902 COMPLEX x;
1903 COMPLEX* px = &x;
1904 double* prx = &reinterpret_cast<double(&)[2]>(x)[0];
1905 double* pix = &reinterpret_cast<double(&)[2]>(x)[1];
1906 assert(reinterpret_cast<void*>(prx) == reinterpret_cast<void*>(px));
1907 assert(reinterpret_cast<void*>(pix-1) == reinterpret_cast<void*>(px));
1909 ~COMPLEX_TEST() {
1911 } complex_test;
1912 /*--------------------------------------------------------------------------*/
1913 /*--------------------------------------------------------------------------*/
1914 int MODEL_SPICE::_count = -1;
1915 int DEV_SPICE::_count = -1;
1917 static DEV_SPICE p0;
1918 static DISPATCHER<CARD>::INSTALL
1919 d0(&device_dispatcher, std::string(SPICE_LETTER) + "|" + DEVICE_TYPE, &p0);
1921 static MODEL_SPICE p1(&p0);
1922 static DISPATCHER<MODEL_CARD>::INSTALL
1923 d1(&model_dispatcher, MODEL_TYPE, &p1);
1924 /*--------------------------------------------------------------------------*/
1925 /*--------------------------------------------------------------------------*/
1926 // vim:ts=8:sw=2:noet: