116 changed files with 7202 additions and 324 deletions
-
23ChangeLog
-
1Makefile.am
-
191configure.in
-
255src/Makefile.am
-
4src/ciderlib/input/Makefile.am
-
4src/ciderlib/oned/Makefile.am
-
4src/ciderlib/support/Makefile.am
-
4src/ciderlib/twod/Makefile.am
-
6src/frontend/Makefile.am
-
940src/frontend/com_measure2.c
-
9src/frontend/com_measure2.h
-
11src/frontend/com_plot.c
-
4src/frontend/com_plot.h
-
11src/frontend/commands.c
-
17src/frontend/display.c
-
4src/frontend/help/Makefile.am
-
4src/frontend/numparam/Makefile.am
-
33src/frontend/outitf.c
-
4src/frontend/parser/Makefile.am
-
6src/frontend/plotting/Makefile.am
-
1src/frontend/plotting/graf.c
-
14src/frontend/plotting/plotit.c
-
36src/frontend/terminal.c
-
4src/frontend/wdisp/Makefile.am
-
1src/include/Makefile.am
-
15src/include/ngspice.h
-
33src/include/tclspice.h
-
54src/main.c
-
19src/maths/cmaths/Makefile.am
-
4src/maths/deriv/Makefile.am
-
4src/maths/ni/Makefile.am
-
4src/maths/poly/Makefile.am
-
4src/maths/sparse/Makefile.am
-
4src/misc/Makefile.am
-
46src/misc/alloc.c
-
122src/pkgIndex.tcl.in
-
4src/spicelib/analysis/Makefile.am
-
4src/spicelib/devices/Makefile.am
-
4src/spicelib/devices/asrc/Makefile.am
-
4src/spicelib/devices/bjt/Makefile.am
-
4src/spicelib/devices/bjt2/Makefile.am
-
4src/spicelib/devices/bsim1/Makefile.am
-
4src/spicelib/devices/bsim2/Makefile.am
-
4src/spicelib/devices/bsim3/Makefile.am
-
4src/spicelib/devices/bsim3soi/Makefile.am
-
4src/spicelib/devices/bsim3soi_dd/Makefile.am
-
4src/spicelib/devices/bsim3soi_fd/Makefile.am
-
4src/spicelib/devices/bsim3soi_pd/Makefile.am
-
4src/spicelib/devices/bsim3v0/Makefile.am
-
4src/spicelib/devices/bsim3v1/Makefile.am
-
4src/spicelib/devices/bsim3v1a/Makefile.am
-
4src/spicelib/devices/bsim3v1s/Makefile.am
-
4src/spicelib/devices/bsim3v32/Makefile.am
-
4src/spicelib/devices/bsim4/Makefile.am
-
4src/spicelib/devices/bsim4v2/Makefile.am
-
4src/spicelib/devices/bsim4v3/Makefile.am
-
4src/spicelib/devices/bsim4v4/Makefile.am
-
4src/spicelib/devices/bsim4v5/Makefile.am
-
4src/spicelib/devices/cap/Makefile.am
-
4src/spicelib/devices/cccs/Makefile.am
-
4src/spicelib/devices/ccvs/Makefile.am
-
4src/spicelib/devices/cpl/Makefile.am
-
4src/spicelib/devices/csw/Makefile.am
-
4src/spicelib/devices/dio/Makefile.am
-
4src/spicelib/devices/hfet1/Makefile.am
-
4src/spicelib/devices/hfet2/Makefile.am
-
4src/spicelib/devices/hisim/Makefile.am
-
4src/spicelib/devices/ind/Makefile.am
-
4src/spicelib/devices/isrc/Makefile.am
-
4src/spicelib/devices/jfet/Makefile.am
-
4src/spicelib/devices/jfet2/Makefile.am
-
4src/spicelib/devices/ltra/Makefile.am
-
4src/spicelib/devices/mes/Makefile.am
-
4src/spicelib/devices/mesa/Makefile.am
-
4src/spicelib/devices/mos1/Makefile.am
-
4src/spicelib/devices/mos2/Makefile.am
-
4src/spicelib/devices/mos3/Makefile.am
-
4src/spicelib/devices/mos6/Makefile.am
-
4src/spicelib/devices/mos9/Makefile.am
-
4src/spicelib/devices/nbjt/Makefile.am
-
4src/spicelib/devices/nbjt2/Makefile.am
-
4src/spicelib/devices/ndev/Makefile.am
-
4src/spicelib/devices/numd/Makefile.am
-
4src/spicelib/devices/numd2/Makefile.am
-
4src/spicelib/devices/numos/Makefile.am
-
4src/spicelib/devices/res/Makefile.am
-
4src/spicelib/devices/soi3/Makefile.am
-
4src/spicelib/devices/sw/Makefile.am
-
4src/spicelib/devices/tra/Makefile.am
-
4src/spicelib/devices/txl/Makefile.am
-
4src/spicelib/devices/urc/Makefile.am
-
4src/spicelib/devices/vbic/Makefile.am
-
4src/spicelib/devices/vccs/Makefile.am
-
4src/spicelib/devices/vcvs/Makefile.am
-
4src/spicelib/devices/vsrc/Makefile.am
-
4src/spicelib/parser/Makefile.am
-
2377src/tclspice.c
-
5src/tclspice.map
-
4src/xspice/cm/Makefile.am
-
4src/xspice/enh/Makefile.am
@ -0,0 +1,940 @@ |
|||
#include <config.h> |
|||
#include <ngspice.h> |
|||
|
|||
#include <fteext.h> |
|||
#include <wordlist.h> |
|||
|
|||
#include "vectors.h" |
|||
#include <math.h> |
|||
|
|||
typedef struct measure |
|||
{ |
|||
char *result; |
|||
|
|||
char *m_vec; // name of the output variable which determines the beginning of the measurement |
|||
char *m_vec2; |
|||
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; |
|||
|
|||
} measure; |
|||
|
|||
enum AnalysisType { |
|||
AT_DELAY, AT_TRIG, |
|||
AT_FIND, AT_WHEN, |
|||
AT_AVG, AT_MIN, AT_MAX, AT_RMS, AT_PP, |
|||
AT_INTEG, AT_DERIV, |
|||
AT_ERR, AT_ERR1, AT_ERR2, AT_ERR3 |
|||
}; |
|||
|
|||
void com_measure_when(struct measure *meas) { |
|||
|
|||
int i, first; |
|||
int riseCnt =0; |
|||
int fallCnt =0; |
|||
int crossCnt =0; |
|||
int section = -1; |
|||
float value, prevValue; |
|||
float timeValue, prevTimeValue; |
|||
|
|||
enum ValSide { S_ABOVE_VAL, S_BELOW_VAL }; |
|||
enum ValEdge { E_RISING, E_FALLING }; |
|||
|
|||
struct dvec *d, *dTime; |
|||
|
|||
d = vec_get(meas->m_vec); |
|||
dTime = plot_cur->pl_scale; |
|||
|
|||
if (d == NULL) { |
|||
fprintf(cp_err, "Error: no such vector as %s.\n", meas->m_vec); |
|||
return; |
|||
} |
|||
|
|||
if (dTime == NULL) { |
|||
fprintf(cp_err, "Error: no such vector as time.\n"); |
|||
return; |
|||
} |
|||
|
|||
prevValue =0; |
|||
prevTimeValue =0; |
|||
first =0; |
|||
|
|||
for (i=0; i < d->v_length; i++) { |
|||
|
|||
value = d->v_realdata[i]; |
|||
timeValue = dTime->v_realdata[i]; |
|||
|
|||
if (timeValue < meas->m_td) |
|||
continue; |
|||
|
|||
if (first == 1) { |
|||
// initialise |
|||
crossCnt =0; |
|||
if (value < meas->m_val) { |
|||
section = S_BELOW_VAL; |
|||
if ( (prevValue <= meas->m_val) && (value >= meas->m_val) ) { |
|||
fallCnt =1; |
|||
crossCnt =1; |
|||
} |
|||
|
|||
} else { |
|||
section = S_ABOVE_VAL; |
|||
if ( (prevValue <= meas->m_val) && (value >= meas->m_val) ) { |
|||
riseCnt =1; |
|||
crossCnt =1; |
|||
} |
|||
} |
|||
printf(""); |
|||
} |
|||
|
|||
if (first > 1) { |
|||
|
|||
if ( (section == S_BELOW_VAL) && (value >= meas->m_val) ) { |
|||
section = S_ABOVE_VAL; |
|||
crossCnt++; |
|||
riseCnt++; |
|||
|
|||
} else if ( (section == S_ABOVE_VAL) && (value <= meas->m_val) ) { |
|||
section = S_BELOW_VAL; |
|||
crossCnt++; |
|||
fallCnt++; |
|||
} |
|||
|
|||
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; |
|||
|
|||
} |
|||
} |
|||
first ++; |
|||
|
|||
prevValue = value; |
|||
prevTimeValue = timeValue; |
|||
} |
|||
|
|||
meas->m_measured = 0.0e0; |
|||
return; |
|||
} |
|||
|
|||
void measure_at(struct measure *meas, float at) { |
|||
|
|||
int i; |
|||
float value, pvalue, svalue, psvalue; |
|||
struct dvec *d, *dScale; |
|||
|
|||
psvalue = pvalue = 0; |
|||
d = vec_get(meas->m_vec); |
|||
dScale = plot_cur->pl_scale; |
|||
|
|||
if (d == NULL) { |
|||
fprintf(cp_err, "Error: no such vector as %s.\n", meas->m_vec); |
|||
return; |
|||
} |
|||
|
|||
if (dScale == NULL) { |
|||
fprintf(cp_err, "Error: no such vector time.\n"); |
|||
return; |
|||
} |
|||
|
|||
for (i=0; i < d->v_length; i++) { |
|||
value = d->v_realdata[i]; |
|||
svalue = dScale->v_realdata[i]; |
|||
|
|||
if ( (i > 0) && (psvalue <= at) && (svalue >= at) ) { |
|||
meas->m_measured = pvalue + (at - psvalue) * (value - pvalue) / (svalue - psvalue); |
|||
// meas->m_measured = value; |
|||
return; |
|||
} |
|||
|
|||
psvalue = svalue; |
|||
pvalue = value; |
|||
} |
|||
|
|||
meas->m_measured = 0.0e0; |
|||
return; |
|||
} |
|||
|
|||
void measure_avg( ) { |
|||
// AVG (Average): |
|||
// Calculates the area under the 'out_var' divided by the periods of intrest |
|||
return; |
|||
} |
|||
|
|||
void measure_minMaxAvg( struct measure *meas, int minMax ) { |
|||
|
|||
int i, avgCnt; |
|||
struct dvec *d, *dScale; |
|||
float value, svalue, mValue, mValueAt; |
|||
int first; |
|||
|
|||
mValue =0; |
|||
mValueAt = svalue =0; |
|||
meas->m_measured = 0.0e0; |
|||
meas->m_measured_at = 0.0e0; |
|||
first =0; |
|||
avgCnt =0; |
|||
|
|||
d = vec_get(meas->m_vec); |
|||
if (d == NULL) { |
|||
fprintf(cp_err, "Error: no such vector as %s.\n", meas->m_vec); |
|||
return; |
|||
} |
|||
|
|||
dScale = vec_get("time"); |
|||
if (d == NULL) { |
|||
fprintf(cp_err, "Error: no such vector as time.\n"); |
|||
return; |
|||
} |
|||
|
|||
for (i=0; i < d->v_length; i++) { |
|||
value = d->v_realdata[i]; |
|||
svalue = dScale->v_realdata[i]; |
|||
|
|||
if (svalue < meas->m_from) |
|||
continue; |
|||
|
|||
if ((meas->m_to != 0.0e0) && (svalue > meas->m_to) ) |
|||
break; |
|||
|
|||
if (first ==0) { |
|||
mValue = value; |
|||
mValueAt = svalue; |
|||
first =1; |
|||
|
|||
} else { |
|||
switch (minMax) { |
|||
case AT_MIN: { |
|||
if (value <= mValue) { |
|||
mValue = value; |
|||
mValueAt = svalue; |
|||
} |
|||
break; |
|||
} |
|||
case AT_MAX: { |
|||
if (value >= mValue) { |
|||
mValue = value; |
|||
mValueAt = svalue; |
|||
} |
|||
break; |
|||
} |
|||
case AT_AVG: |
|||
case AT_RMS: { |
|||
mValue = mValue + value; |
|||
avgCnt ++; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
switch (minMax) |
|||
{ |
|||
case AT_AVG: { |
|||
meas->m_measured = (mValue / avgCnt); |
|||
meas->m_measured_at = svalue; |
|||
break; |
|||
} |
|||
case AT_RMS: { |
|||
// printf(" mValue %e svalue %e avgCnt %i, ", mValue, svalue, avgCnt); |
|||
meas->m_measured = sqrt(mValue) / avgCnt; |
|||
meas->m_measured_at = svalue; |
|||
break; |
|||
} |
|||
case AT_MIN: |
|||
case AT_MAX: { |
|||
meas->m_measured = mValue; |
|||
meas->m_measured_at = mValueAt; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return; |
|||
} |
|||
|
|||
void measure_rms( ) { |
|||
// RMS (root mean squared): |
|||
// Calculates the square root of the area under the 'out_var2' curve |
|||
// divided be the period of interest |
|||
return; |
|||
} |
|||
|
|||
void measure_integ( ) { |
|||
// INTEGRAL INTEG |
|||
return; |
|||
} |
|||
|
|||
void measure_deriv( ) { |
|||
// DERIVATIVE DERIV |
|||
return; |
|||
} |
|||
|
|||
// ERR Equations |
|||
void measure_ERR( ) { |
|||
return; |
|||
} |
|||
|
|||
void measure_ERR1( ) { |
|||
return; |
|||
} |
|||
|
|||
void measure_ERR2( ) { |
|||
return; |
|||
} |
|||
|
|||
void measure_ERR3( ) { |
|||
return; |
|||
} |
|||
|
|||
void measure_errMessage(char *mName, char *mFunction, char *trigTarg, char *errMsg) { |
|||
|
|||
printf("\tmeasure '%s' failed\n", mName); |
|||
printf("Error: measure %s %s(%s) :\n", mName, mFunction, trigTarg); |
|||
printf("\t%s\n",errMsg); |
|||
return; |
|||
} |
|||
|
|||
void com_dotmeasure( ) { |
|||
|
|||
// simulation info |
|||
// printf("*%s\n", plot_cur->pl_title); |
|||
// printf("\t %s, %s\n", plot_cur->pl_name, plot_cur->pl_date); // missing temp |
|||
|
|||
return; |
|||
} |
|||
|
|||
int measure_valid_vector(char *vec) { |
|||
|
|||
struct dvec *d; |
|||
|
|||
d = vec_get(vec); |
|||
if (d == NULL) |
|||
return 0; |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
int measure_parse_stdParams (struct measure *meas, wordlist *wl, wordlist *wlBreak, char *errbuf) { |
|||
|
|||
int pCnt; |
|||
char *p, *pName, *pValue; |
|||
double *engVal, engVal1; |
|||
|
|||
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(strcasecmp(pName,"RISE")==0) { |
|||
meas->m_rise = engVal1; |
|||
meas->m_fall = -1; |
|||
meas->m_cross = -1; |
|||
} else if(strcasecmp(pName,"FALL")==0) { |
|||
meas->m_fall = engVal1; |
|||
meas->m_rise = -1; |
|||
meas->m_cross = -1; |
|||
} else if(strcasecmp(pName,"CROSS")==0) { |
|||
meas->m_cross = engVal1; |
|||
meas->m_rise = -1; |
|||
meas->m_fall = -1; |
|||
} else if(strcasecmp(pName,"VAL")==0) { |
|||
meas->m_val = engVal1; |
|||
} else if(strcasecmp(pName,"TD")==0) { |
|||
meas->m_td = engVal1; |
|||
} else if(strcasecmp(pName,"FROM")==0) { |
|||
meas->m_from = engVal1; |
|||
} else if(strcasecmp(pName,"TO")==0) { |
|||
meas->m_to = engVal1; |
|||
} else if(strcasecmp(pName,"AT")==0) { |
|||
meas->m_at = engVal1; |
|||
} else { |
|||
sprintf(errbuf,"no such parameter as '%s'\n",pName); |
|||
return 0; |
|||
} |
|||
|
|||
pCnt ++; |
|||
wl = wl->wl_next; |
|||
} |
|||
|
|||
if (pCnt == 0) { |
|||
sprintf(errbuf,"bad syntax of ??\n"); |
|||
return 0; |
|||
} |
|||
|
|||
// valid vector |
|||
if (measure_valid_vector(meas->m_vec)==0) { |
|||
sprintf(errbuf,"no such vector as '%s'\n", meas->m_vec); |
|||
return 0; |
|||
} |
|||
|
|||
// valid vector2 |
|||
if (meas->m_vec2 != NULL) { |
|||
if (measure_valid_vector(meas->m_vec2)==0) { |
|||
sprintf(errbuf,"no such vector as '%s'\n", meas->m_vec2); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
int measure_parse_find (struct measure *meas, wordlist *wl, wordlist *wlBreak, char *errbuf) { |
|||
|
|||
int pCnt; |
|||
char *p, *pName, *pVal; |
|||
double *engVal, engVal1; |
|||
|
|||
meas->m_vec = NULL; |
|||
meas->m_vec2 = NULL; |
|||
meas->m_val = -1; |
|||
meas->m_cross = -1; |
|||
meas->m_fall = -1; |
|||
meas->m_rise = -1; |
|||
meas->m_td = 0; |
|||
meas->m_from = 0.0e0; |
|||
meas->m_to = 0.0e0; |
|||
meas->m_at = -1; |
|||
|
|||
pCnt =0; |
|||
while(wl != wlBreak) { |
|||
p = wl->wl_word; |
|||
|
|||
if (pCnt == 0 ) { |
|||
// meas->m_vec =(char *)malloc(strlen(wl->wl_word)+1); |
|||
// strcpy(meas->m_vec, cp_unquote(wl->wl_word)); |
|||
meas->m_vec= cp_unquote(wl->wl_word); |
|||
} else if (pCnt == 1) { |
|||
|
|||
pName = strtok(p, "="); |
|||
pVal = strtok(NULL, "="); |
|||
|
|||
if (pVal == NULL) { |
|||
sprintf(errbuf,"bad syntax of WHEN\n"); |
|||
return 0; |
|||
} |
|||
|
|||
if (strcasecmp(pName,"AT")==0) { |
|||
|
|||
if (!(engVal = ft_numparse(&pVal, FALSE))) { |
|||
sprintf(errbuf,"bad syntax of WHEN\n"); |
|||
return 0; |
|||
} |
|||
|
|||
engVal1 = *engVal; |
|||
|
|||
meas->m_at = engVal1; |
|||
|
|||
} else { |
|||
sprintf(errbuf,"bad syntax of WHEN\n"); |
|||
return 0; |
|||
} |
|||
} else { |
|||
if (measure_parse_stdParams(meas, wl, NULL, errbuf) == 0) |
|||
return 0; |
|||
} |
|||
|
|||
wl = wl->wl_next; |
|||
pCnt ++; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
int measure_parse_when (struct measure *meas, wordlist *wl, char *errBuf) { |
|||
|
|||
int pCnt; |
|||
char *p, *pVar1, *pVar2; |
|||
|
|||
meas->m_vec = NULL; |
|||
meas->m_vec2 = NULL; |
|||
meas->m_val = -1; |
|||
meas->m_cross = -1; |
|||
meas->m_fall = -1; |
|||
meas->m_rise = -1; |
|||
meas->m_td = 0; |
|||
meas->m_from = 0.0e0; |
|||
meas->m_to = 0.0e0; |
|||
meas->m_at = -1; |
|||
|
|||
pCnt =0; |
|||
while (wl) { |
|||
p= wl->wl_word; |
|||
|
|||
if (pCnt == 0) { |
|||
pVar1 = strtok(p, "="); |
|||
pVar2 = strtok(NULL, "="); |
|||
|
|||
if (pVar2 == NULL) { |
|||
sprintf(errBuf,"bad syntax\n"); |
|||
return 0; |
|||
} |
|||
|
|||
meas->m_vec = pVar1; |
|||
if (measure_valid_vector(pVar2)==1) |
|||
meas->m_vec2 = pVar2; |
|||
else |
|||
meas->m_val = atof(pVar2); |
|||
} else { |
|||
if (measure_parse_stdParams(meas, wl, NULL, errBuf) == 0) |
|||
return 0; |
|||
break; |
|||
} |
|||
|
|||
wl = wl->wl_next; |
|||
pCnt ++; |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
|
|||
int measure_parse_trigtarg (struct measure *meas, wordlist *words, wordlist *wlTarg, char *trigTarg, char *errbuf) { |
|||
|
|||
int pcnt; |
|||
char *p; |
|||
|
|||
meas->m_vec = NULL; |
|||
meas->m_vec2 = NULL; |
|||
meas->m_cross = -1; |
|||
meas->m_fall = -1; |
|||
meas->m_rise = -1; |
|||
meas->m_td = 0; |
|||
meas->m_from = 0.0e0; |
|||
meas->m_to = 0.0e0; |
|||
meas->m_at = -1; |
|||
|
|||
pcnt =0; |
|||
while (words != wlTarg) { |
|||
p = words->wl_word; |
|||
|
|||
if (pcnt ==0) { |
|||
// meas->m_vec =(char *)malloc(strlen(words->wl_word)+1); |
|||
// strcpy(meas->m_vec, cp_unquote(words->wl_word)); |
|||
meas->m_vec= cp_unquote(words->wl_word); |
|||
} else { |
|||
|
|||
if (measure_parse_stdParams(meas, words, wlTarg, errbuf) == 0) |
|||
return 0; |
|||
break; |
|||
|
|||
} |
|||
|
|||
words = words->wl_next; |
|||
pcnt ++; |
|||
} |
|||
|
|||
if (pcnt == 0) { |
|||
sprintf(errbuf,"bad syntax of '%s'\n", trigTarg); |
|||
return 0; |
|||
} |
|||
|
|||
// valid vector |
|||
if (measure_valid_vector(meas->m_vec)==0) { |
|||
sprintf(errbuf,"no such vector as '%s'\n", meas->m_vec); |
|||
return 0; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
float |
|||
get_measure2(wordlist *wl) |
|||
{ |
|||
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 mFunctionType, wl_cnt; |
|||
char *p; |
|||
|
|||
mFunctionType = -1; |
|||
|
|||
if (!wl) { |
|||
printf("usage: measure .....\n"); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
if (!plot_cur || !plot_cur->pl_dvecs || !plot_cur->pl_scale) { |
|||
fprintf(cp_err, "Error: no vectors available\n"); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
if (!ciprefix("tran", plot_cur->pl_typename)) { |
|||
fprintf(cp_err, "Error: measure limited to transient analysis\n"); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
words =wl; |
|||
wlTarg = NULL; |
|||
wlWhen = NULL; |
|||
|
|||
if (!words) { |
|||
fprintf(cp_err, "Error: no assignment found.\n"); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
wl_cnt = 0; |
|||
while (words) { |
|||
|
|||
switch(wl_cnt) |
|||
{ |
|||
case 0: |
|||
mType = cp_unquote(words->wl_word); |
|||
break; |
|||
case 1: |
|||
mName = cp_unquote(words->wl_word); |
|||
break; |
|||
case 2: |
|||
{ |
|||
mFunction = cp_unquote(words->wl_word); |
|||
// Functions |
|||
if (strcasecmp(mFunction,"DELAY")==0) |
|||
mFunctionType = AT_DELAY; |
|||
else if (strcasecmp(mFunction,"TRIG")==0) |
|||
mFunctionType = AT_DELAY; |
|||
else if (strcasecmp(mFunction,"FIND")==0) |
|||
mFunctionType = AT_FIND; |
|||
else if (strcasecmp(mFunction,"WHEN")==0) |
|||
mFunctionType = AT_WHEN; |
|||
else if (strcasecmp(mFunction,"AVG")==0) |
|||
mFunctionType = AT_AVG; |
|||
else if (strcasecmp(mFunction,"MIN")==0) |
|||
mFunctionType = AT_MIN; |
|||
else if (strcasecmp(mFunction,"MAX")==0) |
|||
mFunctionType = AT_MAX; |
|||
else if (strcasecmp(mFunction,"RMS")==0) |
|||
mFunctionType = AT_RMS; |
|||
else if (strcasecmp(mFunction,"PP")==0) |
|||
mFunctionType = AT_PP; |
|||
else if (strcasecmp(mFunction,"INTEG")==0) |
|||
mFunctionType = AT_INTEG; |
|||
else if (strcasecmp(mFunction,"DERIV")==0) |
|||
mFunctionType = AT_DERIV; |
|||
else if (strcasecmp(mFunction,"ERR")==0) |
|||
mFunctionType = AT_ERR; |
|||
else if (strcasecmp(mFunction,"ERR1")==0) |
|||
mFunctionType = AT_ERR1; |
|||
else if (strcasecmp(mFunction,"ERR2") == 0) |
|||
mFunctionType = AT_ERR2; |
|||
else if (strcasecmp(mFunction,"ERR3") == 0) |
|||
mFunctionType = AT_ERR3; |
|||
else { |
|||
printf("\tmeasure '%s' failed\n", mName); |
|||
printf("Error: measure %s :\n", mName); |
|||
printf("\tno such function as '%s'\n", mFunction); |
|||
return 0.0e0; |
|||
} |
|||
break; |
|||
} |
|||
default: |
|||
{ |
|||
p = words->wl_word; |
|||
|
|||
if (strcasecmp(p,"targ")==0) |
|||
wlTarg = words; |
|||
|
|||
if (strcasecmp(p,"when")==0) |
|||
wlWhen = words; |
|||
|
|||
break; |
|||
} |
|||
} |
|||
wl_cnt ++; |
|||
words = words->wl_next; |
|||
} |
|||
|
|||
if (wl_cnt < 3) { |
|||
printf("\tmeasure '%s' failed\n", mName); |
|||
printf("Error: measure %s :\n", mName); |
|||
printf("\tinvalid num params\n"); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
//------------------------ |
|||
|
|||
|
|||
words =wl; |
|||
|
|||
if (words) |
|||
words = words->wl_next; // skip |
|||
if (words) |
|||
words = words->wl_next; // results name |
|||
if (words) |
|||
words = words->wl_next; // Function |
|||
|
|||
|
|||
// switch here |
|||
switch(mFunctionType) |
|||
{ |
|||
case AT_DELAY: |
|||
case AT_TRIG: |
|||
{ |
|||
// trig parameters |
|||
measure *measTrig, *measTarg; |
|||
measTrig = (struct measure*)malloc(sizeof(struct measure)); |
|||
measTarg = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_trigtarg(measTrig, words , wlTarg, "trig", errbuf)==0) { |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
while (words != wlTarg) |
|||
words = words->wl_next; // hack |
|||
|
|||
if (words) |
|||
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; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
// measure trig |
|||
if (measTrig->m_at == -1) |
|||
com_measure_when(measTrig); |
|||
else |
|||
measTrig->m_measured = measTrig->m_at; |
|||
|
|||
|
|||
if (measTrig->m_measured == 0.0e0) { |
|||
sprintf(errbuf,"out of interval\n"); |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
// 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; |
|||
} |
|||
|
|||
// 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); |
|||
} |
|||
case AT_FIND: |
|||
{ |
|||
measure *meas, *measFind; |
|||
meas = (struct measure*)malloc(sizeof(struct measure)); |
|||
measFind = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_find(meas, words, wlWhen, errbuf) == 0) { |
|||
measure_errMessage(mName, mFunction, "FIND", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
if (meas->m_at == -1 ) { |
|||
// find .. when statment |
|||
|
|||
while (words != wlWhen) |
|||
words = words->wl_next; // hack |
|||
|
|||
if (words) |
|||
words = words->wl_next; // skip targ |
|||
|
|||
if (measure_parse_when(measFind, words, errbuf) ==0) { |
|||
measure_errMessage(mName, mFunction, "WHEN", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
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_at(measFind, measFind->m_measured); |
|||
meas->m_measured = measFind->m_measured; |
|||
|
|||
} else { |
|||
measure_at(meas, meas->m_at); |
|||
} |
|||
|
|||
if (meas->m_measured == 0.0e0) { |
|||
sprintf(errbuf,"out of interval\n"); |
|||
measure_errMessage(mName, mFunction, "WHEN", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
// print results |
|||
printf("%-20s= %e\n", mName, meas->m_measured); |
|||
return meas->m_measured; |
|||
} |
|||
case AT_WHEN: |
|||
{ |
|||
measure *meas; |
|||
meas = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_when(meas, words, errbuf) ==0) { |
|||
measure_errMessage(mName, mFunction, "WHEN", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
// print results |
|||
printf("%-20s= %e\n", mName, meas->m_measured); |
|||
|
|||
return (meas->m_measured); |
|||
} |
|||
case AT_RMS: |
|||
printf("\tmeasure '%s' failed\n", mName); |
|||
printf("Error: measure %s :\n", mName); |
|||
printf("\tfunction '%s' currently not supported\n", mFunction); |
|||
break; |
|||
case AT_AVG: |
|||
{ |
|||
// trig parameters |
|||
measure *meas; |
|||
meas = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_trigtarg(meas, words , NULL, "trig", errbuf)==0) { |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
// measure |
|||
measure_minMaxAvg(meas, mFunctionType); |
|||
|
|||
if (meas->m_measured == 0.0e0) { |
|||
sprintf(errbuf,"out of interval\n"); |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); // ?? |
|||
return 0.0e0; |
|||
} |
|||
|
|||
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; |
|||
|
|||
} |
|||
case AT_MIN: |
|||
case AT_MAX: |
|||
{ |
|||
// trig parameters |
|||
measure *measTrig; |
|||
measTrig = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_trigtarg(measTrig, words , NULL, "trig", errbuf)==0) { |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
// measure |
|||
if (mFunctionType == AT_MIN) |
|||
measure_minMaxAvg(measTrig, AT_MIN); |
|||
else |
|||
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; |
|||
} |
|||
|
|||
// print results |
|||
printf("%-20s= %e at= %e\n", mName, measTrig->m_measured, measTrig->m_measured_at); |
|||
return measTrig->m_measured; |
|||
} |
|||
case AT_PP: |
|||
{ |
|||
float minValue, maxValue; |
|||
|
|||
measure *measTrig; |
|||
measTrig = (struct measure*)malloc(sizeof(struct measure)); |
|||
|
|||
if (measure_parse_trigtarg(measTrig, words , NULL, "trig", errbuf)==0) { |
|||
measure_errMessage(mName, mFunction, "TRIG", errbuf); |
|||
return 0.0e0; |
|||
} |
|||
|
|||
// 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; |
|||
} |
|||
minValue = measTrig->m_measured; |
|||
|
|||
// measure max |
|||
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; |
|||
} |
|||
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); |
|||
} |
|||
case AT_INTEG: |
|||
case AT_DERIV: |
|||
case AT_ERR: |
|||
case AT_ERR1: |
|||
case AT_ERR2: |
|||
case AT_ERR3: |
|||
{ |
|||
printf("\tmeasure '%s' failed\n", mName); |
|||
printf("Error: measure %s :\n", mName); |
|||
printf("\tfunction '%s' currently not supported\n", mFunction); |
|||
break; |
|||
} |
|||
} |
|||
return 0.0e0; |
|||
} |
|||
|
|||
void com_measure2(wordlist *wl) { |
|||
get_measure2(wl); |
|||
return; |
|||
} |
|||
|
|||
@ -0,0 +1,9 @@ |
|||
#ifndef _COM_MEASURE_H |
|||
#define _COM_MEASURE_H |
|||
|
|||
#include <config.h> |
|||
|
|||
void com_measure2(wordlist *wl); |
|||
float get_measure2(wordlist *wl); |
|||
|
|||
#endif |
|||
@ -0,0 +1,33 @@ |
|||
/*Include file to allow spice to export certain data */ |
|||
#ifndef TCLSPICE_H |
|||
#define TCLSPICE_H |
|||
|
|||
extern int steps_completed; |
|||
extern void blt_init(void *run); |
|||
extern void blt_add(int index,double value); |
|||
extern void blt_relink(int index, void* v); |
|||
extern void blt_lockvec(int index); |
|||
|
|||
/* For things to do per loop */ |
|||
int Tcl_ExecutePerLoop(); |
|||
|
|||
/* For tk ploting */ |
|||
extern int sp_Tk_Init(void); |
|||
#include <graph.h> |
|||
extern int sp_Tk_NewViewport(GRAPH *graph); |
|||
extern int sp_Tk_Close(void); |
|||
extern int sp_Tk_Clear(void); |
|||
extern int sp_Tk_DrawLine(int x1, int y1, int x2, int y2); |
|||
extern int sp_Tk_Arc(int x0, int y0, int radius, double theta1, double theta2); |
|||
extern int sp_Tk_Text(char *text, int x, int y); |
|||
extern int sp_Tk_DefineColor(int colorid, double red, double green, double blue); |
|||
extern int sp_Tk_DefineLinestyle(int linestyleid, int mask); |
|||
extern int sp_Tk_SetLinestyle(int linestyleid); |
|||
extern int sp_Tk_SetColor(int colorid); |
|||
extern int sp_Tk_Update(void); |
|||
|
|||
/* The blt callback method */ |
|||
#include <dvec.h> |
|||
extern int blt_plot(struct dvec *y,struct dvec *x,int new); |
|||
|
|||
#endif |
|||
@ -0,0 +1,122 @@ |
|||
|
|||
proc Loadspice { version dir } { |
|||
|
|||
package require BLT |
|||
|
|||
set suffix [info sharedlibextension] |
|||
|
|||
set library spice${suffix} |
|||
|
|||
global tcl_platform |
|||
if { $tcl_platform(platform) == "unix" } { |
|||
set library [file join $dir lib${library}] |
|||
} |
|||
load $library spice |
|||
|
|||
blt::vector create ::spice::X_Data |
|||
blt::vector create ::spice::Y_Data |
|||
|
|||
namespace eval spice { |
|||
namespace export ac help save alias sens alter altermod iplot setcirc asciiplot jobs setplot aspice setscale bg let settype linearize shell bug listing shift show cdump maxstep showmod compose newhelp noise spec cross oldhelp spice dc op spice_data define spice_header deftype plot state delete plot_datapoints status delta plot_date step plot_get_value stop diff plot_name strcmp display plot_nvars tf disto plot_title dowhile plot_variables tran dump print transpose echo pz tutorial edit quit unalias else rehash undefine end repeat unlet reset fourier reshape version spicetoblt resume where get_output rspice get_param run write goto running xgraph hardcopy rusage steps_completed blt_vnum codemodel halt loadsnap savesnap getplot |
|||
|
|||
} |
|||
|
|||
# Callback functions for the plot command |
|||
# Warning: if any of these functions return an error then |
|||
# spice will probably segfault as tcl/tk will overflow somewhere |
|||
# Note: color is actually spelt COLOUR, which looks much better |
|||
# Note: they don't work in namespace so have to make global |
|||
|
|||
proc spice_gr_NewViewport { } { |
|||
set width 1000 |
|||
set height 400 |
|||
set fontwidth 12 |
|||
set fontheight 24 |
|||
canvas .c -width $width -height $height -background white |
|||
pack .c |
|||
return "$width $height $fontwidth $fontheight" |
|||
} |
|||
proc spice_gr_Close { } { |
|||
} |
|||
proc spice_gr_Clear { } { |
|||
} |
|||
proc spice_gr_DrawLine { x1 y1 x2 y2 } { |
|||
puts "draw" |
|||
.c create line [expr $x1 + 25] [expr 375 - $y1] [expr $x2 + 25] [expr 375 - $y2] |
|||
} |
|||
proc spice_gr_Arc { x0 y0 radius theta1 theta2 } { |
|||
.c create arc [expr $x0 - $radius + 25] [expr 375 - $y0 - $radius] \ |
|||
[expr $x1 + $radius + 25 ] [expr 375 - $y1 + $radius] \ |
|||
-start $theta1 -extent $theta2 |
|||
} |
|||
proc spice_gr_Text {text x y} { |
|||
.c create text [expr $x + 25] [expr 375 - $y] -text $text |
|||
} |
|||
|
|||
proc spice_gr_SetLinestyle {linestyleid} { |
|||
puts "SetLinestyle $linestyleid" |
|||
} |
|||
proc spice_gr_SetColor {colorid } { |
|||
puts "SetColor $colorid $color" |
|||
} |
|||
|
|||
proc spice_gr_Update { } { |
|||
} |
|||
|
|||
|
|||
# These seem to never be called /* |
|||
proc spice_gr_DefineColor {colorid red green blue} { |
|||
puts "DefineColor $colorid $red $green $blue" |
|||
} |
|||
proc spice_gr_DefineLinestyle {linestyleid mask} { |
|||
puts "DefineLinestyle $linestyleid $mask" |
|||
} |
|||
|
|||
proc spice_init_gui { fileName {gui 0} {batchMode 0} {rawFileName ""}} { |
|||
|
|||
# source tclcode |
|||
if {[info procs spicewish::plot] == ""} { |
|||
source [file join $::spice_library "spice/spicewish.tcl"] |
|||
} |
|||
|
|||
if {!$batchMode} { spice::version } |
|||
|
|||
if {$fileName != ""} { |
|||
|
|||
switch [file extension $fileName] { |
|||
".tcl" { |
|||
source $fileName |
|||
} |
|||
".raw" { |
|||
spice::load $fileName |
|||
} |
|||
default { |
|||
spice::source $fileName |
|||
|
|||
if {$batchMode} { |
|||
spice::run |
|||
if {$rawFileName != ""} { |
|||
spice::set filetype=binary |
|||
spice::write $rawFileName |
|||
} |
|||
exit |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if {$gui == 1} { spicewish::gui } |
|||
wm withdraw . |
|||
} |
|||
|
|||
set ::spice_version $version |
|||
set ::spice_library $dir |
|||
} |
|||
|
|||
proc q { } { exit } |
|||
|
|||
|
|||
set version "%VERSION%" |
|||
set libdir "%LIB_DIR%" |
|||
|
|||
package ifneeded spice $version [list Loadspice $version $libdir] |
|||
|
|||
2377
src/tclspice.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,5 @@ |
|||
TCLSPICE_0.2 |
|||
{ |
|||
global: Spice_Init; |
|||
local: *; |
|||
}; |
|||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue