Browse Source

Add current measurement for device XYZ using I(XYZ)

pre-master-46
Holger Vogt 8 years ago
parent
commit
429326e139
  1. 205
      src/frontend/inpcom.c

205
src/frontend/inpcom.c

@ -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;
}
}
Loading…
Cancel
Save