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¶m,
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