1 /*$Id: u_prblst.cc,v 26.137 2010/04/10 02:37:33 al Exp $ -*- C++ -*-
2  * Copyright (C) 2001 Albert Davis
3  * Author: Albert Davis <aldavis@gnu.org>
4  *
5  * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6  *
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.
11  *
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.
16  *
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  * probe list functions
23  */
24 //testing=script,sparse 2006.07.14
25 #include "e_cardlist.h"
26 #include "e_node.h"
27 #include "e_card.h"
28 #include "u_nodemap.h"
29 #include "ap.h"
30 #include "u_prblst.h"
31 /*--------------------------------------------------------------------------*/
purge(CKT_BASE * brh)32 void PROBE_LISTS::purge(CKT_BASE* brh)
33 {
34   for (int i = 0;  i < sCOUNT;  ++i) {
35     alarm[i].remove_one(brh);
36     plot[i] .remove_one(brh);
37     print[i].remove_one(brh);
38     store[i].remove_one(brh);
39   }
40 }
41 /*--------------------------------------------------------------------------*/
listing(const std::string & label) const42 void PROBELIST::listing(const std::string& label)const
43 {
44   IO::mstdout.form("%-7s", label.c_str());
45   for (const_iterator p = begin();  p != end();  ++p) {
46     IO::mstdout << ' ' << p->label();
47     if (p->range() != 0.) {untested();
48       IO::mstdout.setfloatwidth(5)
49 	<< '(' << p->lo() << ',' << p->hi() << ')';
50     }else{
51     }
52   }
53   IO::mstdout << '\n';
54 }
55 /*--------------------------------------------------------------------------*/
clear(void)56 void PROBELIST::clear(void)
57 {
58   erase(begin(), end());
59 }
60 /*--------------------------------------------------------------------------*/
61 /* check for match
62  * called by STL remove, below
63  * both are needed to support different versions of STL
64  */
operator ==(const PROBE & prb,const std::string & par)65 bool operator==(const PROBE& prb, const std::string& par)
66 {
67   return wmatch(prb.label(), par);
68 }
operator !=(const PROBE & prb,const std::string & par)69 bool operator!=(const PROBE& prb, const std::string& par)
70 {untested();
71   //return !wmatch(prb.label(), par);
72   return !(prb == par);
73 }
74 /*--------------------------------------------------------------------------*/
75 /* remove a complete probe, extract from CS
76  * wild card match  ex:  vds(m*)
77  */
remove_list(CS & cmd)78 void PROBELIST::remove_list(CS& cmd)
79 {
80   unsigned mark = cmd.cursor();
81   std::string parameter(cmd.ctos(TOKENTERM) + '(');
82   int paren = cmd.skip1b('(');
83   parameter += cmd.ctos(TOKENTERM) + ')';
84   paren -= cmd.skip1b(')');
85   if (paren != 0) {untested();
86     cmd.warn(bWARNING, "need )");
87   }else if (parameter.empty()) {untested();
88     cmd.warn(bWARNING, "what's this?");
89   }else{
90   }
91 
92   iterator x = remove(begin(), end(), parameter);
93   if (x != end()) {
94     erase(x, end());
95   }else{itested();
96     cmd.warn(bWARNING, mark, "probe isn't set -- can't remove");
97   }
98 }
99 /*--------------------------------------------------------------------------*/
100 /* check for match
101  * called by STL remove, below
102  * both are needed to support different versions of stl
103  */
operator ==(const PROBE & prb,const CKT_BASE * brh)104 bool operator==(const PROBE& prb, const CKT_BASE* brh)
105 {
106   return (prb.object() == brh);
107 }
operator !=(const PROBE & prb,const CKT_BASE * brh)108 bool operator!=(const PROBE& prb, const CKT_BASE* brh)
109 {untested();
110   return (prb.object() != brh);
111 }
112 /*--------------------------------------------------------------------------*/
113 /* remove a brh from a PROBELIST
114  * removes all probes on brh
115  */
remove_one(CKT_BASE * brh)116 void PROBELIST::remove_one(CKT_BASE *brh)
117 {
118   assert(brh);
119   erase(remove(begin(), end(), brh), end());
120   // remove .. removes all that match and compacts the list, leaving blanks at the end
121   // erase  .. shortens, throw away the blanks at the end
122 }
123 /*--------------------------------------------------------------------------*/
124 /* add_list: add a "list" of probes, usually only one
125  * This means possibly several probes with a single parameter
126  * like "v(r*)" meaning all resistors
127  * but not "v(r4) v(r5)" which has two parameters.
128  * It also takes care of setting the range for plot or alarm.
129  */
add_list(CS & cmd)130 void PROBELIST::add_list(CS& cmd)
131 {
132   int oldcount = size();
133   std::string what(cmd.ctos(TOKENTERM));/* parameter */
134   if (what.empty()) {untested();
135     cmd.warn(bWARNING, "need a probe");
136   }else{
137   }
138 
139   int paren = cmd.skip1b('(');		/* device, node, etc. */
140   if (cmd.umatch("nodes ")) {
141     // all nodes
142     add_all_nodes(what);
143   }else if (cmd.umatch("0")) {
144     // node 0 means system stuff
145     push_new_probe(what, 0);
146   }else if (cmd.is_alnum() || cmd.match1("*?")) {
147     // branches or named nodes
148     unsigned here1 = cmd.cursor();
149     bool found_something = add_branches(cmd.ctos(),what,&CARD_LIST::card_list);
150     if (!found_something) {
151       cmd.warn(bWARNING, here1, "no match");
152     }else{
153     }
154     for (;;) {
155       // a list, as in v(r1,r2,r3) or v(1,2,3)
156       if (!(cmd.is_alnum() || cmd.match1("*?"))) {
157 	break;
158       }else{
159       }
160       unsigned here2 = cmd.cursor();
161       found_something = add_branches(cmd.ctos(),what,&CARD_LIST::card_list);
162       if (!found_something) {itested();
163 	cmd.reset(here2);
164 	break;
165       }else{
166       }
167     }
168   }else{itested();
169     cmd.warn(bDANGER, "need device or node");
170   }
171   paren -= cmd.skip1b(')');
172   if (paren != 0) {itested();
173     cmd.warn(bWARNING, "need )");
174   }else{
175   }
176 
177   if (cmd.skip1b('(')) {	/* range for plotting and alarm */
178     double lo = cmd.ctof();
179     double hi = cmd.ctof();
180     for (iterator p = begin() + oldcount;  p != end();  ++p) {
181       p->set_limit(lo,hi);
182     }
183     if (!cmd.skip1b(')')) {untested();
184       cmd.check(bWARNING, "need )");
185     }else{
186     }
187   }else{
188   }
189 }
190 /*--------------------------------------------------------------------------*/
push_new_probe(const std::string & param,const CKT_BASE * object)191 void PROBELIST::push_new_probe(const std::string& param,const CKT_BASE* object)
192 {
193   bag.push_back(PROBE(param, object));
194 }
195 /*--------------------------------------------------------------------------*/
add_all_nodes(const std::string & what)196 void PROBELIST::add_all_nodes(const std::string& what)
197 {
198   for (NODE_MAP::const_iterator
199        i = CARD_LIST::card_list.nodes()->begin();
200        i != CARD_LIST::card_list.nodes()->end();
201        ++i) {
202     if ((i->first != "0") && (i->first.find('.') == std::string::npos)) {
203       NODE* node = i->second;
204       assert (node);
205       push_new_probe(what, node);
206     }else{
207     }
208   }
209 }
210 /*--------------------------------------------------------------------------*/
211 /* add_branches: add net elements to probe list
212  * 	all matching a label with wildcards
213  */
add_branches(const std::string & device,const std::string & param,const CARD_LIST * scope)214 bool PROBELIST::add_branches(const std::string&device,
215 			     const std::string&param,
216 			     const CARD_LIST* scope)
217 {
218   assert(scope);
219   bool found_something = false;
220 
221   std::string::size_type dotplace = device.find_first_of(".");
222   if (dotplace != std::string::npos) {
223     // has a dot, look deeper
224     { // forward (Verilog style)
225       std::string dev = device.substr(dotplace+1, std::string::npos);
226       std::string container = device.substr(0, dotplace);
227       for (CARD_LIST::const_iterator
228 	     i = scope->begin();  i != scope->end();  ++i) {
229 	CARD* card = *i;
230 	if (card->is_device()
231 	    && card->subckt()
232 	    && wmatch(card->short_label(), container)) {
233 	  found_something |= add_branches(dev, param, card->subckt());
234 	}else{
235 	}
236       }
237     }
238     { // reverse (ACS style)
239       dotplace = device.find_last_of(".");
240       std::string container = device.substr(dotplace+1, std::string::npos);
241       std::string dev = device.substr(0, dotplace);
242       for (CARD_LIST::const_iterator
243 	     i = scope->begin();  i != scope->end();  ++i) {
244 	CARD* card = *i;
245 	if (card->is_device()
246 	    && card->subckt()
247 	    && wmatch(card->short_label(), container)) {
248 	  found_something |= add_branches(dev, param, card->subckt());
249 	}else{
250 	}
251       }
252     }
253   }else{
254     // no dots, look here
255     if (device.find_first_of("*?") != std::string::npos) {
256       // there's a wild card.  do linear search for all
257       { // nodes
258 	for (NODE_MAP::const_iterator
259 	     i = scope->nodes()->begin();
260 	     i != scope->nodes()->end();
261 	     ++i) {
262 	  if (i->first != "0") {
263 	    NODE* node = i->second;
264 	    assert (node);
265 	    if (wmatch(node->short_label(), device)) {
266 	      push_new_probe(param, node);
267 	      found_something = true;
268 	    }else{
269 	    }
270 	  }else{
271 	  }
272 	}
273       }
274       {// components
275 	for (CARD_LIST::const_iterator
276 	     i = scope->begin();  i != scope->end();  ++i) {
277 	  CARD* card = *i;
278 	  if (wmatch(card->short_label(), device)) {
279 	    push_new_probe(param, card);
280 	    found_something = true;
281 	  }else{
282 	  }
283 	}
284       }
285     }else{
286       // no wild card.  do fast search for one
287       { // nodes
288 	NODE* node = (*scope->nodes())[device];
289 	if (node) {
290 	  push_new_probe(param, node);
291 	  found_something = true;
292 	}else{
293 	}
294       }
295       { //components
296 	CARD_LIST::const_iterator i = scope->find_(device);
297 	if (i != scope->end()) {
298 	  push_new_probe(param, *i);
299 	  found_something = true;
300 	}else{
301 	}
302       }
303     }
304   }
305 
306   return found_something;
307 }
308 /*--------------------------------------------------------------------------*/
309 /*--------------------------------------------------------------------------*/
310