Browse Source

.meas patches by Bill Swartz added

pre-master-46
h_vogt 17 years ago
parent
commit
b399caf9bc
  1. 5
      ChangeLog
  2. 9
      examples/inverter.sp
  3. 333
      src/frontend/com_measure2.c
  4. 5
      src/frontend/com_measure2.h
  5. 91
      src/frontend/measure.c
  6. 13
      src/frontend/numparam/xpressn.c
  7. 12
      visualc/vngspice.vcproj

5
ChangeLog

@ -2,6 +2,11 @@
* src/frontend/resource.c: applied patch from Thomas D. Dean to remove
the limit warning.
2009-08-08 Holger Vogt
* measure.c, com_measure2.c, com_measure2.h, xpressn.c:
Patches from Bill Swartz added
* examples/inverter3.sp: test of new features
2009-08-08 Holger Vogt
* measure.c: add more comments
* example/func_cap.sp, inverter.sp, inverter2.sp: hint to

9
examples/inverter.sp

@ -79,12 +79,15 @@ c1 out gnd 220fF
.tran 1ps 4ns
.meas tran inv_delay trig v(in) val='vp/2' fall=1 targ v(out) val='vp/2' rise=1
.meas tran out_slew trig v(out) val='0.2*vp' rise=1 targ v(out) val='0.8*vp' rise=1
*.meas tran test_data1 trig AT = 1n targ v(out) val='vp/2' rise=3
*not yet implemented
*.meas tran test_data2 trig v(in) val='vp/2' fall=1 targ AT = 2n
.meas tran out_slew trig v(out) val='0.2*vp' rise=2 targ v(out) val='0.8*vp' rise=2
.meas tran delay_chk param='(inv_delay < 100ps) ? 1 : 0'
.meas tran skew when v(out)=0.6
.meas tran skew2 when v(out)=skew_meas
.meas tran skew3 when v(out)=skew_meas fall=2 *fall is ignored
*.meas tran skew when v(out)=v(in) not implemented
*.meas tran skew3 when v(out)=skew_meas fall=2
*.meas tran skew4 FIND v(out) AT=2n
.control
run

333
src/frontend/com_measure2.c

@ -1,3 +1,10 @@
/* New routines to evaluate the .measure cards.
Entry point is function get_measure2(), called by fcn do_measure()
from measure.c, if line measure.c:25 is commented out.
Patches by Bill Swartz from 2009-05-18 are included.
$Id$
*/
#include <config.h>
#include <ngspice.h>
#include <memory.h>
@ -7,11 +14,20 @@
#include "vectors.h"
#include <math.h>
#include "com_measure2.h"
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
typedef enum {
MEASUREMENT_OK = 0,
MEASUREMENT_FAILURE = 1
} MEASURE_VAL_T ;
#define MEASURE_DEFAULT -1
#define MEASURE_LAST_TRANSITION -2
typedef struct measure
{
char *result;
@ -21,13 +37,13 @@ typedef struct measure
int m_rise;
int m_fall;
int m_cross;
float m_val; // value of the m_ver at which the counter for crossing, rises or falls is incremented by one
float m_td; // amount of delay before the measurement should start
float m_from;
float m_to;
float m_at;
float m_measured;
float m_measured_at;
double m_val; // value of the m_ver at which the counter for crossing, rises or falls is incremented by one
double m_td; // amount of delay before the measurement should start
double m_from;
double m_to;
double m_at;
double m_measured;
double m_measured_at;
} measure;
@ -39,15 +55,30 @@ enum AnalysisType {
AT_ERR, AT_ERR1, AT_ERR2, AT_ERR3
};
/** return precision (either 5 or value of environment variable NGSPICE_MEAS_PRECISION) */
int get_measure_precision(void)
{
char *env_ptr;
int precision = 5;
if ( ( env_ptr = getenv("NGSPICE_MEAS_PRECISION") ) ) {
precision = atoi(env_ptr);
}
return precision;
} /* end measure_get_precision() */
void com_measure_when(struct measure *meas) {
int i, first;
int riseCnt =0;
int fallCnt =0;
int crossCnt =0;
int riseCnt = 0;
int fallCnt = 0;
int crossCnt = 0;
int section = -1;
float value, prevValue;
float timeValue, prevTimeValue;
int measurement_pending;
int init_measured_value;
double value, prevValue;
double timeValue, prevTimeValue;
enum ValSide { S_ABOVE_VAL, S_BELOW_VAL };
enum ValEdge { E_RISING, E_FALLING };
@ -70,6 +101,8 @@ void com_measure_when(struct measure *meas) {
prevValue =0;
prevTimeValue =0;
first =0;
measurement_pending=0;
init_measured_value=1;
for (i=0; i < d->v_length; i++) {
@ -105,18 +138,41 @@ void com_measure_when(struct measure *meas) {
section = S_ABOVE_VAL;
crossCnt++;
riseCnt++;
if( meas->m_fall != MEASURE_LAST_TRANSITION ){
/* we can measure rise/cross transition if the user
* has not requested a last fall transition */
measurement_pending=1;
}
} else if ( (section == S_ABOVE_VAL) && (value <= meas->m_val) ) {
section = S_BELOW_VAL;
crossCnt++;
fallCnt++;
if( meas->m_rise != MEASURE_LAST_TRANSITION ){
/* we can measure fall/cross transition if the user
* has not requested a last rise transition */
measurement_pending=1;
}
}
if ((crossCnt == meas->m_cross) || (riseCnt == meas->m_rise) || (fallCnt == meas->m_fall)) {
meas->m_measured = prevTimeValue + (meas->m_val - prevValue) * (timeValue - prevTimeValue) / (value - prevValue);
return;
/* user requested an exact match of cross, rise, or fall
* exit when we meet condition */
meas->m_measured = prevTimeValue + (meas->m_val - prevValue) * (timeValue - prevTimeValue) / (value - prevValue);
return;
}
if ( measurement_pending ){
if( (meas->m_cross == MEASURE_DEFAULT) && (meas->m_rise == MEASURE_DEFAULT) && (meas->m_fall == MEASURE_DEFAULT) ){
/* user didn't request any option, return the first possible case */
meas->m_measured = prevTimeValue + (meas->m_val - prevValue) * (timeValue - prevTimeValue) / (value - prevValue);
return;
} else if( (meas->m_cross == MEASURE_LAST_TRANSITION) || (meas->m_rise == MEASURE_LAST_TRANSITION) || (meas->m_fall == MEASURE_LAST_TRANSITION) ){
meas->m_measured = prevTimeValue + (meas->m_val - prevValue) * (timeValue - prevTimeValue) / (value - prevValue);
/* no return - look for last */
init_measured_value=0;
}
measurement_pending=0;
}
}
first ++;
@ -124,14 +180,16 @@ void com_measure_when(struct measure *meas) {
prevTimeValue = timeValue;
}
meas->m_measured = 0.0e0;
if ( init_measured_value ){
meas->m_measured = 0.0e0;
}
return;
}
void measure_at(struct measure *meas, float at) {
void measure_at(struct measure *meas, double at) {
int i;
float value, pvalue, svalue, psvalue;
double value, pvalue, svalue, psvalue;
struct dvec *d, *dScale;
psvalue = pvalue = 0;
@ -176,7 +234,7 @@ void measure_minMaxAvg( struct measure *meas, int minMax ) {
int i, avgCnt;
struct dvec *d, *dScale;
float value, svalue, mValue, mValueAt;
double value, svalue, mValue, mValueAt;
int first;
mValue =0;
@ -298,8 +356,8 @@ void measure_ERR3( ) {
return;
}
void measure_errMessage(char *mName, char *mFunction, char *trigTarg, char *errMsg) {
void measure_errMessage(char *mName, char *mFunction, char *trigTarg, char *errMsg, bool autocheck) {
if (autocheck) return;
printf("\tmeasure '%s' failed\n", mName);
printf("Error: measure %s %s(%s) :\n", mName, mFunction, trigTarg);
printf("\t%s\n",errMsg);
@ -318,7 +376,9 @@ void com_dotmeasure( ) {
int measure_valid_vector(char *vec) {
struct dvec *d;
if(vec == NULL)
return 1;
d = vec_get(vec);
if (d == NULL)
return 0;
@ -332,34 +392,46 @@ int measure_parse_stdParams (struct measure *meas, wordlist *wl, wordlist *wlBre
char *p, *pName, *pValue;
double *engVal, engVal1;
pCnt =0;
pCnt = 0;
while (wl != wlBreak) {
p = wl->wl_word;
pName = strtok(p, "=");
pValue = strtok(NULL, "=");
if (pValue == NULL) {
sprintf(errbuf,"bad syntax of ??\n");
return 0;
}
if (!(engVal = ft_numparse(&pValue, FALSE))) {
sprintf(errbuf,"bad syntax of ??\n");
return 0;
}
engVal1 = *engVal;
if (pValue == NULL) {
if( strcasecmp(pName,"LAST")==0) {
meas->m_cross = MEASURE_LAST_TRANSITION;
meas->m_rise = -1;
meas->m_fall = -1;
pCnt ++;
wl = wl->wl_next;
continue ;
} else {
sprintf(errbuf,"bad syntax of ??\n");
return 0;
}
}
if( strcasecmp(pValue,"LAST")==0) {
engVal1 = MEASURE_LAST_TRANSITION;
} else {
if (!(engVal = ft_numparse(&pValue, FALSE))) {
sprintf(errbuf,"bad syntax of ??\n");
return 0;
}
engVal1 = *engVal; // What is this ??
}
if(strcasecmp(pName,"RISE")==0) {
meas->m_rise = engVal1;
meas->m_rise = (int)engVal1;
meas->m_fall = -1;
meas->m_cross = -1;
} else if(strcasecmp(pName,"FALL")==0) {
meas->m_fall = engVal1;
meas->m_fall = (int)engVal1;
meas->m_rise = -1;
meas->m_cross = -1;
} else if(strcasecmp(pName,"CROSS")==0) {
meas->m_cross = engVal1;
meas->m_cross = (int)engVal1;
meas->m_rise = -1;
meas->m_fall = -1;
} else if(strcasecmp(pName,"VAL")==0) {
@ -531,10 +603,11 @@ int measure_parse_trigtarg (struct measure *meas, wordlist *words, wordlist *wlT
while (words != wlTarg) {
p = words->wl_word;
if (pcnt ==0) {
// meas->m_vec =(char *)tmalloc(strlen(words->wl_word)+1);
// strcpy(meas->m_vec, cp_unquote(words->wl_word));
if ((pcnt == 0) && !ciprefix("at", p)) {
meas->m_vec= cp_unquote(words->wl_word);
} else if (ciprefix("at", p)) {
if (measure_parse_stdParams(meas, words, wlTarg, errbuf) == 0)
return 0;
} else {
if (measure_parse_stdParams(meas, words, wlTarg, errbuf) == 0)
@ -561,32 +634,34 @@ int measure_parse_trigtarg (struct measure *meas, wordlist *words, wordlist *wlT
return 1;
}
float
get_measure2(wordlist *wl)
int
get_measure2(wordlist *wl,double *result,char *out_line, bool autocheck)
{
wordlist *words, *wlTarg, *wlWhen;
char errbuf[100];
char *mType = NULL; // analysis type
char *mName = NULL; // name given to the measured output
char *mFunction = NULL;
int precision; // measurement precision
int mFunctionType, wl_cnt;
char *p;
mFunctionType = -1;
*result = 0.0e0; /* default result */
if (!wl) {
printf("usage: measure .....\n");
return 0.0e0;
return MEASUREMENT_FAILURE;
}
if (!plot_cur || !plot_cur->pl_dvecs || !plot_cur->pl_scale) {
fprintf(cp_err, "Error: no vectors available\n");
return 0.0e0;
return MEASUREMENT_FAILURE;
}
if (!ciprefix("tran", plot_cur->pl_typename)) {
fprintf(cp_err, "Error: measure limited to transient analysis\n");
return 0.0e0;
return MEASUREMENT_FAILURE;
}
words =wl;
@ -595,10 +670,11 @@ get_measure2(wordlist *wl)
if (!words) {
fprintf(cp_err, "Error: no assignment found.\n");
return 0.0e0;
return MEASUREMENT_FAILURE;
}
wl_cnt = 0;
precision = get_measure_precision() ;
wl_cnt = 0;
while (words) {
switch(wl_cnt)
@ -647,7 +723,7 @@ get_measure2(wordlist *wl)
printf("\tmeasure '%s' failed\n", mName);
printf("Error: measure %s :\n", mName);
printf("\tno such function as '%s'\n", mFunction);
return 0.0e0;
return MEASUREMENT_FAILURE;
}
break;
}
@ -672,7 +748,7 @@ get_measure2(wordlist *wl)
printf("\tmeasure '%s' failed\n", mName);
printf("Error: measure %s :\n", mName);
printf("\tinvalid num params\n");
return 0.0e0;
return MEASUREMENT_FAILURE;
}
//------------------------
@ -700,14 +776,14 @@ get_measure2(wordlist *wl)
measTarg = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_trigtarg(measTrig, words , wlTarg, "trig", errbuf)==0) {
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
if ((measTrig->m_rise == -1) && (measTrig->m_fall == -1) && (measTrig->m_cross == -1)) {
sprintf(errbuf,"rise, fall or cross must be given\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
if ((measTrig->m_rise == -1) && (measTrig->m_fall == -1) && (measTrig->m_cross == -1) && (measTrig->m_at == -1)) {
sprintf(errbuf,"at, rise, fall or cross must be given\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
while (words != wlTarg)
@ -717,14 +793,14 @@ get_measure2(wordlist *wl)
words = words->wl_next; // skip targ
if (measure_parse_trigtarg(measTarg, words , NULL, "targ", errbuf)==0) {
measure_errMessage(mName, mFunction, "TARG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TARG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
if ((measTarg->m_rise == -1) && (measTarg->m_fall == -1) && (measTarg->m_cross == -1)) {
sprintf(errbuf,"rise, fall or cross must be given\n");
measure_errMessage(mName, mFunction, "TARG", errbuf);
return 0.0e0;
if ((measTarg->m_rise == -1) && (measTarg->m_fall == -1) && (measTarg->m_cross == -1)&& (measTarg->m_at == -1)) {
sprintf(errbuf,"at, rise, fall or cross must be given\n");
measure_errMessage(mName, mFunction, "TARG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// measure trig
@ -736,22 +812,27 @@ get_measure2(wordlist *wl)
if (measTrig->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// measure targ
com_measure_when(measTarg);
if (measTarg->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TARG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TARG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// print results
printf("%-20s= %e targ= %e trig= %e\n", mName, (measTarg->m_measured - measTrig->m_measured), measTarg->m_measured, measTrig->m_measured);
return (measTarg->m_measured - measTrig->m_measured);
if( out_line ){
sprintf(out_line,"%-20s= %e targ= %e trig= %e\n", mName, (measTarg->m_measured - measTrig->m_measured), measTarg->m_measured, measTrig->m_measured);
} else {
printf("%-20s= %e targ= %e trig= %e\n", mName, (measTarg->m_measured - measTrig->m_measured), measTarg->m_measured, measTrig->m_measured);
}
*result = (measTarg->m_measured - measTrig->m_measured);
return MEASUREMENT_OK;
}
case AT_FIND:
{
@ -760,8 +841,8 @@ get_measure2(wordlist *wl)
measFind = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_find(meas, words, wlWhen, errbuf) == 0) {
measure_errMessage(mName, mFunction, "FIND", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "FIND", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
if (meas->m_at == -1 ) {
@ -774,16 +855,16 @@ get_measure2(wordlist *wl)
words = words->wl_next; // skip targ
if (measure_parse_when(measFind, words, errbuf) ==0) {
measure_errMessage(mName, mFunction, "WHEN", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "WHEN", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
com_measure_when(measFind);
if (measFind->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "WHEN", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "WHEN", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
measure_at(measFind, measFind->m_measured);
@ -795,13 +876,18 @@ get_measure2(wordlist *wl)
if (meas->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "WHEN", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "WHEN", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// print results
printf("%-20s= %e\n", mName, meas->m_measured);
return meas->m_measured;
if( out_line ){
sprintf(out_line,"%-20s= %e\n", mName, meas->m_measured);
} else {
printf("%-20s= %e\n", mName, meas->m_measured);
}
*result = meas->m_measured;
return MEASUREMENT_OK;
}
case AT_WHEN:
{
@ -809,22 +895,27 @@ get_measure2(wordlist *wl)
meas = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_when(meas, words, errbuf) ==0) {
measure_errMessage(mName, mFunction, "WHEN", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "WHEN", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
com_measure_when(meas);
if (meas->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "WHEN", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "WHEN", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// print results
printf("%-20s= %e\n", mName, meas->m_measured);
return (meas->m_measured);
if( out_line ){
sprintf(out_line,"%-20s= %.*e\n", mName, precision, meas->m_measured);
} else {
printf("%-20s= %e\n", mName, meas->m_measured);
}
*result = meas->m_measured;
return MEASUREMENT_OK;
}
case AT_RMS:
printf("\tmeasure '%s' failed\n", mName);
@ -838,8 +929,8 @@ get_measure2(wordlist *wl)
meas = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_trigtarg(meas, words , NULL, "trig", errbuf)==0) {
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// measure
@ -847,16 +938,21 @@ get_measure2(wordlist *wl)
if (meas->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf); // ??
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck); // ??
return MEASUREMENT_FAILURE;
}
if (meas->m_at == -1)
meas->m_at = 0.0e0;
// print results
printf("%-20s= %e from= %e to= %e\n", mName, meas->m_measured, meas->m_at, meas->m_measured_at);
return meas->m_measured;
if( out_line ){
sprintf(out_line,"%-20s= %e from= %e to= %e\n", mName, meas->m_measured, meas->m_at, meas->m_measured_at);
} else {
printf("%-20s= %e from= %e to= %e\n", mName, meas->m_measured, meas->m_at, meas->m_measured_at);
}
*result=meas->m_measured;
return MEASUREMENT_OK;
}
case AT_MIN:
@ -867,8 +963,8 @@ get_measure2(wordlist *wl)
measTrig = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_trigtarg(measTrig, words , NULL, "trig", errbuf)==0) {
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// measure
@ -880,32 +976,37 @@ get_measure2(wordlist *wl)
if (measTrig->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf); // ??
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck); // ??
return MEASUREMENT_FAILURE;
}
// print results
printf("%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at);
return measTrig->m_measured;
if( out_line ){
sprintf(out_line,"%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at);
} else {
printf("%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at);
}
*result=measTrig->m_measured;
return MEASUREMENT_OK;
}
case AT_PP:
{
float minValue, maxValue;
double minValue, maxValue;
measure *measTrig;
measTrig = (struct measure*)tmalloc(sizeof(struct measure));
if (measure_parse_trigtarg(measTrig, words , NULL, "trig", errbuf)==0) {
measure_errMessage(mName, mFunction, "TRIG", errbuf);
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck);
return MEASUREMENT_FAILURE;
}
// measure min
measure_minMaxAvg(measTrig, AT_MIN);
if (measTrig->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf); // ??
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck); // ??
return MEASUREMENT_FAILURE;
}
minValue = measTrig->m_measured;
@ -913,14 +1014,19 @@ get_measure2(wordlist *wl)
measure_minMaxAvg(measTrig, AT_MAX);
if (measTrig->m_measured == 0.0e0) {
sprintf(errbuf,"out of interval\n");
measure_errMessage(mName, mFunction, "TRIG", errbuf); // ??
return 0.0e0;
measure_errMessage(mName, mFunction, "TRIG", errbuf, autocheck); // ??
return MEASUREMENT_FAILURE;
}
maxValue = measTrig->m_measured;
// print results
printf("%-20s= %e from= %e to= %e\n", mName, (maxValue - minValue), measTrig->m_from, measTrig->m_to);
return (maxValue - minValue);
if( out_line ){
sprintf(out_line,"%-20s= %e from= %e to= %e\n", mName, (maxValue - minValue), measTrig->m_from, measTrig->m_to);
} else {
printf("%-20s= %e from= %e to= %e\n", mName, (maxValue - minValue), measTrig->m_from, measTrig->m_to);
}
*result = (maxValue - minValue);
return MEASUREMENT_OK;
}
case AT_INTEG:
case AT_DERIV:
@ -935,11 +1041,14 @@ get_measure2(wordlist *wl)
break;
}
}
return 0.0e0;
return MEASUREMENT_FAILURE;
}
void com_measure2(wordlist *wl) {
get_measure2(wl);
return;
}
/* I don't know where this routine is called... I want to eliminate it. */
/* void com_measure2(wordlist *wl) {
double result ;
get_measure2(wl,&result,NULL,FALSE);
return;
}
*/

5
src/frontend/com_measure2.h

@ -3,7 +3,8 @@
#include <config.h>
void com_measure2(wordlist *wl);
float get_measure2(wordlist *wl);
int get_measure_precision(void) ;
/* void com_measure2(wordlist *wl); */
int get_measure2(wordlist *wl,double *result,char *out_line, bool auto_check) ;
#endif

91
src/frontend/measure.c

@ -14,31 +14,26 @@
#include "variable.h"
#include "numparam/numpaif.h"
#include "missing_math.h"
#include "com_measure2.h"
#define EOS '\0'
#ifdef HAS_WINDOWS
void winmessage(char* new_msg);
#endif
#define OLD_WAY /* do not use functions from com_measure2.c */
#ifndef OLD_WAY
static wordlist *measure_parse_line( char *line ) ;
#endif
static bool measure_valid[20000];/* TRUE: if measurement no. [xxx] has been done successfully
(not used anywhere)*/
static bool just_chk_meas; /* TRUE: only check if measurement can be done successfully,
no output generated (if option autostop is set)*/
static bool measures_passed; /* TRUE: stop simulation (if option autostop is set)*/
/** return precision (either 5 or value of environment variable NGSPICE_MEAS_PRECISION) */
static int
get_measure_precision()
{
char *env_ptr;
int precision = 5;
if ( ( env_ptr = getenv("NGSPICE_MEAS_PRECISION") ) ) {
precision = atoi(env_ptr);
}
return precision;
}
/* returns interpolated time point (char x_or_y='x') or interpolated data value */
static double
interpolate(
@ -624,15 +619,18 @@ do_measure(
) {
struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard;
char *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000];
int mindex = 0, ok = 0;
int idx = 0, ok = 0;
int fail;
double result = 0;
bool first_time = TRUE;
wordlist *measure_word_list ;
int precision = get_measure_precision();
just_chk_meas = chk_only;
an_name = strdup( what ); /* analysis type, e.g. "tran" */
strtolower( an_name );
measure_word_list = NULL ;
/* Evaluating the linked list of .meas cards, assembled from the input deck
by fcn inp_spsource() in inp.c:575.
@ -685,8 +683,9 @@ do_measure(
continue;
}
#ifdef OLD_WAY
if ( strcmp( meastype, "trig" ) == 0 || strcmp( meastype, "delay" ) == 0 ) {
if ( do_delay_measurement( resname, out_line, line, meas_card->li_line, mindex++, &result ) && just_chk_meas != TRUE ) {
if ( do_delay_measurement( resname, out_line, line, meas_card->li_line, idx++, &result ) && just_chk_meas != TRUE ) {
nupa_add_param( resname, result );
}
}
@ -694,7 +693,7 @@ do_measure(
strcmp( meastype, "max" ) == 0 || strcmp( meastype, "min" ) == 0 ||
strcmp( meastype, "rms" ) == 0 || strcmp( meastype, "integ" ) == 0 ||
strcmp( meastype, "integral" ) == 0 || strcmp( meastype, "when" ) == 0 ) {
if ( do_other_measurement( resname, out_line, meastype, line, meas_card->li_line, mindex++, &result ) && just_chk_meas != TRUE ) {
if ( do_other_measurement( resname, out_line, meastype, line, meas_card->li_line, idx++, &result ) && just_chk_meas != TRUE ) {
nupa_add_param( resname, result );
}
}
@ -706,7 +705,20 @@ do_measure(
fprintf( cp_err, " %s\n", meas_card->li_line );
}
}
#else /* NEW_WAY */
out_line[0] = EOS ;
measure_word_list = measure_parse_line( meas_card->li_line) ;
fail = get_measure2(measure_word_list,&result,out_line,chk_only) ;
if( fail ){
measure_valid[idx++] = FALSE;
measures_passed = FALSE;
} else {
nupa_add_param( resname, result );
measure_valid[idx++] = TRUE;
}
#endif /* OLD_WAY */
newcard = alloc(struct line);
newcard->li_line = strdup(out_line);
newcard->li_next = NULL;
@ -720,7 +732,7 @@ do_measure(
txfree(an_type); txfree(resname); txfree(meastype);
// see if number of measurements exceeds fixed array size of 20,000
if ( mindex >= 20000 ) {
if ( idx >= 20000 ) {
fprintf( stderr, "ERROR: number of measurements exceeds 20,000!\nAborting...\n" );
#ifdef HAS_WINDOWS
winmessage("Fatal error in SPICE");
@ -817,3 +829,44 @@ check_autostop( char* what ) {
return flag;
}
static wordlist *measure_parse_line( char *line )
{
int len ; /* length of string */
wordlist *wl ; /* build a word list - head of list */
wordlist *new_item ; /* single item of a list */
char *item ; /* parsed item */
char *long_str ; /* concatenated string */
char *extra_item ; /* extra item */
wl = NULL ;
(void) gettok(&line) ;
do {
item = gettok(&line) ;
if(!(item)){
break ;
}
len = strlen(item) ;
if( item[len-1] == '=' ){
/* We can't end on an equal append the next piece */
extra_item = gettok(&line) ;
if(!(extra_item)){
break ;
}
len += strlen( extra_item ) + 2 ;
long_str = MALLOC(len) ;
sprintf( long_str, "%s%s", item, extra_item ) ;
txfree( item ) ;
txfree( extra_item ) ;
item = long_str ;
}
new_item = alloc(struct wordlist) ;
new_item->wl_word = item ;
new_item->wl_next = NULL ;
new_item->wl_prev = NULL ;
wl = wl_append(wl, new_item) ;
} while( line && *line ) ;
return(wl) ;
} /* end measure_parse_line() */

13
src/frontend/numparam/xpressn.c

@ -10,6 +10,10 @@
#include "numparam.h"
#include "ngspice.h"
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
/* random numbers in /maths/misc/randnumb.c */
extern double gauss();
@ -1724,8 +1728,13 @@ nupa_substitute (tdico * dico, char *s, char *r, unsigned char err)
else
{
pscopy (t, s, i + 1, k - i - 1);
err = evaluate (dico, q, t, 0);
}
/* exeption made for .meas */
if( strcasecmp(t,"LAST")==0) {
strcpy(q,"last") ;
err=0;
} else
err = evaluate (dico, q, t, 0);
}
i = k;
if (!err)

12
visualc/vngspice.vcproj

@ -767,6 +767,10 @@
RelativePath="..\src\frontend\com_let.h"
>
</File>
<File
RelativePath="..\src\frontend\com_measure2.h"
>
</File>
<File
RelativePath="..\src\frontend\com_option.h"
>
@ -1208,11 +1212,11 @@
>
</File>
<File
RelativePath="..\src\spicelib\parser\inp.h"
RelativePath="..\src\frontend\inp.h"
>
</File>
<File
RelativePath="..\src\frontend\inp.h"
RelativePath="..\src\spicelib\parser\inp.h"
>
</File>
<File
@ -4447,6 +4451,10 @@
RelativePath="..\src\frontend\com_let.c"
>
</File>
<File
RelativePath="..\src\frontend\com_measure2.c"
>
</File>
<File
RelativePath="..\src\frontend\com_option.c"
>

Loading…
Cancel
Save