1 /*$Id: lang_spectre.cc 2015/01/27 al $ -*- 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
22 //testing=script 2015.01.27
30 /*--------------------------------------------------------------------------*/
32 /*--------------------------------------------------------------------------*/
33 class LANG_SPECTRE
: public LANGUAGE
{
37 std::string
name()const {return "spectre";}
38 bool case_insensitive()const {return false;}
39 UNITS
units()const {return uSI
;}
41 public: // override virtual, used by callback
42 std::string
arg_front()const {unreachable();return " ";}
43 std::string
arg_mid()const {unreachable();return "=";}
44 std::string
arg_back()const {unreachable();return "";}
46 public: // override virtual, called by commands
47 void parse_top_item(CS
&, CARD_LIST
*);
48 DEV_COMMENT
* parse_comment(CS
&, DEV_COMMENT
*);
49 DEV_DOT
* parse_command(CS
&, DEV_DOT
*);
50 MODEL_CARD
* parse_paramset(CS
&, MODEL_CARD
*);
51 BASE_SUBCKT
* parse_module(CS
&, BASE_SUBCKT
*);
52 COMPONENT
* parse_instance(CS
&, COMPONENT
*);
53 std::string
find_type_in_string(CS
&) const;
55 private: // override virtual, called by print_item
56 void print_paramset(OMSTREAM
&, const MODEL_CARD
*);
57 void print_module(OMSTREAM
&, const BASE_SUBCKT
*);
58 void print_instance(OMSTREAM
&, const COMPONENT
*);
59 void print_comment(OMSTREAM
&, const DEV_COMMENT
*);
60 void print_command(OMSTREAM
& o
, const DEV_DOT
* c
);
61 string
getlines(FILE *fileptr
) const;
63 void print_args(OMSTREAM
&, const CARD
*);
64 static void parse_args(CS
& cmd
, CARD
* x
);
65 void parse_ports(CS
& cmd
, COMPONENT
* x
) const;
68 DISPATCHER
<LANGUAGE
>::INSTALL
69 d(&language_dispatcher
, lang_spectre
.name(), &lang_spectre
);
70 /*--------------------------------------------------------------------------*/
71 /*--------------------------------------------------------------------------*/
72 static void parse_type(CS
& cmd
, CARD
* x
)
77 x
->set_dev_type(new_type
);
79 /*--------------------------------------------------------------------------*/
80 void LANG_SPECTRE::parse_args(CS
& cmd
, CARD
* x
)
85 while (cmd
.more() && !cmd
.stuck(&here
)) {
86 std::string name
= cmd
.ctos("=", "", "");
88 std::string value
= cmd
.ctos("", "(", ")");
90 trace2("parse_args", name
, value
);
91 x
->set_param_by_name(name
, value
);
92 }catch (Exception_No_Match
&) {
93 cmd
.warn(bDANGER
, here
, x
->long_label() + ": bad parameter " + name
+ " ignored");
97 /*--------------------------------------------------------------------------*/
98 static void parse_label(CS
& cmd
, CARD
* x
)
103 x
->set_label(my_name
);
105 /*--------------------------------------------------------------------------*/
106 void LANG_SPECTRE::parse_ports(CS
& cmd
, COMPONENT
* x
) const
112 while (cmd
.is_alnum()) {
113 unsigned here
= cmd
.cursor();
117 x
->set_port_by_index(index
++, value
);
118 }catch (Exception_Too_Many
& e
) {
119 cmd
.warn(bDANGER
, here
, e
.message());
124 unsigned here
= cmd
.cursor();
125 string s
= find_type_in_string(cmd
);
126 bool sub
= (s
=="subckt");
127 unsigned stop
= cmd
.cursor();
128 trace4("LANG_SPECTRE::parse_ports no paren", x
->long_label(), s
, cmd
.tail(), stop
);
130 trace1("LANG_SPECTRE::parse_ports here", cmd
.tail());
132 while (cmd
.cursor() < stop
|| ( sub
&& cmd
.is_alnum())) {
137 x
->set_port_by_index(index
++, value
);
138 }catch (Exception_Too_Many
& e
) {
139 cmd
.warn(bDANGER
, here
, e
.message());
143 if (index
< x
->min_nodes()) {
144 cmd
.warn(bDANGER
, "need " + to_string(x
->min_nodes()-index
) +" more nodes, grounding");
145 for (uint_t iii
= index
; iii
< x
->min_nodes(); ++iii
) {
146 x
->set_port_to_ground(iii
);
151 /*--------------------------------------------------------------------------*/
152 /*--------------------------------------------------------------------------*/
153 DEV_COMMENT
* LANG_SPECTRE::parse_comment(CS
& cmd
, DEV_COMMENT
* x
)
156 x
->set(cmd
.fullstring());
159 /*--------------------------------------------------------------------------*/
160 DEV_DOT
* LANG_SPECTRE::parse_command(CS
& cmd
, DEV_DOT
* x
)
163 x
->set(cmd
.fullstring());
164 CARD_LIST
* scope
= (x
->owner()) ? x
->owner()->subckt() : &CARD_LIST::card_list
;
166 cmd
.reset().skipbl();
167 if ((cmd
>> "model |simulator |parameters |subckt |list |eval |include ")) {
169 CMD::cmdproc(cmd
, scope
);
175 unsigned here
= cmd
.cursor();
179 std::string file_name
= label
+ '.' + command
;
180 std::string s
= cmd
.tail() + " > " + file_name
;
181 CS
augmented_cmd(CS::_STRING
, s
);
182 CMD::cmdproc(augmented_cmd
, scope
);
184 CMD::cmdproc(cmd
, scope
);
190 /*--------------------------------------------------------------------------*/
191 MODEL_CARD
* LANG_SPECTRE::parse_paramset(CS
& cmd
, MODEL_CARD
* x
)
194 cmd
.reset().skipbl();
199 cmd
.check(bWARNING
, "what's this?");
202 /*--------------------------------------------------------------------------*/
203 BASE_SUBCKT
* LANG_SPECTRE::parse_module(CS
& cmd
, BASE_SUBCKT
* x
)
208 cmd
.reset().skipbl();
215 cmd
.get_line("spectre-subckt>");
217 if (cmd
>> "ends ") {
220 new__instance(cmd
, x
, x
->subckt());
225 /*--------------------------------------------------------------------------*/
226 COMPONENT
* LANG_SPECTRE::parse_instance(CS
& cmd
, COMPONENT
* x
)
234 cmd
.check(bWARNING
, "what's this?");
237 /*--------------------------------------------------------------------------*/
238 std::string
LANG_SPECTRE::find_type_in_string(CS
& cmd
) const
240 // known to be not always correct
242 cmd
.reset().skipbl();
245 if ((cmd
>> "*|//")) {
247 type
= "dev_comment";
248 }else if ((cmd
>> "model |simulator |parameters |subckt |list |include |eval ")) {
249 // type is first, it's a control statement
250 type
= cmd
.trimmed_last_match();
251 }else if (cmd
.reset().skiparg().match1("(") && cmd
.scan(")")) {
252 // node list surrounded by parens
257 }else if (cmd
.reset().scan("=")) {
258 // back up two, by starting over
259 cmd
.reset().skiparg();
260 unsigned here1
= cmd
.cursor();
262 unsigned here2
= cmd
.cursor();
264 unsigned here3
= cmd
.cursor();
265 while (here2
!= here3
&& !cmd
.match1('=')) {
269 here3
= cmd
.cursor();
276 cmd
.reset().skiparg();
284 /*--------------------------------------------------------------------------*/
285 void LANG_SPECTRE::parse_top_item(CS
& cmd
, CARD_LIST
* Scope
)
287 cmd
.get_line("gnucap-spectre>");
288 new__instance(cmd
, NULL
, Scope
);
290 /*--------------------------------------------------------------------------*/
291 /*--------------------------------------------------------------------------*/
292 void LANG_SPECTRE::print_args(OMSTREAM
& o
, const CARD
* x
)
296 if (x
->use_obsolete_callback_print()) {
297 x
->print_args_obsolete_callback(o
, this); //BUG//callback//
299 for (int ii
= x
->param_count() - 1; ii
>= 0; --ii
) {
300 if (x
->param_is_printable(ii
)) {
301 std::string arg
= " " + x
->param_name(ii
) + "=" + x
->param_value(ii
);
308 /*--------------------------------------------------------------------------*/
309 static void print_type(OMSTREAM
& o
, const COMPONENT
* x
)
312 o
<< ' ' << x
->dev_type();
314 /*--------------------------------------------------------------------------*/
315 static void print_label(OMSTREAM
& o
, const COMPONENT
* x
)
318 o
<< x
->short_label();
320 /*--------------------------------------------------------------------------*/
321 static void print_ports(OMSTREAM
& o
, const COMPONENT
* x
)
326 std::string sep
= "";
327 for (uint_t ii
= 0; x
->port_exists(ii
); ++ii
) {
328 o
<< sep
<< x
->port_value(ii
);
331 for (uint_t ii
= 0; x
->current_port_exists(ii
); ++ii
) {untested();
332 o
<< sep
<< x
->current_port_value(ii
);
337 /*--------------------------------------------------------------------------*/
338 /*--------------------------------------------------------------------------*/
339 void LANG_SPECTRE::print_paramset(OMSTREAM
& o
, const MODEL_CARD
* x
)
342 o
<< "model " << x
->short_label() << ' ' << x
->dev_type() << ' ';
346 /*--------------------------------------------------------------------------*/
347 void LANG_SPECTRE::print_module(OMSTREAM
& o
, const BASE_SUBCKT
* x
)
352 o
<< "subckt " << x
->short_label();
356 for (CARD_LIST::const_iterator
357 ci
= x
->subckt()->begin(); ci
!= x
->subckt()->end(); ++ci
) {
361 o
<< "ends " << x
->short_label() << "\n\n";
363 /*--------------------------------------------------------------------------*/
364 void LANG_SPECTRE::print_instance(OMSTREAM
& o
, const COMPONENT
* x
)
372 /*--------------------------------------------------------------------------*/
373 void LANG_SPECTRE::print_comment(OMSTREAM
& o
, const DEV_COMMENT
* x
)
376 if (x
->comment()[0] != '*') {
380 o
<< x
->comment() << '\n';
382 /*--------------------------------------------------------------------------*/
383 void LANG_SPECTRE::print_command(OMSTREAM
& o
, const DEV_DOT
* x
)
388 /*--------------------------------------------------------------------------*/
389 std::string
LANG_SPECTRE::getlines(FILE *fileptr
) const
392 const int buffer_size
= BIGBUFLEN
;
395 bool need_to_get_more
= true; // get another line (extend)
396 while (need_to_get_more
) {
397 char buffer
[buffer_size
+1];
398 char* got_something
= fgets(buffer
, buffer_size
, fileptr
);
399 if (!got_something
) { // probably end of file
400 need_to_get_more
= false;
402 throw Exception_End_Of_Input("");
407 size_t count
= strlen(buffer
);
409 }else if (buffer
[count
-1] == '\\') {itested();
410 buffer
[count
-1] = '\0';
412 // look ahead at next line
413 //int c = fgetc(fileptr);
416 while (isspace(c
= fgetc(fileptr
)));
419 need_to_get_more
= true;
421 need_to_get_more
= false;
431 /*--------------------------------------------------------------------------*/
432 /*--------------------------------------------------------------------------*/
433 class CMD_MODEL
: public CMD
{
434 void do_it(CS
& cmd
, CARD_LIST
* Scope
)
436 // already got "model"
437 std::string my_name
, base_name
;
439 unsigned here
= cmd
.cursor();
442 //const MODEL_CARD* p = model_dispatcher[base_name];
443 const CARD
* p
= lang_spectre
.find_proto(base_name
, NULL
);
445 MODEL_CARD
* new_card
= dynamic_cast<MODEL_CARD
*>(p
->clone());
447 assert(!new_card
->owner());
448 lang_spectre
.parse_paramset(cmd
, new_card
);
449 Scope
->push_back(new_card
);
451 cmd
.warn(bDANGER
, here
, "model: base has incorrect type");
454 cmd
.warn(bDANGER
, here
, "model: no match");
458 DISPATCHER
<CMD
>::INSTALL
d1(&command_dispatcher
, "model", &p1
);
459 /*--------------------------------------------------------------------------*/
460 class CMD_SUBCKT
: public CMD
{
461 void do_it(CS
& cmd
, CARD_LIST
* Scope
)
463 const CARD
* s
= device_dispatcher
["subckt"];
464 assert(s
); // for now
465 BASE_SUBCKT
* new_module
= dynamic_cast<BASE_SUBCKT
*>(s
->clone());
467 assert(!new_module
->owner());
468 assert(new_module
->subckt());
469 assert(new_module
->subckt()->is_empty());
470 lang_spectre
.parse_module(cmd
, new_module
);
471 Scope
->push_back(new_module
);
474 DISPATCHER
<CMD
>::INSTALL
d2(&command_dispatcher
, "subckt", &p2
);
475 /*--------------------------------------------------------------------------*/
476 class CMD_SIMULATOR
: public CMD
{
477 void do_it(CS
& cmd
, CARD_LIST
* Scope
)
479 command("options " + cmd
.tail(), Scope
);
482 DISPATCHER
<CMD
>::INSTALL
d3(&command_dispatcher
, "simulator", &p3
);
483 /*--------------------------------------------------------------------------*/
484 class CMD_SPECTRE
: public CMD
{
486 void do_it(CS
&, CARD_LIST
* Scope
)
488 command("options lang=spectre", Scope
);
491 DISPATCHER
<CMD
>::INSTALL
d8(&command_dispatcher
, "spectre", &p8
);
492 /*--------------------------------------------------------------------------*/
494 /*--------------------------------------------------------------------------*/
495 /*--------------------------------------------------------------------------*/
496 // vim:ts=8:sw=2:noet: