ngspice compatibility mode
This commit is contained in:
parent
49aadcca58
commit
e66ef33c57
|
|
@ -1,3 +1,8 @@
|
|||
2010-04-23 Holger Vogt
|
||||
* xpressn.c: agauss is no. 20
|
||||
main.c, inp.c, inpcom.c, compatmode.h, inpptree.h, ifeval.c, inpptree.c, ptfuncs.c:
|
||||
ngspice compatibility mode with various functions
|
||||
|
||||
2010-04-11 Dietmar Warning
|
||||
* Robert Larice patch to allow new operations in control blocks:
|
||||
* examples/new-check-3.sp, new-check-4.sp
|
||||
|
|
|
|||
|
|
@ -536,6 +536,18 @@ inp_spsource(FILE *fp, bool comfile, char *filename)
|
|||
line_free(deck->li_actual,FALSE);
|
||||
deck->li_actual = realdeck;
|
||||
|
||||
/* print out the expanded deck into debug-out2.txt */
|
||||
if (ft_ngdebug) {
|
||||
FILE *fdo;
|
||||
struct line *tmp_ptr1 = NULL;
|
||||
/*debug: print into file*/
|
||||
fdo = fopen("debug-out2.txt", "w");
|
||||
for(tmp_ptr1 = deck; tmp_ptr1 != NULL; tmp_ptr1 = tmp_ptr1->li_next)
|
||||
fprintf(fdo, "%s\n", tmp_ptr1->li_line);
|
||||
;
|
||||
(void) fclose(fdo);
|
||||
}
|
||||
|
||||
/* now load deck into ft_curckt -- the current circuit. */
|
||||
inp_dodeck(deck, tt, wl_first, FALSE, options, filename);
|
||||
|
||||
|
|
@ -595,12 +607,12 @@ inp_spsource(FILE *fp, bool comfile, char *filename)
|
|||
printf("In inp_spsource, done with dodeck.\n");
|
||||
#endif
|
||||
|
||||
/* print out the expanded deck into debug-out2.txt */
|
||||
/* print out the expanded deck into debug-out3.txt */
|
||||
if (ft_ngdebug) {
|
||||
FILE *fdo;
|
||||
struct line *tmp_ptr1 = NULL;
|
||||
/*debug: print into file*/
|
||||
fdo = fopen("debug-out2.txt", "w");
|
||||
fdo = fopen("debug-out3.txt", "w");
|
||||
for(tmp_ptr1 = deck; tmp_ptr1 != NULL; tmp_ptr1 = tmp_ptr1->li_next)
|
||||
fprintf(fdo, "%s\n", tmp_ptr1->li_line);
|
||||
;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ Author: 1985 Wayne A. Christopher
|
|||
#include "fteext.h"
|
||||
#include "dvec.h"
|
||||
#include "fteinp.h"
|
||||
#include "compatmode.h"
|
||||
|
||||
#include "inpcom.h"
|
||||
#include "variable.h"
|
||||
|
|
@ -81,6 +82,7 @@ static char *func_params[1000][1000];
|
|||
static char *func_macro[5000];
|
||||
static int num_functions;
|
||||
static int num_parameters[1000];
|
||||
static COMPATMODE_T inp_compat_mode;
|
||||
|
||||
/* Collect information for dynamic allocation of numparam arrays */
|
||||
/* number of lines in input deck */
|
||||
|
|
@ -92,6 +94,8 @@ int dynMaxckt = 0; /* subckt.c 307 */
|
|||
/* number of parameter substitutions */
|
||||
long dynsubst; /* spicenum.c 221 */
|
||||
|
||||
extern COMPATMODE_T ngspice_compat_mode(void) ;
|
||||
|
||||
/* static declarations */
|
||||
static char * readline(FILE *fd);
|
||||
static int get_number_terminals( char *c );
|
||||
|
|
@ -110,6 +114,8 @@ static void inp_reorder_params( struct line *deck, struct line *list_head, struc
|
|||
static int inp_split_multi_param_lines( struct line *deck, int line_number );
|
||||
static void inp_sort_params( struct line *start_card, struct line *end_card, struct line *card_bf_start, struct line *s_c, struct line *e_c );
|
||||
static char* inp_remove_ws( char *s );
|
||||
static void inp_compat(struct line *deck);
|
||||
static void inp_bsource_compat(struct line *deck);
|
||||
|
||||
/*-------------------------------------------------------------------------*
|
||||
* This routine reads a line (of arbitrary length), up to a '\n' or 'EOF' *
|
||||
|
|
@ -465,29 +471,29 @@ inp_fix_macro_param_func_paren_io( struct line *begin_card ) {
|
|||
for ( card = begin_card; card != NULL; card = card->li_next ) {
|
||||
|
||||
if ( *card->li_line == '*' ) continue;
|
||||
|
||||
/*
|
||||
// zero out any voltage node references on .param lines
|
||||
if ( ciprefix( ".param", card->li_line ) ) {
|
||||
search_ptr = card->li_line;
|
||||
while( ( open_paren_ptr = strstr( search_ptr, "(" ) ) ) {
|
||||
fcn_name = open_paren_ptr - 1;
|
||||
while ( *fcn_name != '\0' && fcn_name != search_ptr && (isalnum(*fcn_name) || *fcn_name == '_' ) ) fcn_name--;
|
||||
if ( fcn_name != search_ptr ) fcn_name++;
|
||||
*open_paren_ptr = '\0';
|
||||
if ( strcmp( fcn_name, "v" ) == 0 ) {
|
||||
*open_paren_ptr = ' ';
|
||||
*fcn_name = '0';
|
||||
fcn_name++;
|
||||
while ( *fcn_name != ')' ) { *fcn_name = ' '; fcn_name++; }
|
||||
*fcn_name = ' ';
|
||||
}
|
||||
else {
|
||||
*open_paren_ptr = '(';
|
||||
}
|
||||
search_ptr = open_paren_ptr + 1;
|
||||
fcn_name = open_paren_ptr - 1;
|
||||
while ( *fcn_name != '\0' && fcn_name != search_ptr && (isalnum(*fcn_name) || *fcn_name == '_' ) ) fcn_name--;
|
||||
if ( fcn_name != search_ptr ) fcn_name++;
|
||||
*open_paren_ptr = '\0';
|
||||
if ( strcmp( fcn_name, "v" ) == 0 ) {
|
||||
*open_paren_ptr = ' ';
|
||||
*fcn_name = '0';
|
||||
fcn_name++;
|
||||
while ( *fcn_name != ')' ) { *fcn_name = ' '; fcn_name++; }
|
||||
*fcn_name = ' ';
|
||||
}
|
||||
else {
|
||||
*open_paren_ptr = '(';
|
||||
}
|
||||
search_ptr = open_paren_ptr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
if ( ciprefix( ".macro", card->li_line ) || ciprefix( ".eom", card->li_line ) ) {
|
||||
str_ptr = card->li_line;
|
||||
while( !isspace(*str_ptr) ) str_ptr++;
|
||||
|
|
@ -897,6 +903,7 @@ inp_fix_ternary_operator_str( char *line )
|
|||
*str_ptr = keep;
|
||||
}
|
||||
}
|
||||
else return line; // hvogt
|
||||
|
||||
// get conditional
|
||||
str_ptr2 = question = strstr( str_ptr, "?" );
|
||||
|
|
@ -1592,7 +1599,19 @@ inp_readall(FILE *fp, struct line **data, int call_depth, char *dir_name)
|
|||
|
||||
if (cp_getvar("addcontrol", VT_BOOL, (char *) &v))
|
||||
inp_add_control_section(working, &line_number);
|
||||
inp_compat_mode = ngspice_compat_mode() ;
|
||||
if (inp_compat_mode == COMPATMODE_ALL) {
|
||||
/* Do all the compatibility stuff here */
|
||||
working = cc->li_next;
|
||||
/* E, G, L, R, C compatibility transformations */
|
||||
inp_compat(working);
|
||||
working = cc->li_next;
|
||||
/* B source numparam compatibility transformation */
|
||||
inp_bsource_compat(working);
|
||||
}
|
||||
}
|
||||
|
||||
/* save the return value (via **data) */
|
||||
*data = cc;
|
||||
|
||||
/* get max. line length and number of lines in input deck,
|
||||
|
|
@ -2200,6 +2219,9 @@ inp_fix_subckt_multiplier( struct line *subckt_card,
|
|||
for ( card = subckt_card->li_next;
|
||||
card != NULL && !ciprefix( ".ends", card->li_line );
|
||||
card = card->li_next ) {
|
||||
/* no 'm' for B line or comment line */
|
||||
if ((*(card->li_line) == '*') || (*(card->li_line) == 'b'))
|
||||
continue;
|
||||
new_str = tmalloc( strlen( card->li_line ) + 7 );
|
||||
sprintf( new_str, "%s m={m}", card->li_line );
|
||||
|
||||
|
|
@ -2558,13 +2580,13 @@ inp_expand_macro_in_str( char *str )
|
|||
curr_ptr = open_paren_ptr+1;
|
||||
while ( isspace(*curr_ptr) ) curr_ptr++;
|
||||
num_params = 0;
|
||||
if ( ciprefix( "v(", curr_ptr ) ) {
|
||||
/* if ( ciprefix( "v(", curr_ptr ) ) {
|
||||
// look for any commas and change to ' '
|
||||
char *str_ptr = curr_ptr;
|
||||
while ( *str_ptr != '\0' && *str_ptr != ')' ) {
|
||||
if ( *str_ptr == ',' || *str_ptr == '(' ) *str_ptr = ' '; str_ptr++; }
|
||||
if ( *str_ptr == ')' ) *str_ptr = ' ';
|
||||
}
|
||||
}*/
|
||||
num_parens = 0;
|
||||
for (comma_ptr = curr_ptr; *comma_ptr && *comma_ptr != '\0'; comma_ptr++) {
|
||||
if (*comma_ptr == ',' && num_parens == 0) {
|
||||
|
|
@ -3459,3 +3481,453 @@ inp_split_multi_param_lines( struct line *deck, int line_num )
|
|||
}
|
||||
return line_num;
|
||||
}
|
||||
|
||||
|
||||
/* compatibility:
|
||||
Exxx n1 n2 VCVS n3 n4 gain --> Exxx n1 n2 n3 n4 gain
|
||||
Gxxx n1 n2 VCCS n3 n4 tr --> Exxx n1 n2 n3 n4 tr
|
||||
Exxx n1 n2 VOL = {equation} --> BExxx n1 n2 V = {equation}
|
||||
Gxxx n1 n2 CUR = {equation} --> BGxxx n1 n2 I = {equation}
|
||||
|
||||
Do the following transformations only if {equation} contains
|
||||
simulation output like v(node), v(node1, node2), i(branch).
|
||||
Otherwise let do numparam the substitutions (R=const is handled
|
||||
in inp2r.c).
|
||||
|
||||
Rxxx n1 n2 R = {equation} or Rxxx n1 n2 {equation}
|
||||
-->
|
||||
BRxxx n1 n2 I = V(n1,n2)/{equation}
|
||||
|
||||
Unfortunately the capability for ac noise calculation of
|
||||
resistance may be lost.
|
||||
|
||||
Cxxx n1 n2 C = {equation} or Cxxx n1 n2 {equation}
|
||||
-->
|
||||
Cxxx n1 n2-aux 1
|
||||
Vxxx n2-aux n2 DC=0
|
||||
Bxxx n1 n2 I = ((equation) - 1) * Vxxx#branch
|
||||
|
||||
Lxxx n1 n2 L = {equation} or Lxxx n1 n2 {equation}
|
||||
-->
|
||||
Lxxx n1 int 1
|
||||
Bxxx int n2 V = ((equation) - 1) * V(n1, int)
|
||||
*/
|
||||
static void inp_compat(struct line *deck)
|
||||
{
|
||||
char *curr_line, *str_ptr, *cut_line, *title_tok, *node1, *node2;
|
||||
char *xline, *linline, *amline, *fline, *eqline;
|
||||
size_t xlen, i;
|
||||
char *ckt_array[4];
|
||||
struct line *new_line, *tmp_ptr;
|
||||
|
||||
struct line *param_end = NULL, *param_beg = NULL;
|
||||
struct line *card = deck;
|
||||
|
||||
while ( card != NULL )
|
||||
{
|
||||
curr_line = card->li_line;
|
||||
if ( *curr_line == '*' ) { card = card->li_next; continue; }
|
||||
if ( *curr_line == 'e' ) {
|
||||
/* Exxx n1 n2 VCVS n3 n4 gain --> Exxx n1 n2 n3 n4 gain
|
||||
remove vcvs */
|
||||
if (str_ptr = strstr( curr_line, "vcvs" ) ) {
|
||||
*str_ptr = ' '; *(str_ptr + 1) = ' ';
|
||||
*(str_ptr + 2) = ' '; *(str_ptr + 3) = ' ';
|
||||
}
|
||||
/* Exxx n1 n2 VOL = {equation} --> BExxx n1 n2 V = {equation} */
|
||||
if (str_ptr = strstr( curr_line, "vol" ) ) {
|
||||
*(str_ptr + 2) = ' ';
|
||||
while (str_ptr > curr_line) {
|
||||
*(str_ptr + 1) = *str_ptr;
|
||||
str_ptr--;
|
||||
}
|
||||
*(str_ptr + 1) = *str_ptr;
|
||||
*str_ptr = 'b';
|
||||
}
|
||||
}
|
||||
else if ( *curr_line == 'g' ) {
|
||||
/* Gxxx n1 n2 VCCS n3 n4 tr --> Exxx n1 n2 n3 n4 tr
|
||||
remove vccs */
|
||||
if (str_ptr = strstr( curr_line, "vccs" ) ) {
|
||||
*str_ptr = ' '; *(str_ptr + 1) = ' ';
|
||||
*(str_ptr + 2) = ' '; *(str_ptr + 3) = ' ';
|
||||
}
|
||||
/* Gxxx n1 n2 CUR = {equation} --> BGxxx n1 n2 I = {equation} */
|
||||
if (str_ptr = strstr( curr_line, "cur" ) ) {
|
||||
*(str_ptr + 2) = ' '; *str_ptr = 'i';
|
||||
while (str_ptr > curr_line) {
|
||||
*(str_ptr + 1) = *str_ptr;
|
||||
str_ptr--;
|
||||
}
|
||||
*(str_ptr + 1) = *str_ptr;
|
||||
*str_ptr = 'b';
|
||||
}
|
||||
}
|
||||
/* Rxxx n1 n2 R = {equation} or Rxxx n1 n2 {equation}
|
||||
-->
|
||||
BRxxx pos neg I = V(pos, neg)/{equation}
|
||||
*/
|
||||
else if ( *curr_line == 'r' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
{ card = card->li_next; continue; }
|
||||
cut_line = curr_line;
|
||||
/* make BRxxx pos neg I = V(pos, neg)/{equation}*/
|
||||
title_tok = gettok(&cut_line);
|
||||
node1 = gettok(&cut_line);
|
||||
node2 = gettok(&cut_line);
|
||||
/* Find equation, starts with '{', till end of line */
|
||||
str_ptr = strstr(cut_line, "{");
|
||||
xlen = strlen(title_tok) + strlen(node1) + strlen(node2) +
|
||||
strlen(node1) + strlen(node2) + strlen(str_ptr) + 15;
|
||||
xline = (char*)tmalloc(xlen);
|
||||
sprintf(xline, "b%s %s %s I = v(%s, %s)/%s", title_tok, node1, node2,
|
||||
node1, node2, str_ptr);
|
||||
new_line = alloc(struct line);
|
||||
new_line->li_next = NULL;
|
||||
new_line->li_error = NULL;
|
||||
new_line->li_actual = NULL;
|
||||
new_line->li_line = xline;
|
||||
new_line->li_linenum = 0;
|
||||
// comment out current old R line
|
||||
*(card->li_line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
card->li_next = new_line;
|
||||
new_line->li_next = tmp_ptr;
|
||||
// point 'card' pointer to the new line
|
||||
card = new_line;
|
||||
}
|
||||
/* Cxxx n1 n2 C = {equation} or Cxxx n1 n2 {equation}
|
||||
-->
|
||||
Cxxx n1 n2-aux 1
|
||||
Vxxx n2-aux n2 DC=0
|
||||
Bxxx n1 n2 I = ((equation) - 1) * Vxxx#branch
|
||||
*/
|
||||
else if ( *curr_line == 'c' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
{ card = card->li_next; continue; }
|
||||
cut_line = curr_line;
|
||||
/* title and nodes */
|
||||
title_tok = gettok(&cut_line);
|
||||
node1 = gettok(&cut_line);
|
||||
node2 = gettok(&cut_line);
|
||||
/* Find equation, starts with '{', till end of line */
|
||||
str_ptr = strstr(cut_line, "{");
|
||||
|
||||
// Bxxx n1 n2 I = ((equation) - 1) * i(Vxxx)
|
||||
xlen = 2*strlen(title_tok) + strlen(str_ptr) + strlen(node1)
|
||||
+ strlen(node2) + 25;
|
||||
eqline = (char*)tmalloc(xlen);
|
||||
sprintf(eqline, "b%s %s %s i = ((%s) - 1) * i(Vx%s)",
|
||||
title_tok, node1, node2, str_ptr, title_tok);
|
||||
// CCxxx node1 Cxxx2 1
|
||||
xlen = 2*strlen(title_tok) + strlen(node1) + 11;
|
||||
linline = (char*)tmalloc(xlen);
|
||||
sprintf(linline, "c%s %s %s_int2 1", title_tok, node1, title_tok);
|
||||
// VCxxx Cxxx2 node2 DC 0
|
||||
xlen = 2*strlen(title_tok) + strlen(node2) + 16;
|
||||
amline = (char*)tmalloc(xlen);
|
||||
sprintf(amline, "vx%s %s_int2 %s dc 0", title_tok, title_tok, node2);
|
||||
|
||||
ckt_array[0] = eqline;
|
||||
ckt_array[1] = linline;
|
||||
ckt_array[2] = amline;
|
||||
// insert new B source line immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( param_end )
|
||||
{
|
||||
param_end->li_next = alloc(struct line);
|
||||
param_end = param_end->li_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
param_end = param_beg = alloc(struct line);
|
||||
}
|
||||
param_end->li_next = NULL;
|
||||
param_end->li_error = NULL;
|
||||
param_end->li_actual = NULL;
|
||||
param_end->li_line = ckt_array[i];
|
||||
param_end->li_linenum = 0;
|
||||
}
|
||||
// comment out current variable capacitor line
|
||||
*(card->li_line) = '*';
|
||||
// insert new param lines immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
card->li_next = param_beg;
|
||||
param_end->li_next = tmp_ptr;
|
||||
// point 'card' pointer to last in scalar list
|
||||
card = param_end;
|
||||
|
||||
param_beg = param_end = NULL;
|
||||
}
|
||||
|
||||
/* Lxxx n1 n2 L = {equation} or Lxxx n1 n2 {equation}
|
||||
-->
|
||||
Lxxx n1 int 1
|
||||
Bxxx int n2 V = ((equation) - 1) * V(n1, int)
|
||||
*/
|
||||
else if ( *curr_line == 'l' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
{ card = card->li_next; continue; }
|
||||
cut_line = curr_line;
|
||||
/* title and nodes */
|
||||
title_tok = gettok(&cut_line);
|
||||
node1 = gettok(&cut_line);
|
||||
node2 = gettok(&cut_line);
|
||||
/* Find equation, starts with '{', till end of line */
|
||||
str_ptr = strstr(cut_line, "{");
|
||||
|
||||
// Bxxx int1 n2 V = (expression(v(somehting)) - 1) * v(n1, int1)
|
||||
xlen = 3*strlen(title_tok) + strlen(str_ptr) + strlen(node1)
|
||||
+ strlen(node2) + 34;
|
||||
eqline = (char*)tmalloc(xlen);
|
||||
sprintf(eqline, "b%s %s_int1 %s v = ((%s) - 1) * v(%s,%s_int1)",
|
||||
title_tok, title_tok, node2, str_ptr, node1, title_tok);
|
||||
// LLxxx n1 int1 1
|
||||
xlen = 2*strlen(title_tok) + strlen(node1) + 11;
|
||||
linline = (char*)tmalloc(xlen);
|
||||
sprintf(linline, "l%s %s %s_int1 1", title_tok, node1, title_tok);
|
||||
|
||||
ckt_array[0] = eqline;
|
||||
ckt_array[1] = linline;
|
||||
// insert new B source line immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
if ( param_end )
|
||||
{
|
||||
param_end->li_next = alloc(struct line);
|
||||
param_end = param_end->li_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
param_end = param_beg = alloc(struct line);
|
||||
}
|
||||
param_end->li_next = NULL;
|
||||
param_end->li_error = NULL;
|
||||
param_end->li_actual = NULL;
|
||||
param_end->li_line = ckt_array[i];
|
||||
param_end->li_linenum = 0;
|
||||
}
|
||||
// comment out current variable capacitor line
|
||||
*(card->li_line) = '*';
|
||||
// insert new param lines immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
card->li_next = param_beg;
|
||||
param_end->li_next = tmp_ptr;
|
||||
// point 'card' pointer to last in scalar list
|
||||
card = param_end;
|
||||
|
||||
param_beg = param_end = NULL;
|
||||
}
|
||||
card = card->li_next;
|
||||
}
|
||||
}
|
||||
/* lines for B sources: no parsing in numparam code, just replacement of parameters.
|
||||
Parsing done in B source parser.
|
||||
To achive this, do the following:
|
||||
Remove all '{' and '}' --> no parsing of equations in numparam
|
||||
Place '{' and '}' directly around all potential parameters,
|
||||
thus skip function names like exp (search for exp( to detect fcn name),
|
||||
functions containing nodes like v(node), v(node1, node2), i(branch)
|
||||
and other keywords. --> Only parameter replacement in numparam
|
||||
|
||||
*/
|
||||
|
||||
static void inp_bsource_compat(struct line *deck)
|
||||
{
|
||||
char *curr_line, *equal_ptr, *str_ptr, *tmp_char, *new_str, *final_str;
|
||||
char actchar, prevchar = ' ';
|
||||
struct line *card = deck, *new_line, *tmp_ptr;
|
||||
wordlist *wl = NULL, *wlist = NULL, *cwl;
|
||||
char buf[512];
|
||||
size_t i, xlen, ustate = 0;
|
||||
|
||||
while ( card != NULL )
|
||||
{
|
||||
curr_line = card->li_line;
|
||||
if ( *curr_line == 'b' ) {
|
||||
/* store starting point for later parsing, beginning of {expression} */
|
||||
equal_ptr = strstr(curr_line, "=");
|
||||
/* find the m={m} token and remove it */
|
||||
if(str_ptr = strstr(curr_line, "m={m}"))
|
||||
*str_ptr = '\0';
|
||||
/* scan the line and remove all '{' and '}' */
|
||||
str_ptr = curr_line;
|
||||
while (*str_ptr) {
|
||||
if ((*str_ptr == '{') || (*str_ptr == '}'))
|
||||
*str_ptr = ' ';
|
||||
str_ptr++;
|
||||
}
|
||||
/* scan the expression */
|
||||
str_ptr = equal_ptr + 1;
|
||||
while (*str_ptr != '\0') {
|
||||
while ((*str_ptr != '\0') && isspace(*str_ptr))
|
||||
str_ptr++;
|
||||
if (*str_ptr == '\0') break;
|
||||
actchar = *str_ptr;
|
||||
cwl = alloc(struct wordlist);
|
||||
cwl->wl_prev = wl;
|
||||
if (wl)
|
||||
wl->wl_next = cwl;
|
||||
else {
|
||||
wlist = cwl;
|
||||
cwl->wl_next = NULL;
|
||||
}
|
||||
if ((actchar == ',') || (actchar == '(') || (actchar == ')')
|
||||
|| (actchar == '*') || (actchar == '/') || (actchar == '^')
|
||||
|| (actchar == '+') || (actchar == '?') || (actchar == ':'))
|
||||
{
|
||||
if ((actchar == '*') && (*(str_ptr+1) == '*')) {
|
||||
actchar = '^';
|
||||
str_ptr++;
|
||||
}
|
||||
buf[0] = actchar;
|
||||
buf[1] = '\0';
|
||||
cwl->wl_word = copy(buf);
|
||||
str_ptr++;
|
||||
if (actchar == ')') ustate = 0;
|
||||
else ustate = 1; /* we have an operator */
|
||||
}
|
||||
else if ((actchar == '>') || (actchar == '<')
|
||||
|| (actchar == '!') || (actchar == '=') )
|
||||
{
|
||||
/* >=, <=, !=, == */
|
||||
if ((*(str_ptr+1) == '=')) {
|
||||
buf[0] = actchar;
|
||||
buf[1] = '=';
|
||||
buf[2] = '\0';
|
||||
str_ptr++;
|
||||
}
|
||||
else {
|
||||
buf[0] = actchar;
|
||||
buf[1] = '\0';
|
||||
}
|
||||
cwl->wl_word = copy(buf);
|
||||
str_ptr++;
|
||||
ustate = 1; /* we have an operator */
|
||||
}
|
||||
else if ((actchar == '-') && (ustate == 0)) {
|
||||
buf[0] = actchar;
|
||||
buf[1] = '\0';
|
||||
cwl->wl_word = copy(buf);
|
||||
str_ptr++;
|
||||
ustate = 1; /* we have an operator */
|
||||
}
|
||||
else if ((actchar == '-') && (ustate == 1)) {
|
||||
cwl->wl_word = copy("");
|
||||
str_ptr++;
|
||||
ustate = 2; /* place a '-' in front of token */
|
||||
}
|
||||
else if (isalpha(actchar))
|
||||
{
|
||||
/* unary -, change sign */
|
||||
if (ustate == 2) {
|
||||
i = 1;
|
||||
buf[0] = '-';
|
||||
}
|
||||
else i = 0;
|
||||
|
||||
if (((actchar == 'v') || (actchar == 'i')) && (*(str_ptr+1) == '(')) {
|
||||
while (*str_ptr != ')') {
|
||||
buf[i] = *str_ptr;
|
||||
i++;
|
||||
str_ptr++;
|
||||
}
|
||||
buf[i] = *str_ptr;
|
||||
buf[i+1] = '\0';
|
||||
cwl->wl_word = copy(buf);
|
||||
str_ptr++;
|
||||
}
|
||||
else {
|
||||
while (isalnum(*str_ptr) || (*str_ptr == '!') || (*str_ptr == '#')
|
||||
|| (*str_ptr == '$')|| (*str_ptr == '%')|| (*str_ptr == '_')
|
||||
|| (*str_ptr == '[')|| (*str_ptr == ']')) {
|
||||
buf[i] = *str_ptr;
|
||||
i++;
|
||||
str_ptr++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
if ((*str_ptr == '(') || cieq(buf, "hertz") || cieq(buf, "temper")
|
||||
|| cieq(buf, "time"))
|
||||
{
|
||||
cwl->wl_word = copy(buf);
|
||||
}
|
||||
else {
|
||||
xlen = strlen(buf);
|
||||
tmp_char = tmalloc(xlen + 3);
|
||||
sprintf(tmp_char, "{%s}", buf);
|
||||
cwl->wl_word = tmp_char;
|
||||
}
|
||||
}
|
||||
ustate = 0; /* we have a number */
|
||||
}
|
||||
else if (isdigit(actchar))
|
||||
{
|
||||
/* unary -, change sign */
|
||||
if (ustate == 2) {
|
||||
i = 1;
|
||||
buf[0] = '-';
|
||||
}
|
||||
else i = 0;
|
||||
while (isdigit(*str_ptr) || (*str_ptr == '.') || (*str_ptr == 'e')
|
||||
|| (*str_ptr == '+')|| (*str_ptr == '-'))
|
||||
{
|
||||
if (((*str_ptr == '+')|| (*str_ptr == '-')) && (*(str_ptr-1) != 'e'))
|
||||
break;
|
||||
buf[i] = *str_ptr;
|
||||
i++;
|
||||
str_ptr++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
cwl->wl_word = copy(buf);
|
||||
ustate = 0; /* we have a number */
|
||||
}
|
||||
else /* strange char */
|
||||
{
|
||||
printf("Preparing B line for numparam\nWhat is this?\n%s\n", str_ptr);
|
||||
buf[0] = *str_ptr;
|
||||
buf[1] = '\0';
|
||||
cwl->wl_word = copy(buf);
|
||||
str_ptr++;
|
||||
}
|
||||
wl = cwl;
|
||||
prevchar = actchar;
|
||||
}
|
||||
|
||||
new_str = wl_flatten(wlist);
|
||||
wl_free(wlist);
|
||||
wl = NULL;
|
||||
|
||||
tmp_char = copy(curr_line);
|
||||
equal_ptr = strstr(tmp_char, "=");
|
||||
/* cut the tmp_char after the equal sign */
|
||||
*(equal_ptr + 1) = '\0';
|
||||
xlen = strlen(tmp_char) + strlen(new_str) + 2;
|
||||
final_str = tmalloc(xlen);
|
||||
sprintf(final_str, "%s %s", tmp_char, new_str);
|
||||
|
||||
new_line = alloc(struct line);
|
||||
new_line->li_next = NULL;
|
||||
new_line->li_error = NULL;
|
||||
new_line->li_actual = NULL;
|
||||
new_line->li_line = final_str;
|
||||
new_line->li_linenum = 0;
|
||||
// comment out current old R line
|
||||
*(card->li_line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
tmp_ptr = card->li_next;
|
||||
card->li_next = new_line;
|
||||
new_line->li_next = tmp_ptr;
|
||||
// point 'card' pointer to the new line
|
||||
card = new_line;
|
||||
|
||||
tfree(new_str);
|
||||
tfree(tmp_char);
|
||||
} /* end of if 'b' */
|
||||
|
||||
card = card->li_next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1248,7 +1248,7 @@ formula (tdico * dico, char *s, unsigned char *perror)
|
|||
{
|
||||
if ((fu == 18))
|
||||
u = ternary_fcn ((int) v, w, u);
|
||||
else if ((fu == 19))
|
||||
else if ((fu == 20))
|
||||
u = agauss (v, w, u);
|
||||
else
|
||||
u = mathfunction (fu, v, u);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
typedef enum {
|
||||
COMPATMODE_NATIVE = 0,
|
||||
COMPATMODE_HSPICE = 1,
|
||||
COMPATMODE_SPICE3 = 2
|
||||
COMPATMODE_SPICE3 = 2,
|
||||
COMPATMODE_ALL = 3,
|
||||
} COMPATMODE_T ;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ typedef struct INPparseNode {
|
|||
#define PTF_LT0 27
|
||||
#define PTF_GE0 28
|
||||
#define PTF_LE0 29
|
||||
|
||||
#define PTF_POW 30
|
||||
#define PTF_MIN 31
|
||||
#define PTF_MAX 32
|
||||
|
||||
/* The following things are used by the parser -- these are the token types the
|
||||
* lexer returns.
|
||||
|
|
@ -177,6 +179,8 @@ extern double PTpwl();
|
|||
extern double PTpwl_derivative();
|
||||
extern double PTuramp();
|
||||
extern double PTuminus();
|
||||
extern double PTmin();
|
||||
extern double PTmax();
|
||||
extern double PTeq0(double arg);
|
||||
extern double PTne0(double arg);
|
||||
extern double PTgt0(double arg);
|
||||
|
|
|
|||
|
|
@ -365,6 +365,8 @@ COMPATMODE_T ngspice_compat_mode(void)
|
|||
char behaviour[80] ;
|
||||
|
||||
if( cp_getvar("ngbehavior", VT_STRING, behaviour)){
|
||||
if (strcasecmp(behaviour,"all")==0)
|
||||
return( COMPATMODE_ALL ) ;
|
||||
if (strcasecmp(behaviour,"hspice")==0)
|
||||
return( COMPATMODE_HSPICE ) ;
|
||||
if (strcasecmp(behaviour,"spice3")==0)
|
||||
|
|
|
|||
|
|
@ -72,18 +72,40 @@ PTeval(INPparseNode * tree, double gmin, double *res, double *vals)
|
|||
break;
|
||||
|
||||
case PT_FUNCTION:
|
||||
err = PTeval(tree->left, gmin, &r1, vals);
|
||||
if (err != OK)
|
||||
return (err);
|
||||
if(tree->data == NULL)
|
||||
*res = (*tree->function) (r1);
|
||||
else
|
||||
*res = (*tree->function) (r1, tree->data);
|
||||
if (*res == HUGE) {
|
||||
fprintf(stderr, "Error: %g out of range for %s\n",
|
||||
r1, tree->funcname);
|
||||
return (E_PARMVAL);
|
||||
}
|
||||
switch(tree->funcnum) {
|
||||
|
||||
case PTF_POW:
|
||||
case PTF_MIN:
|
||||
case PTF_MAX:
|
||||
err = PTeval(tree->left->left, gmin, &r1, vals);
|
||||
if (err != OK)
|
||||
return (err);
|
||||
err = PTeval(tree->left->right, gmin, &r2, vals);
|
||||
if (err != OK)
|
||||
return (err);
|
||||
*res = (*tree->function) (r1, r2);
|
||||
if (*res == HUGE) {
|
||||
fprintf(stderr, "Error: %g, %g out of range for %s\n",
|
||||
r1, r2, tree->funcname);
|
||||
return (E_PARMVAL);
|
||||
}
|
||||
break;
|
||||
/* fcns with single argument */
|
||||
default:
|
||||
err = PTeval(tree->left, gmin, &r1, vals);
|
||||
if (err != OK)
|
||||
return (err);
|
||||
if(tree->data == NULL)
|
||||
*res = (*tree->function) (r1);
|
||||
else
|
||||
*res = (*tree->function) (r1, tree->data);
|
||||
if (*res == HUGE) {
|
||||
fprintf(stderr, "Error: %g out of range for %s\n",
|
||||
r1, tree->funcname);
|
||||
return (E_PARMVAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PT_TERN:
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ static struct func {
|
|||
{ "lt0", PTF_LT0, PTlt0},
|
||||
{ "ge0", PTF_GE0, PTge0},
|
||||
{ "le0", PTF_LE0, PTle0},
|
||||
{ "pow", PTF_POW, PTpower},
|
||||
{ "min", PTF_MIN, PTmin},
|
||||
{ "max", PTF_MAX, PTmax},
|
||||
} ;
|
||||
|
||||
#define NUM_FUNCS (int)(sizeof (funcs) / sizeof (struct func))
|
||||
|
|
@ -438,6 +441,57 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
|||
arg1 = mkcon((double) 0.0);
|
||||
break;
|
||||
|
||||
case PTF_MIN:
|
||||
/*
|
||||
min(a,b)
|
||||
p->left: ',' p->left->left: a p->left->right: b
|
||||
*/
|
||||
newp = mkcon((double) 0);
|
||||
return (newp);
|
||||
|
||||
case PTF_MAX:
|
||||
newp = mkcon((double) 0);
|
||||
return (newp);
|
||||
|
||||
case PTF_POW:
|
||||
{
|
||||
/*
|
||||
pow(a,b)
|
||||
p->left: ',' p->left->left: a p->left->right: b
|
||||
*/
|
||||
|
||||
/* Two cases...
|
||||
The power is constant
|
||||
*/
|
||||
if (p->left->right->type == PT_CONSTANT) {
|
||||
arg1 = PTdifferentiate(p->left->left, varnum);
|
||||
|
||||
newp = mkb(PT_TIMES, mkb(PT_TIMES,
|
||||
mkcon(p->left->right->constant),
|
||||
mkb(PT_POWER, p->left->left,
|
||||
mkcon(p->left->right->constant - 1))),
|
||||
arg1);
|
||||
} else {
|
||||
/* This is complicated. f(x) ^ g(x) ->
|
||||
exp(y(x) * ln(f(x)) ...
|
||||
*/
|
||||
arg1 = PTdifferentiate(p->left->left, varnum);
|
||||
arg2 = PTdifferentiate(p->left->right, varnum);
|
||||
newp = mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES,
|
||||
p->left->right, mkf(PTF_LN,
|
||||
p->left->left))),
|
||||
mkb(PT_PLUS,
|
||||
mkb(PT_TIMES, p->left->right,
|
||||
mkb(PT_DIVIDE, arg1, p->left->left)),
|
||||
mkb(PT_TIMES, arg2, mkf(PTF_LN, /*arg1*/p->left->left))));
|
||||
/*changed by HT, '05/06/29*/
|
||||
|
||||
}
|
||||
arg2 = PTdifferentiate(p->left->left, varnum);
|
||||
newp = mkb(PT_TIMES, arg1, arg2);
|
||||
return (newp);
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Internal Error: bad function # %d\n",
|
||||
p->funcnum);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,18 @@ PTpower(double arg1, double arg2)
|
|||
return (pow(arg1, arg2));
|
||||
}
|
||||
|
||||
double
|
||||
PTmin(double arg1, double arg2)
|
||||
{
|
||||
return arg1 > arg2 ? arg2 : arg1;
|
||||
}
|
||||
|
||||
double
|
||||
PTmax(double arg1, double arg2)
|
||||
{
|
||||
return arg1 > arg2 ? arg1 : arg2;
|
||||
}
|
||||
|
||||
double
|
||||
PTacos(double arg)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue