bump to -rc12
[gnucap-felix.git] / lib / e_base.cc
blob2b9f96a94c5681a48887899174389a11704cb778
1 /*$Id: e_base.cc 2015/02/05 al $ -*- 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 * Base class for "cards" in the circuit description file
24 //testing=script 2014.07.04
25 #include "ap.h"
26 #include "u_sim_data.h"
27 #include "m_wave.h"
28 #include "u_prblst.h"
29 #include "u_xprobe.h"
30 #include "e_base.h"
31 #include <typeinfo>
32 #include "ap.h"
33 /*--------------------------------------------------------------------------*/
34 static char fix_case(char c)
36 return ((OPT::case_insensitive) ? (static_cast<char>(tolower(c))) : (c));
38 /*--------------------------------------------------------------------------*/
39 double CKT_BASE::tr_probe_num(const std::string&)const {return NOT_VALID;}
40 double CKT_BASE::tt_probe_num(const std::string&)const {return NOT_VALID;}
41 XPROBE CKT_BASE::ac_probe_ext(const std::string&)const {return XPROBE(NOT_VALID, mtNONE);}
42 XPROBE CKT_BASE::sens_probe_ext(const std::string&)const {
43 trace1("CKT_BASE::sens_probe_ext", typeid(*this).name());
44 return XPROBE(NOT_VALID, mtNONE);
46 /*--------------------------------------------------------------------------*/
47 SIM_DATA* CKT_BASE::_sim = NULL;
48 PROBE_LISTS* CKT_BASE::_probe_lists = NULL;
49 /*--------------------------------------------------------------------------*/
50 double CKT_BASE::tt_behaviour = 0;
51 double CKT_BASE::tr_behaviour_del = 0;
52 double CKT_BASE::tr_behaviour_rel = 0;
53 double CKT_BASE::tt_behaviour_del = 0;
54 double CKT_BASE::tt_behaviour_rel = 0;
55 /*--------------------------------------------------------------------------*/
56 CKT_BASE::~CKT_BASE()
58 trace1("~CKT_BASE", _probes);
59 if (_probes == 0) {
60 }else if (!_probe_lists) {untested();
61 }else if (!_sim) {untested();
62 }else{
63 _probe_lists->purge(this);
66 /*--------------------------------------------------------------------------*/
67 const std::string CKT_BASE::long_label()const
69 trace0("CKT_BASE::long_label");
70 //incomplete();
71 std::string buffer(short_label());
72 //for (const CKT_BASE* brh = owner(); exists(brh); brh = brh->owner()) {untested();
73 // buffer += '.' + brh->short_label();
74 //}
75 return buffer;
77 /*--------------------------------------------------------------------------*/
78 bool CKT_BASE::help(CS& Cmd, OMSTREAM& Out)const
80 if (help_text() != "") {
81 unsigned here = Cmd.cursor();
82 std::string keyword;
83 Cmd >> keyword;
84 CS ht(CS::_STRING, help_text());
85 if (keyword == "") {
86 Out << ht.get_to("@@");
87 }else if (ht.scan("@@" + keyword + ' ')) {
88 Out << ht.get_to("@@");
89 }else if (keyword == "?") {
90 while (ht.scan("@@")) {
91 Out << " " << ht.get_to("\n") << '\n';
93 }else{
94 Cmd.warn(bWARNING, here, "no help on subtopic " + Cmd.substr(here));
96 return true;
97 }else{
98 return false;
101 /*--------------------------------------------------------------------------*/
102 double CKT_BASE::probe_num(const std::string& what)const
104 trace2("CKT_BASE::probe_num", what, long_label());
105 double x;
106 if (_sim->analysis_is_tt()){
107 x = tt_probe_num(what) ;
108 }else if (_sim->analysis_is_ac()) {
109 x = ac_probe_num(what);
110 }else if (_sim->analysis_is_sens()) {
111 x = ac_probe_num(what);
112 }else{
113 x = tr_probe_num(what);
115 // FIXME, HACK
116 return x; // (std::abs(x)>=1) ? x : floor(x/OPT::floor + .5) * OPT::floor;
118 /*--------------------------------------------------------------------------*/
119 double CKT_BASE::ac_probe_num(const std::string& what)const
121 trace1("CKT_BASE::ac_probe_num", what);
122 size_t length = what.length();
123 mod_t modifier = mtNONE;
124 bool want_db = false;
125 char parameter[BUFLEN+1];
126 strcpy(parameter, what.c_str());
128 if (length > 2 && Umatch(&parameter[length-2], "db ")) {
129 want_db = true;
130 length -= 2;
132 if (length > 1) { // selects modifier based on last letter of parameter
133 switch (fix_case(parameter[length-1])) {
134 case 'm': modifier = mtMAG; length--; break;
135 case 'p': modifier = mtPHASE; length--; break;
136 case 'r': modifier = mtREAL; length--; break;
137 case 'i': modifier = mtIMAG; length--; break;
138 default: modifier = mtNONE; break;
141 parameter[length] = '\0'; // chop
143 // "p" is "what" with the modifier chopped off.
144 // Try that first.
145 XPROBE xp(0);
146 if (_sim->analysis_is_ac()) {
147 xp = XPROBE(ac_probe_ext(parameter));
148 } else {
149 xp = XPROBE(sens_probe_ext(parameter));
152 // If we don't find it, try again with the full string.
153 if (!xp.exists()) {
154 xp = ac_probe_ext(what);
155 if (!xp.exists()) {
156 // Still didn't find anything. Print "??".
157 }else{untested();
158 // The second attempt worked.
161 return xp(modifier, want_db);
163 /*--------------------------------------------------------------------------*/
164 /*static*/ double CKT_BASE::probe(const CKT_BASE *This, const std::string& what)
166 if (This) {
167 return This->probe_num(what);
168 }else{ /* return 0 if doesn't exist */
169 return 0.0; /* happens when optimized models */
170 } /* don't have all parts */
172 /*--------------------------------------------------------------------------*/
173 /*static*/ WAVE_LIST& CKT_BASE::create_waves(const std::string& coll_name)
175 assert(_sim);
176 _sim->_label = coll_name;
177 return _sim->_waves[coll_name];
179 /*--------------------------------------------------------------------------*/
180 /*static*/ WAVE_LIST* CKT_BASE::find_waves(const std::string& coll_name)
182 std::map<std::string,WAVE_LIST>::iterator i;
183 string n = coll_name;
184 if (0 && OPT::case_insensitive) { untested();
185 notstd::to_upper(&n);
186 }else{
188 i = _sim->_waves.find(n);
189 if(i!=_sim->_waves.end()){
190 return &i->second;
191 }else{
192 return NULL;
195 /*--------------------------------------------------------------------------*/
196 /*static*/ WAVE& CKT_BASE::create_wave(const std::string& wave_name, std::string coll_name)
198 assert(_sim);
199 if(coll_name==""){untested();
200 coll_name = _sim->_label;
201 }else{
203 std::string n = wave_name;
204 if (OPT::case_insensitive) {
205 notstd::to_upper(&n);
206 }else{ untested();
208 return _sim->_waves[coll_name][n];
210 /*--------------------------------------------------------------------------*/
211 /*static*/ WAVE* CKT_BASE::find_wave(const std::string& probe_name)
213 trace2("find_wave", probe_name, _sim->_label);
214 std::map<std::string,WAVE>* w = &_sim->_waves[_sim->_label];
215 std::map<std::string,WAVE>::iterator i;
216 string n = probe_name;
217 if (OPT::case_insensitive) {
218 notstd::to_upper(&n);
219 }else{ untested();
221 i = w->find(n);
222 if(i!=_sim->_waves[_sim->_label].end()){
223 return &i->second;
224 }else{
226 std::string prefix;
227 std::string suffix;
228 CS cmd(CS::_STRING, probe_name);
229 prefix = cmd.ctos(":");
231 if(_sim->_waves.find(prefix) == _sim->_waves.end()) {
232 return NULL;
233 }else{
236 cmd >> ":";
237 suffix = cmd.ctos("");
238 if (OPT::case_insensitive) {
239 notstd::to_upper(&suffix);
240 }else{untested();
242 trace0(("\"" + prefix + "\":\"" + suffix + "\"").c_str());
243 i = _sim->_waves[prefix].find(suffix);
244 if(i!=_sim->_waves[prefix].end()){
245 return &i->second;
248 return NULL;
250 /*--------------------------------------------------------------------------*/
251 bool CKT_BASE::operator!=(const std::string& n)const {return strcasecmp(_label.c_str(),n.c_str())!=0;}
252 /*--------------------------------------------------------------------------*/
253 /*--------------------------------------------------------------------------*/
254 // vim:ts=8:sw=2:noet: