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)
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
29 /*--------------------------------------------------------------------------*/
31 /*--------------------------------------------------------------------------*/
32 class LANG_SPECTRE
: public LANGUAGE
{
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
);
60 void print_args(OMSTREAM
&, const CARD
*);
63 DISPATCHER
<LANGUAGE
>::INSTALL
64 d(&language_dispatcher
, lang_spectre
.name(), &lang_spectre
);
65 /*--------------------------------------------------------------------------*/
66 /*--------------------------------------------------------------------------*/
67 static void parse_type(CS
& cmd
, CARD
* x
)
72 x
->set_dev_type(new_type
);
74 /*--------------------------------------------------------------------------*/
75 static void parse_args(CS
& cmd
, CARD
* x
)
80 while (cmd
.more() && !cmd
.stuck(&here
)) {
81 std::string name
= cmd
.ctos("=", "", "");
83 std::string value
= cmd
.ctos("", "(", ")");
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
)
97 x
->set_label(my_name
);
99 /*--------------------------------------------------------------------------*/
100 static void parse_ports(CS
& cmd
, COMPONENT
* x
)
106 while (cmd
.is_alnum()) {
107 unsigned here
= cmd
.cursor();
111 x
->set_port_by_index(index
++, value
);
112 }catch (Exception_Too_Many
& e
) {untested();
113 cmd
.warn(bDANGER
, here
, e
.message());
118 unsigned here
= cmd
.cursor();
119 OPT::language
->find_type_in_string(cmd
);
120 unsigned stop
= cmd
.cursor();
124 while (cmd
.cursor() < stop
) {
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
)
141 x
->set(cmd
.fullstring());
144 /*--------------------------------------------------------------------------*/
145 DEV_DOT
* LANG_SPECTRE::parse_command(CS
& cmd
, DEV_DOT
* 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 ")) {
154 CMD::cmdproc(cmd
, scope
);
160 unsigned here
= cmd
.cursor();
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
);
169 CMD::cmdproc(cmd
, scope
);
175 /*--------------------------------------------------------------------------*/
176 MODEL_CARD
* LANG_SPECTRE::parse_paramset(CS
& cmd
, MODEL_CARD
* x
)
179 cmd
.reset().skipbl();
184 cmd
.check(bWARNING
, "what's this?");
187 /*--------------------------------------------------------------------------*/
188 MODEL_SUBCKT
* LANG_SPECTRE::parse_module(CS
& cmd
, MODEL_SUBCKT
* x
)
193 cmd
.reset().skipbl();
200 cmd
.get_line("spectre-subckt>");
202 if (cmd
>> "ends ") {
205 new__instance(cmd
, x
, x
->subckt());
210 /*--------------------------------------------------------------------------*/
211 COMPONENT
* LANG_SPECTRE::parse_instance(CS
& cmd
, COMPONENT
* x
)
218 cmd
.check(bWARNING
, "what's this?");
221 /*--------------------------------------------------------------------------*/
222 std::string
LANG_SPECTRE::find_type_in_string(CS
& cmd
)
224 // known to be not always correct
226 cmd
.reset().skipbl();
229 if ((cmd
>> "*|//")) {itested();
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
241 }else if (cmd
.reset().scan("=")) {itested();
242 // back up two, by starting over
243 cmd
.reset().skiparg();
244 unsigned here1
= cmd
.cursor();
246 unsigned here2
= cmd
.cursor();
248 unsigned here3
= cmd
.cursor();
249 while (here2
!= here3
&& !cmd
.match1('=')) {
253 here3
= cmd
.cursor();
260 cmd
.reset().skiparg();
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
)
280 if (x
->use_obsolete_callback_print()) {
281 x
->print_args_obsolete_callback(o
, this); //BUG//callback//
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
);
292 /*--------------------------------------------------------------------------*/
293 static void print_type(OMSTREAM
& o
, const COMPONENT
* x
)
296 o
<< ' ' << x
->dev_type();
298 /*--------------------------------------------------------------------------*/
299 static void print_label(OMSTREAM
& o
, const COMPONENT
* x
)
302 o
<< x
->short_label();
304 /*--------------------------------------------------------------------------*/
305 static void print_ports(OMSTREAM
& o
, const COMPONENT
* x
)
310 std::string sep
= "";
311 for (int ii
= 0; x
->port_exists(ii
); ++ii
) {
312 o
<< sep
<< x
->port_value(ii
);
315 for (int ii
= 0; x
->current_port_exists(ii
); ++ii
) {
316 o
<< sep
<< x
->current_port_value(ii
);
321 /*--------------------------------------------------------------------------*/
322 /*--------------------------------------------------------------------------*/
323 void LANG_SPECTRE::print_paramset(OMSTREAM
& o
, const MODEL_CARD
* x
)
326 o
<< "model " << x
->short_label() << ' ' << x
->dev_type() << ' ';
330 /*--------------------------------------------------------------------------*/
331 void LANG_SPECTRE::print_module(OMSTREAM
& o
, const MODEL_SUBCKT
* x
)
336 o
<< "subckt " << x
->short_label();
340 for (CARD_LIST::const_iterator
341 ci
= x
->subckt()->begin(); ci
!= x
->subckt()->end(); ++ci
) {
345 o
<< "ends " << x
->short_label() << "\n\n";
347 /*--------------------------------------------------------------------------*/
348 void LANG_SPECTRE::print_instance(OMSTREAM
& o
, const COMPONENT
* x
)
356 /*--------------------------------------------------------------------------*/
357 void LANG_SPECTRE::print_comment(OMSTREAM
& o
, const DEV_COMMENT
* x
)
360 o
<< x
->comment() << '\n';
362 /*--------------------------------------------------------------------------*/
363 void LANG_SPECTRE::print_command(OMSTREAM
& o
, const DEV_DOT
* x
)
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
;
376 unsigned here
= cmd
.cursor();
379 //const MODEL_CARD* p = model_dispatcher[base_name];
380 const CARD
* p
= lang_spectre
.find_proto(base_name
, NULL
);
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");
391 cmd
.warn(bDANGER
, here
, "model: no match");
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
;
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
);
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
);
417 DISPATCHER
<CMD
>::INSTALL
d3(&command_dispatcher
, "simulator", &p3
);
418 /*--------------------------------------------------------------------------*/
419 class CMD_SPECTRE
: public CMD
{
421 void do_it(CS
&, CARD_LIST
* Scope
)
423 command("options lang=spectre", Scope
);
426 DISPATCHER
<CMD
>::INSTALL
d8(&command_dispatcher
, "spectre", &p8
);
427 /*--------------------------------------------------------------------------*/
429 /*--------------------------------------------------------------------------*/
430 /*--------------------------------------------------------------------------*/
431 // vim:ts=8:sw=2:noet: