viminfo
[gnucap-felix.git] / apps / lang_spectre.cc
blob2355077a078895e8160d60eae5a6bd6b26bc7a32
1 /*$Id: lang_spectre.cc,v 26.137 2010/04/10 02:37:05 al Exp $ -*- 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 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.
22 #include "globals.h"
23 #include "c_comand.h"
24 #include "d_dot.h"
25 #include "d_coment.h"
26 #include "d_subckt.h"
27 #include "e_model.h"
28 #include "u_lang.h"
29 /*--------------------------------------------------------------------------*/
30 namespace {
31 /*--------------------------------------------------------------------------*/
32 class LANG_SPECTRE : public LANGUAGE {
33 public:
34 ~LANG_SPECTRE() {itested();}
35 std::string name()const {return "spectre";}
36 bool case_insensitive()const {return false;}
37 UNITS units()const {return uSI;}
39 public: // override virtual, used by callback
40 std::string arg_front()const {return " ";}
41 std::string arg_mid()const {return "=";}
42 std::string arg_back()const {return "";}
44 public: // override virtual, called by commands
45 void parse_top_item(CS&, CARD_LIST*);
46 DEV_COMMENT* parse_comment(CS&, DEV_COMMENT*);
47 DEV_DOT* parse_command(CS&, DEV_DOT*);
48 MODEL_CARD* parse_paramset(CS&, MODEL_CARD*);
49 MODEL_SUBCKT* parse_module(CS&, MODEL_SUBCKT*);
50 COMPONENT* parse_instance(CS&, COMPONENT*);
51 std::string find_type_in_string(CS&);
53 private: // override virtual, called by print_item
54 void print_paramset(OMSTREAM&, const MODEL_CARD*);
55 void print_module(OMSTREAM&, const MODEL_SUBCKT*);
56 void print_instance(OMSTREAM&, const COMPONENT*);
57 void print_comment(OMSTREAM&, const DEV_COMMENT*);
58 void print_command(OMSTREAM& o, const DEV_DOT* c);
59 private: // local
60 void print_args(OMSTREAM&, const CARD*);
61 } lang_spectre;
63 DISPATCHER<LANGUAGE>::INSTALL
64 d(&language_dispatcher, lang_spectre.name(), &lang_spectre);
65 /*--------------------------------------------------------------------------*/
66 /*--------------------------------------------------------------------------*/
67 static void parse_type(CS& cmd, CARD* x)
69 assert(x);
70 std::string new_type;
71 cmd >> new_type;
72 x->set_dev_type(new_type);
74 /*--------------------------------------------------------------------------*/
75 static void parse_args(CS& cmd, CARD* x)
77 assert(x);
79 unsigned here = 0;
80 while (cmd.more() && !cmd.stuck(&here)) {
81 std::string name = cmd.ctos("=", "", "");
82 cmd >> '=';
83 std::string value = cmd.ctos("", "(", ")");
84 try{
85 x->set_param_by_name(name, value);
86 }catch (Exception_No_Match&) {untested();
87 cmd.warn(bDANGER, here, x->long_label() + ": bad parameter " + name + " ignored");
91 /*--------------------------------------------------------------------------*/
92 static void parse_label(CS& cmd, CARD* x)
94 assert(x);
95 std::string my_name;
96 cmd >> my_name;
97 x->set_label(my_name);
99 /*--------------------------------------------------------------------------*/
100 static void parse_ports(CS& cmd, COMPONENT* x)
102 assert(x);
104 if (cmd >> '(') {
105 int index = 0;
106 while (cmd.is_alnum()) {
107 unsigned here = cmd.cursor();
108 try{
109 std::string value;
110 cmd >> value;
111 x->set_port_by_index(index++, value);
112 }catch (Exception_Too_Many& e) {untested();
113 cmd.warn(bDANGER, here, e.message());
116 cmd >> ')';
117 }else{
118 unsigned here = cmd.cursor();
119 OPT::language->find_type_in_string(cmd);
120 unsigned stop = cmd.cursor();
121 cmd.reset(here);
123 int index = 0;
124 while (cmd.cursor() < stop) {
125 here = cmd.cursor();
126 try{
127 std::string value;
128 cmd >> value;
129 x->set_port_by_index(index++, value);
130 }catch (Exception_Too_Many& e) {untested();
131 cmd.warn(bDANGER, here, e.message());
136 /*--------------------------------------------------------------------------*/
137 /*--------------------------------------------------------------------------*/
138 DEV_COMMENT* LANG_SPECTRE::parse_comment(CS& cmd, DEV_COMMENT* x)
140 assert(x);
141 x->set(cmd.fullstring());
142 return x;
144 /*--------------------------------------------------------------------------*/
145 DEV_DOT* LANG_SPECTRE::parse_command(CS& cmd, DEV_DOT* x)
147 assert(x);
148 x->set(cmd.fullstring());
149 CARD_LIST* scope = (x->owner()) ? x->owner()->subckt() : &CARD_LIST::card_list;
151 cmd.reset().skipbl();
152 if ((cmd >> "model |simulator |parameters |subckt ")) {
153 cmd.reset();
154 CMD::cmdproc(cmd, scope);
155 }else{
156 std::string label;
157 cmd >> label;
159 if (label != "-") {
160 unsigned here = cmd.cursor();
161 std::string command;
162 cmd >> command;
163 cmd.reset(here);
164 std::string file_name = label + '.' + command;
165 std::string s = cmd.tail() + " > " + file_name;
166 CS augmented_cmd(CS::_STRING, s);
167 CMD::cmdproc(augmented_cmd, scope);
168 }else{
169 CMD::cmdproc(cmd, scope);
172 delete x;
173 return NULL;
175 /*--------------------------------------------------------------------------*/
176 MODEL_CARD* LANG_SPECTRE::parse_paramset(CS& cmd, MODEL_CARD* x)
178 assert(x);
179 cmd.reset().skipbl();
180 cmd >> "model ";
181 parse_label(cmd, x);
182 parse_type(cmd, x);
183 parse_args(cmd, x);
184 cmd.check(bWARNING, "what's this?");
185 return x;
187 /*--------------------------------------------------------------------------*/
188 MODEL_SUBCKT* LANG_SPECTRE::parse_module(CS& cmd, MODEL_SUBCKT* x)
190 assert(x);
192 // header
193 cmd.reset().skipbl();
194 cmd >> "subckt ";
195 parse_label(cmd, x);
196 parse_ports(cmd, x);
198 // body
199 for (;;) {
200 cmd.get_line("spectre-subckt>");
202 if (cmd >> "ends ") {
203 break;
204 }else{
205 new__instance(cmd, x, x->subckt());
208 return x;
210 /*--------------------------------------------------------------------------*/
211 COMPONENT* LANG_SPECTRE::parse_instance(CS& cmd, COMPONENT* x)
213 cmd.reset();
214 parse_label(cmd, x);
215 parse_ports(cmd, x);
216 parse_type(cmd, x);
217 parse_args(cmd, x);
218 cmd.check(bWARNING, "what's this?");
219 return x;
221 /*--------------------------------------------------------------------------*/
222 std::string LANG_SPECTRE::find_type_in_string(CS& cmd)
224 // known to be not always correct
226 cmd.reset().skipbl();
227 unsigned here = 0;
228 std::string type;
229 if ((cmd >> "*|//")) {itested();
230 assert(here == 0);
231 type = "dev_comment";
232 }else if ((cmd >> "model |simulator |parameters |subckt ")) {
233 // type is first, it's a control statement
234 type = cmd.trimmed_last_match();
235 }else if (cmd.reset().skiparg().match1("(") && cmd.scan(")")) {
236 // node list surrounded by parens
237 // type follows
238 here = cmd.cursor();
239 cmd.reset(here);
240 cmd >> type;
241 }else if (cmd.reset().scan("=")) {itested();
242 // back up two, by starting over
243 cmd.reset().skiparg();
244 unsigned here1 = cmd.cursor();
245 cmd.skiparg();
246 unsigned here2 = cmd.cursor();
247 cmd.skiparg();
248 unsigned here3 = cmd.cursor();
249 while (here2 != here3 && !cmd.match1('=')) {
250 cmd.skiparg();
251 here1 = here2;
252 here2 = here3;
253 here3 = cmd.cursor();
255 here = here1;
256 cmd.reset(here);
257 cmd >> type;
258 }else{
259 // type is second
260 cmd.reset().skiparg();
261 here = cmd.cursor();
262 cmd.reset(here);
263 cmd >> type;
265 cmd.reset(here);
266 return type;
268 /*--------------------------------------------------------------------------*/
269 void LANG_SPECTRE::parse_top_item(CS& cmd, CARD_LIST* Scope)
271 cmd.get_line("gnucap-spectre>");
272 new__instance(cmd, NULL, Scope);
274 /*--------------------------------------------------------------------------*/
275 /*--------------------------------------------------------------------------*/
276 void LANG_SPECTRE::print_args(OMSTREAM& o, const CARD* x)
278 assert(x);
279 o << ' ';
280 if (x->use_obsolete_callback_print()) {
281 x->print_args_obsolete_callback(o, this); //BUG//callback//
282 }else{
283 for (int ii = x->param_count() - 1; ii >= 0; --ii) {
284 if (x->param_is_printable(ii)) {
285 std::string arg = " " + x->param_name(ii) + "=" + x->param_value(ii);
286 o << arg;
287 }else{
292 /*--------------------------------------------------------------------------*/
293 static void print_type(OMSTREAM& o, const COMPONENT* x)
295 assert(x);
296 o << ' ' << x->dev_type();
298 /*--------------------------------------------------------------------------*/
299 static void print_label(OMSTREAM& o, const COMPONENT* x)
301 assert(x);
302 o << x->short_label();
304 /*--------------------------------------------------------------------------*/
305 static void print_ports(OMSTREAM& o, const COMPONENT* x)
307 assert(x);
309 o << " (";
310 std::string sep = "";
311 for (int ii = 0; x->port_exists(ii); ++ii) {
312 o << sep << x->port_value(ii);
313 sep = " ";
315 for (int ii = 0; x->current_port_exists(ii); ++ii) {
316 o << sep << x->current_port_value(ii);
317 sep = " ";
319 o << ")";
321 /*--------------------------------------------------------------------------*/
322 /*--------------------------------------------------------------------------*/
323 void LANG_SPECTRE::print_paramset(OMSTREAM& o, const MODEL_CARD* x)
325 assert(x);
326 o << "model " << x->short_label() << ' ' << x->dev_type() << ' ';
327 print_args(o, x);
328 o << "\n\n";
330 /*--------------------------------------------------------------------------*/
331 void LANG_SPECTRE::print_module(OMSTREAM& o, const MODEL_SUBCKT* x)
333 assert(x);
334 assert(x->subckt());
336 o << "subckt " << x->short_label();
337 print_ports(o, x);
338 o << "\n";
340 for (CARD_LIST::const_iterator
341 ci = x->subckt()->begin(); ci != x->subckt()->end(); ++ci) {
342 print_item(o, *ci);
345 o << "ends " << x->short_label() << "\n\n";
347 /*--------------------------------------------------------------------------*/
348 void LANG_SPECTRE::print_instance(OMSTREAM& o, const COMPONENT* x)
350 print_label(o, x);
351 print_ports(o, x);
352 print_type(o, x);
353 print_args(o, x);
354 o << "\n";
356 /*--------------------------------------------------------------------------*/
357 void LANG_SPECTRE::print_comment(OMSTREAM& o, const DEV_COMMENT* x)
359 assert(x);
360 o << x->comment() << '\n';
362 /*--------------------------------------------------------------------------*/
363 void LANG_SPECTRE::print_command(OMSTREAM& o, const DEV_DOT* x)
365 assert(x);
366 o << x->s() << '\n';
368 /*--------------------------------------------------------------------------*/
369 /*--------------------------------------------------------------------------*/
370 class CMD_MODEL : public CMD {
371 void do_it(CS& cmd, CARD_LIST* Scope)
373 // already got "model"
374 std::string my_name, base_name;
375 cmd >> my_name;
376 unsigned here = cmd.cursor();
377 cmd >> base_name;
379 //const MODEL_CARD* p = model_dispatcher[base_name];
380 const CARD* p = lang_spectre.find_proto(base_name, NULL);
381 if (p) {
382 MODEL_CARD* new_card = dynamic_cast<MODEL_CARD*>(p->clone());
383 if (exists(new_card)) {
384 assert(!new_card->owner());
385 lang_spectre.parse_paramset(cmd, new_card);
386 Scope->push_back(new_card);
387 }else{ //BUG// memory leak
388 cmd.warn(bDANGER, here, "model: base has incorrect type");
390 }else{
391 cmd.warn(bDANGER, here, "model: no match");
394 } p1;
395 DISPATCHER<CMD>::INSTALL d1(&command_dispatcher, "model", &p1);
396 /*--------------------------------------------------------------------------*/
397 class CMD_SUBCKT : public CMD {
398 void do_it(CS& cmd, CARD_LIST* Scope)
400 MODEL_SUBCKT* new_module = new MODEL_SUBCKT;
401 assert(new_module);
402 assert(!new_module->owner());
403 assert(new_module->subckt());
404 assert(new_module->subckt()->is_empty());
405 lang_spectre.parse_module(cmd, new_module);
406 Scope->push_back(new_module);
408 } p2;
409 DISPATCHER<CMD>::INSTALL d2(&command_dispatcher, "subckt", &p2);
410 /*--------------------------------------------------------------------------*/
411 class CMD_SIMULATOR : public CMD {
412 void do_it(CS& cmd, CARD_LIST* Scope)
414 command("options " + cmd.tail(), Scope);
416 } p3;
417 DISPATCHER<CMD>::INSTALL d3(&command_dispatcher, "simulator", &p3);
418 /*--------------------------------------------------------------------------*/
419 class CMD_SPECTRE : public CMD {
420 public:
421 void do_it(CS&, CARD_LIST* Scope)
423 command("options lang=spectre", Scope);
425 } p8;
426 DISPATCHER<CMD>::INSTALL d8(&command_dispatcher, "spectre", &p8);
427 /*--------------------------------------------------------------------------*/
429 /*--------------------------------------------------------------------------*/
430 /*--------------------------------------------------------------------------*/
431 // vim:ts=8:sw=2:noet: