|
|
|
@ -120,6 +120,7 @@ static char *inp_remove_ws(char *s); |
|
|
|
static void inp_compat(struct card *deck); |
|
|
|
static void inp_bsource_compat(struct card *deck); |
|
|
|
static bool inp_temper_compat(struct card *card); |
|
|
|
static void inp_meas_current(struct card *card); |
|
|
|
static void inp_dot_if(struct card *deck); |
|
|
|
static char *inp_modify_exp(char* expression); |
|
|
|
static struct func_temper *inp_new_func(char *funcname, char *funcbody, struct card *card, |
|
|
|
@ -579,6 +580,7 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile, bool *expr_w_t |
|
|
|
if (inp_compat_mode != COMPATMODE_SPICE3) { |
|
|
|
/* Do all the compatibility stuff here */ |
|
|
|
working = cc->nextcard; |
|
|
|
inp_meas_current(working); |
|
|
|
/* E, G, L, R, C compatibility transformations */ |
|
|
|
inp_compat(working); |
|
|
|
working = cc->nextcard; |
|
|
|
@ -6055,7 +6057,6 @@ inp_quote_params(struct card *c, struct card *end_c, struct dependency *deps, in |
|
|
|
Assemble all other tokens in a wordlist, and flatten it |
|
|
|
to become the new .model line. |
|
|
|
*/ |
|
|
|
|
|
|
|
static void |
|
|
|
inp_vdmos_model(struct card *deck) |
|
|
|
{ |
|
|
|
@ -6099,3 +6100,205 @@ inp_vdmos_model(struct card *deck) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* storage for devices which get voltage source added */ |
|
|
|
struct replace_currm |
|
|
|
{ |
|
|
|
struct card *s_start; |
|
|
|
struct card *cline; |
|
|
|
char *rtoken; |
|
|
|
struct replace_currm *next; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Measure current in node 1 of all devices, e.g. I, B, F, and G. |
|
|
|
I(V...) will be ignored, however H, E nonlinear voltage |
|
|
|
sources may be converted later |
|
|
|
to B source, therefore we need to add current measurement here. |
|
|
|
First find all ocurrencies of i(XYZ), store their cards, then |
|
|
|
search for XYZ, but only within respective subcircuit, or if |
|
|
|
all happens at top level. Other hierarchy is ignored for now. |
|
|
|
Replace I(XYZ) bx I(V_XYZ), add voltage source V_XYZ with |
|
|
|
suitable extra nodes. |
|
|
|
*/ |
|
|
|
static void |
|
|
|
inp_meas_current(struct card *deck) |
|
|
|
{ |
|
|
|
struct card *card, *subc_start = NULL, *subc_prev = NULL; |
|
|
|
struct replace_currm *new_rep, *act_rep = NULL, *rep = NULL; |
|
|
|
char *s, *t, *u, *v; |
|
|
|
int skip_control = 0, subs = 0; |
|
|
|
|
|
|
|
/* scan through deck and find i(xyz), replace by i(v_xyz) */ |
|
|
|
for (card = deck; card; card = card->nextcard) { |
|
|
|
|
|
|
|
char *curr_line = card->line; |
|
|
|
|
|
|
|
/* exclude any command inside .control ... .endc */ |
|
|
|
if (ciprefix(".control", curr_line)) { |
|
|
|
skip_control++; |
|
|
|
continue; |
|
|
|
} |
|
|
|
else if (ciprefix(".endc", curr_line)) { |
|
|
|
skip_control--; |
|
|
|
continue; |
|
|
|
} |
|
|
|
else if (skip_control > 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (*curr_line == '*') |
|
|
|
continue; |
|
|
|
|
|
|
|
if (*curr_line == '.') { |
|
|
|
if (ciprefix(".subckt", curr_line)) { |
|
|
|
subs++; |
|
|
|
subc_prev = subc_start; |
|
|
|
subc_start = card; |
|
|
|
} |
|
|
|
else if (ciprefix(".ends", curr_line)) { |
|
|
|
subs--; |
|
|
|
subc_start = subc_prev; |
|
|
|
} |
|
|
|
else |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (!strstr(curr_line, "i(")) |
|
|
|
continue; |
|
|
|
|
|
|
|
s = v = stripWhiteSpacesInsideParens(curr_line); |
|
|
|
while (s) { |
|
|
|
/* i( may occur more than once in a line */ |
|
|
|
s = u = strstr(s, "i("); |
|
|
|
/* we have found it, but not (in error) at the beginning of the line */ |
|
|
|
if (s && s > v) { |
|
|
|
/* '{' if at beginning of expression */ |
|
|
|
if (is_arith_char(s[-1]) || s[-1] == '{') { |
|
|
|
s += 2; |
|
|
|
if (*s == 'v') { |
|
|
|
// printf("i(v...) found in\n%s\n not converted!\n\n", curr_line); |
|
|
|
continue; |
|
|
|
} |
|
|
|
else { |
|
|
|
char *beg_str, *new_str; |
|
|
|
get_r_paren(&u); |
|
|
|
/* token containing name of devices to be measured */ |
|
|
|
t = copy_substring(s, --u); |
|
|
|
if (ft_ngdebug) |
|
|
|
printf("i(%s) found in\n%s\n\n", t, curr_line); |
|
|
|
|
|
|
|
/* new entry to the end of struct rep */ |
|
|
|
new_rep = TMALLOC(struct replace_currm, 1); |
|
|
|
new_rep->s_start = subc_start; |
|
|
|
new_rep->next = NULL; |
|
|
|
new_rep->cline = card; |
|
|
|
new_rep->rtoken = t; |
|
|
|
if (act_rep) { |
|
|
|
act_rep->next = new_rep; |
|
|
|
act_rep = act_rep->next; |
|
|
|
} |
|
|
|
else |
|
|
|
rep = act_rep = new_rep; |
|
|
|
/* change line, convert i(XXX) to i(v_XXX) */ |
|
|
|
beg_str = copy_substring(v, s); |
|
|
|
new_str = tprintf("%s%s%s", beg_str, "v_", s); |
|
|
|
if (ft_ngdebug) |
|
|
|
printf("converted to\n%s\n\n", new_str); |
|
|
|
tfree(curr_line); |
|
|
|
tfree(v); |
|
|
|
card->line = s = v = new_str; |
|
|
|
s++; |
|
|
|
tfree(beg_str); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
s++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* return if we did not find any i( */ |
|
|
|
if (rep == NULL) |
|
|
|
return; |
|
|
|
|
|
|
|
/* scan through all the devices, search for xyz, modify node 1 by adding _vmeas, |
|
|
|
add a line with zero voltage v_xyz, having original node 1 and modified node 1. |
|
|
|
Do this within the top level or the same level of subcircuit only. */ |
|
|
|
new_rep = rep; |
|
|
|
for (; rep; rep = rep->next) { |
|
|
|
card = rep->s_start; |
|
|
|
subs = 0; |
|
|
|
if (card) |
|
|
|
card = card->nextcard; |
|
|
|
else |
|
|
|
card = deck; |
|
|
|
for (; card; card = card->nextcard) { |
|
|
|
char *tok, *new_tok, *node1, *new_line; |
|
|
|
char *curr_line = card->line; |
|
|
|
/* exclude any command inside .control ... .endc */ |
|
|
|
if (ciprefix(".control", curr_line)) { |
|
|
|
skip_control++; |
|
|
|
continue; |
|
|
|
} |
|
|
|
else if (ciprefix(".endc", curr_line)) { |
|
|
|
skip_control--; |
|
|
|
continue; |
|
|
|
} |
|
|
|
else if (skip_control > 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (*curr_line == '*') |
|
|
|
continue; |
|
|
|
|
|
|
|
if (*curr_line == '.') { |
|
|
|
if (ciprefix(".subckt", curr_line)) |
|
|
|
subs++; |
|
|
|
else if (ciprefix(".ends", curr_line)) |
|
|
|
subs--; |
|
|
|
else |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (subs > 0) |
|
|
|
continue; |
|
|
|
/* We are at now top level or in top level of subcircuit |
|
|
|
where i(xyz) has been found */ |
|
|
|
tok = gettok(&curr_line); |
|
|
|
/* done when end of subcircuit is reached */ |
|
|
|
if (eq(".ends", tok) && rep->s_start) |
|
|
|
break; |
|
|
|
if (eq(rep->rtoken, tok)) { |
|
|
|
node1 = gettok(&curr_line); |
|
|
|
/* Add _vmeas only once to first device node. |
|
|
|
Continue if we already have modified device "tok" */ |
|
|
|
if (!strstr(node1, "_vmeas")) { |
|
|
|
new_line = tprintf("%s %s_vmeas %s", tok, node1, curr_line); |
|
|
|
tfree(card->line); |
|
|
|
card->line = new_line; |
|
|
|
} |
|
|
|
|
|
|
|
new_tok = tprintf("v_%s", tok); |
|
|
|
/* We have already added a line v_xyz to the deck */ |
|
|
|
if (!ciprefix(new_tok, card->nextcard->line)) { |
|
|
|
/* add new line */ |
|
|
|
new_line = tprintf("%s %s %s_vmeas 0", new_tok, node1, node1); |
|
|
|
/* insert new_line after card->line */ |
|
|
|
insert_new_line(card, new_line, card->linenum + 1, 0); |
|
|
|
} |
|
|
|
tfree(new_tok); |
|
|
|
tfree(node1); |
|
|
|
} |
|
|
|
tfree(tok); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* free rep */ |
|
|
|
while (new_rep) { |
|
|
|
struct replace_currm *repn = new_rep->next; |
|
|
|
tfree(new_rep->rtoken); |
|
|
|
tfree(new_rep); |
|
|
|
new_rep = repn; |
|
|
|
} |
|
|
|
} |