From 458b6cf7762c7e8cbbc7b6098d8b2f0f375d5f84 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 23 Apr 2022 20:07:52 +0200 Subject: [PATCH] Add flag 'power' to fcn setallvsources() Add code to calculate the power dissipation in a device (top level instances, including X (subcircuit) invocations). --- src/frontend/inpc_probe.c | 121 +++++++++++++++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 9 deletions(-) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 2445e7bbb..bf83c6bcc 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -22,13 +22,14 @@ extern char* search_plain_identifier(char* str, const char* identifier); static char* get_terminal_name(char* element, char* numberstr, NGHASHPTR instances); static char* get_terminal_number(char* element, char* numberstr); -static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall); +static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall, bool power); /* Find any line starting with .probe: assemble all parameters like add V(0) current measure sources to all device nodes in addition to .save all alli add V(0) current measure sources to all device nodes in addition to .save all I(R1) add V(0) measure source to node 1 of a two-terminal device R1 + I(Q1) add V(0) measure sources to all nodes of a multi-terminal device Q1 I(M4,3) add V(0) measure source to node 3 of a multi-terminal device M4 Vd(R1) add E source inputs to measure voltage difference to both terminals of a two-terminal device R1 Vd(X1:2:3) add E source inputs to terminals 2 and 3 of a multi-terminal device X1 @@ -745,7 +746,7 @@ void inp_probe(struct card* deck) else if (!node1 && numnodes > 2) { int err = 0; tfree(nodename1); - err = setallvsources(tmpcard, instances, instname, numnodes, haveall); + err = setallvsources(tmpcard, instances, instname, numnodes, haveall, FALSE); if (err) { fprintf(stderr, "Warning: Cannot set zero voltage sources,\n .probe %s will be ignored\n", wltmp->wl_word); } @@ -807,6 +808,33 @@ void inp_probe(struct card* deck) tfree(nodename1); } } + /* measure the power of a device */ + else if (ciprefix("p(", tmpstr)) + { + char* instname; + struct card* tmpcard; + int numnodes; + + tmpstr += 2; + instname = gettok_noparens(&tmpstr); + tmpcard = nghash_find(instances, instname); + if (!tmpcard) { + fprintf(stderr, "Warning: Could not find the instance line for %s,\n .probe %s will be ignored\n", instname, wltmp->wl_word); + continue; + } + char* thisline = tmpcard->line; + numnodes = get_number_terminals(thisline); + int err = 0; + /* call fcn with power requested */ + err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE); + if (err == 1) { + fprintf(stderr, "Warning: Cannot set zero voltage sources,\n .probe %s will be ignored\n", wltmp->wl_word); + } + else if (err == 2) { + fprintf(stderr, "Warning: Zero voltage sources already set,\n .probe %s will be ignored\n", wltmp->wl_word); + } + continue; + } else if (!haveall) { fprintf(stderr, "Warning: unknown .probe parameter %s,\n .probe %s will be ignored!\n", tmpstr, wltmp->wl_word); continue; @@ -1183,18 +1211,53 @@ void modprobenames(INPtables* tab) { } } -static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instname, int numnodes, bool haveall) +/* If a command like .probe i(Q1) is found, set 0 VSRC (voltage source) in series to all nodes of the device Q1. + Polarity of VSRC is that its node 2 is directed towards the device, its node 1 towards the outer net connection. + If .probe p(Q1) is found, flag power is true, then do additional power calculations: + Define a reference voltage of an n-terminal device as Vref = (V(1) + V(2) +...+ V(n)) / n with terminal (node) voltages V(n). + Calculate power PQ1 = (v(1) - Vref) * i1 + (V(2) - Vref) * i2 + ... + (V(n) - Vref) * in) with terminal currents in. + See "Quantities of a Multiterminal Circuit Determined on the Basis of Kirchhoff’s Laws", M. Depenbrock, + ETEP Vol. 8, No. 4, July/August 1998 */ +static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instname, int numnodes, bool haveall, bool power) { struct card* card; char* newline; int nodenum; - bool err = FALSE; + int err = 0; wordlist * allsaves = NULL; - if (haveall) - return 1; + if (haveall && !power) + return 2; + DS_CREATE(BVrefline, 200); + DS_CREATE(Bpowerline, 200); + DS_CREATE(Bpowersave, 200); + + if (power) { + /* For example: Bq1Vref q1Vref 0 V = 1/3*( */ + char numbuf[3]; + cadd(&BVrefline, 'B'); + sadd(&BVrefline, instname); + sadd(&BVrefline, "Vref "); + sadd(&BVrefline, instname); + sadd(&BVrefline, "Vref 0 V = 1/"); + sadd(&BVrefline, _itoa(numnodes, numbuf, 10)); + sadd(&BVrefline, "*("); + /* For example: Bq1power q1:power 0 V = */ + cadd(&Bpowerline, 'B'); + sadd(&Bpowerline, instname); + sadd(&Bpowerline, "power "); + sadd(&Bpowerline, instname); + cadd(&Bpowerline, ':'); + sadd(&Bpowerline, "power 0 V = 0+"); + /* For example: q1:power */ + sadd(&Bpowersave, instname); + cadd(&Bpowersave, ':'); + sadd(&Bpowersave, "power"); + } + + /* Scan through all nodes of the device */ for (nodenum = 1; nodenum <= numnodes; nodenum++) { int i; char* instline = tmpcard->line; @@ -1218,16 +1281,46 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn card = insert_new_line(card, vline, 0, 0); + char* nodesaves; /* special treatment for xlines: keep the x if next char is a number */ if (*instname == 'x' && !isdigit_c(instname[1])) { - char* nodesaves = tprintf("%s:%s#branch", instname + 1, nodename1); + nodesaves = tprintf("%s:%s#branch", instname + 1, nodename1); allsaves = wl_cons(nodesaves, allsaves); } else { - char* nodesaves = tprintf("%s:%s#branch", instname, nodename1); + nodesaves = tprintf("%s:%s#branch", instname, nodename1); allsaves = wl_cons(nodesaves, allsaves); } + if (power) { + /* For example V(1)+V(2)+V(3)*/ + if (nodenum == 1) + sadd(&BVrefline, "V("); + else + sadd(&BVrefline, "+V("); + sadd(&BVrefline, newnode); + cadd(&BVrefline, ')'); + /*For example: (V(node1)-V(q1Vref))*node1#branch+(V(node2)-V(q1Vref))*node2#branch */ + if (nodenum == 1) + sadd(&Bpowerline, "(V("); + else + sadd(&Bpowerline, "+(V("); + sadd(&Bpowerline, newnode); + sadd(&Bpowerline, ")-V("); + sadd(&Bpowerline, instname); + sadd(&Bpowerline, "Vref))*i(vcurr_"); + sadd(&Bpowerline, instname); + cadd(&Bpowerline, ':'); + sadd(&Bpowerline, nodename1); + cadd(&Bpowerline, ':'); + sadd(&Bpowerline, nodenumstr); + cadd(&Bpowerline, '_'); + sadd(&Bpowerline, strnode1); + cadd(&Bpowerline, ')'); + + allsaves = wl_cons(copy(ds_get_buf(&Bpowersave)), allsaves); + } + tfree(begstr); tfree(strnode1); tfree(newnode); @@ -1243,5 +1336,15 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn card = insert_new_line(card, newsaveline, 0, 0); } - return 0; + if (power) { + cadd(&BVrefline, ')'); + card = tmpcard->nextcard; + card = insert_new_line(card, copy(ds_get_buf(&BVrefline)), 0, 0); + card = insert_new_line(card, copy(ds_get_buf(&Bpowerline)), 0, 0); + } + + ds_free(&BVrefline); + ds_free(&Bpowerline); + ds_free(&Bpowersave); + return err; }