This commit is contained in:
parent
789091b928
commit
8dc8bb950b
25
ChangeLog
25
ChangeLog
|
|
@ -1,3 +1,28 @@
|
|||
2004-08-10 Adrian Dawe <adrian.dawe@multigig.com>
|
||||
|
||||
* src/measure.tcl
|
||||
src/nodeDialog.tcl
|
||||
src/pkgIndex.tcl.in
|
||||
src/spicepp.pl.in
|
||||
src/spicewish
|
||||
src/spicewish.tcl
|
||||
src/tclspice.c
|
||||
src/viewer.tcl
|
||||
src/frontend/Makefile.am
|
||||
src/frontend/com_measure.c
|
||||
src/frontend/com_measure.h
|
||||
src/frontend/commands.c
|
||||
src/include/cktdefs.h
|
||||
src/spicelib/devices/Makefile.am
|
||||
src/spicelib/devices/cktcrte.c
|
||||
src/spicelib/devices/cktfinddev.c
|
||||
src/spicelib/devices/cktinit.c
|
||||
src/spicelib/devices/names.c
|
||||
src/spicelib/devices/names.h:
|
||||
Added hash table for circuit elements
|
||||
Update TCL gui
|
||||
Added measure command
|
||||
|
||||
2004-08-04 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* src/tclspice.c:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ libfte_a_SOURCES = \
|
|||
com_dl.h \
|
||||
com_plot.c \
|
||||
com_plot.h \
|
||||
com_measure.c \
|
||||
com_measure.h \
|
||||
com_rehash.c \
|
||||
com_set.c \
|
||||
com_set.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,943 @@
|
|||
#include <config.h>
|
||||
#include <ngspice.h>
|
||||
|
||||
#include <fteext.h>
|
||||
#include <wordlist.h>
|
||||
|
||||
#include "vectors.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef TCL_MODULE
|
||||
|
||||
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_measure(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_measure(wordlist *wl) {
|
||||
get_measure(wl);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _COM_MEASURE_H
|
||||
#define _COM_MEASURE_H
|
||||
|
||||
#include <config.h>
|
||||
#ifdef TCL_MODULE
|
||||
void com_measure(wordlist *wl);
|
||||
float get_measure(wordlist *wl);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -48,6 +48,7 @@
|
|||
#include "com_setscale.h"
|
||||
#include "com_xgraph.h"
|
||||
#include "com_state.h"
|
||||
#include "com_measure.h"
|
||||
#include "fourier.h"
|
||||
|
||||
#ifdef EXPERIMENTAL_CODE
|
||||
|
|
@ -116,6 +117,10 @@ struct comm spcp_coms[] = {
|
|||
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
||||
arg_plot,
|
||||
"expr ... [vs expr] [xl xlo xhi] [yl ylo yhi] : Plot things." },
|
||||
{ "measure", com_measure, FALSE, FALSE, TRUE,
|
||||
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
||||
arg_plot,
|
||||
"measure..." },
|
||||
{ "plot", com_bltplot, FALSE, FALSE, TRUE,
|
||||
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
||||
arg_plot,
|
||||
|
|
|
|||
|
|
@ -258,6 +258,10 @@ typedef struct {
|
|||
#endif
|
||||
/* gtri - evt - wbk - 5/20/91 - add event-driven and enhancements data */
|
||||
|
||||
|
||||
void *element_lookup_table; /* names_t * maps strings to pointers to GENELEMENTS */
|
||||
|
||||
|
||||
} CKTcircuit;
|
||||
|
||||
/* Now function prottypes */
|
||||
|
|
|
|||
|
|
@ -313,5 +313,89 @@ namespace eval meas_markers {
|
|||
bind $w <Key-F2> { spicewish::meas_markers::riseTime %W.g %x %y }
|
||||
bind $w <Key-F3> { spicewish::meas_markers::propDelay %W.g %x %y}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace eval motionMeasure {
|
||||
|
||||
variable measInfo
|
||||
|
||||
proc create { graph } {
|
||||
eval "bind $graph <ButtonPress-1> { [namespace current]::SetMeasPoint %W %x %y }"
|
||||
eval "bind $graph <ButtonRelease-1> { [namespace current]::removeMarker %W }"
|
||||
}
|
||||
|
||||
proc InitVars { graph } {
|
||||
variable measInfo
|
||||
set measInfo($graph,A,x) {}
|
||||
set measInfo($graph,A,y) {}
|
||||
set measInfo($graph,B,x) {}
|
||||
set measInfo($graph,B,y) {}
|
||||
set measInfo($graph,corner) A
|
||||
}
|
||||
|
||||
proc removeMarker { graph } {
|
||||
variable measInfo
|
||||
bind $graph <Motion> {}
|
||||
$graph marker delete "zoomOutlineV"
|
||||
$graph marker delete "zoomOutlineH"
|
||||
}
|
||||
|
||||
proc SetMeasPoint { graph x y } {
|
||||
variable measInfo
|
||||
|
||||
if { ![info exists measInfo($graph,corner)] } {
|
||||
InitVars $graph
|
||||
}
|
||||
GetCoords $graph $x $y $measInfo($graph,corner)
|
||||
|
||||
eval "bind $graph <Motion> { [namespace current]::GetCoords %W %x %y B; [namespace current]::Box %W }"
|
||||
}
|
||||
|
||||
proc GetCoords { graph x y index } {
|
||||
variable measInfo
|
||||
if { [$graph cget -invertxy] } {
|
||||
set measInfo($graph,$index,x) $y
|
||||
set measInfo($graph,$index,y) $x
|
||||
|
||||
} else {
|
||||
set measInfo($graph,$index,x) $x
|
||||
set measInfo($graph,$index,y) $y
|
||||
}
|
||||
}
|
||||
|
||||
proc Box { graph } {
|
||||
variable measInfo
|
||||
if { $measInfo($graph,A,x) > $measInfo($graph,B,x) } {
|
||||
set x1 [$graph xaxis invtransform $measInfo($graph,B,x)]
|
||||
set y1 [$graph yaxis invtransform $measInfo($graph,B,y)]
|
||||
set x2 [$graph xaxis invtransform $measInfo($graph,A,x)]
|
||||
set y2 [$graph yaxis invtransform $measInfo($graph,A,y)]
|
||||
} else {
|
||||
set x1 [$graph xaxis invtransform $measInfo($graph,A,x)]
|
||||
set y1 [$graph yaxis invtransform $measInfo($graph,A,y)]
|
||||
set x2 [$graph xaxis invtransform $measInfo($graph,B,x)]
|
||||
set y2 [$graph yaxis invtransform $measInfo($graph,B,y)]
|
||||
}
|
||||
set coords { $x1 $y1 $x2 $y1 $x2 $y2 $x1 $y2 $x1 $y1 }
|
||||
if { [$graph marker exists "zoomOutlineV"] } {
|
||||
$graph marker configure "zoomOutlineV" -coords "$x1 $y1 $x1 $y2"
|
||||
$graph marker configure "zoomOutlineH" -coords "$x1 $y2 $x2 $y2"
|
||||
} else {
|
||||
set X [lindex [$graph xaxis use] 0]
|
||||
set Y [lindex [$graph yaxis use] 0]
|
||||
|
||||
$graph marker create line -coords "$x1 $y1 $x1 $y2" -name "zoomOutlineV" -linewidth 2
|
||||
$graph marker create line -coords "$x1 $y2 $x2 $y2" -name "zoomOutlineH" -linewidth 2
|
||||
}
|
||||
|
||||
set ::spicewish::viewer::meas_x1($graph) $x1
|
||||
set ::spicewish::viewer::meas_y1($graph) $y1
|
||||
set ::spicewish::viewer::meas_x2($graph) $x2
|
||||
set ::spicewish::viewer::meas_y2($graph) $y2
|
||||
set ::spicewish::viewer::meas_dx($graph) [expr $x2 - $x1]
|
||||
set ::spicewish::viewer::meas_dy($graph) [expr $y2 - $y1]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace eval nodeDialog {
|
|||
variable selection
|
||||
variable selected "const"
|
||||
variable selectionCnt
|
||||
variable vecFilter ""
|
||||
|
||||
proc create { } {
|
||||
variable w
|
||||
|
|
@ -21,7 +22,6 @@ namespace eval nodeDialog {
|
|||
wm title $w "Vectors"
|
||||
|
||||
# Plot names
|
||||
#pack [frame $w.plots] -fill x
|
||||
frame $w.plots
|
||||
pack [listbox $w.plots.lst -height 4 \
|
||||
-width 50 \
|
||||
|
|
@ -34,7 +34,6 @@ namespace eval nodeDialog {
|
|||
] -fill y -side right
|
||||
|
||||
# vector names
|
||||
#pack [frame $w.nodes] -fill both -expand 1
|
||||
frame $w.nodes
|
||||
pack [blt::hierbox $w.nodes.hb -hideroot 1 \
|
||||
-yscrollcommand {.nodeSelect.nodes.sx set} \
|
||||
|
|
@ -46,8 +45,14 @@ namespace eval nodeDialog {
|
|||
-command {.nodeSelect.nodes.hb yview} \
|
||||
] -fill y -side right
|
||||
|
||||
# vector Filter
|
||||
frame $w.filter
|
||||
pack [label $w.filter.l -text "Filter:"] -side left
|
||||
pack [entry $w.filter.e \
|
||||
-textvariable spicewish::nodeDialog::vecFilter \
|
||||
] -side left -expand 1 -fill x
|
||||
|
||||
# control frame
|
||||
#pack [frame $w.fcont] -fill x
|
||||
frame $w.fcont
|
||||
pack [label $w.fcont.lselected -text "Selected: "] -side left
|
||||
pack [button $w.fcont.bNodeCnt -textvariable spicewish::nodeDialog::selectionCnt \
|
||||
|
|
@ -62,9 +67,10 @@ namespace eval nodeDialog {
|
|||
blt::table $w \
|
||||
0,0 $w.plots -fill x \
|
||||
1,0 $w.nodes -fill both \
|
||||
2,0 $w.fcont -fill x
|
||||
2,0 $w.filter -fill x\
|
||||
3,0 $w.fcont -fill x
|
||||
|
||||
blt::table configure $w r0 r2 -resize none
|
||||
blt::table configure $w r0 r2 r3 -resize none
|
||||
|
||||
# bindings
|
||||
$w.nodes.hb bind all <Button-1> {
|
||||
|
|
@ -72,7 +78,7 @@ namespace eval nodeDialog {
|
|||
set index [$hierbox_path index current]
|
||||
set nodeName [$hierbox_path entry cget $index -label]
|
||||
set plotTypeName [spice::plot_typename [.nodeSelect.plots.lst curselection]]
|
||||
set listPos [lsearch $::spicewish::nodeDialog::selection($plotTypeName) $nodeName]
|
||||
set listPos [lsearch $::spicewish::nodeDialog::selection($plotTypeName) [spicewish::viewer::evaluate $nodeName]]
|
||||
|
||||
if { [ $hierbox_path entry cget $index -labelcolor] == "black"} {
|
||||
$hierbox_path entry configure $index -labelcolor "blue"
|
||||
|
|
@ -85,9 +91,7 @@ namespace eval nodeDialog {
|
|||
$hierbox_path entry configure $index -labelcolor "black"
|
||||
$hierbox_path configure -selectforeground black
|
||||
|
||||
set spicewish::nodeDialog::selection($plotTypeName) [lreplace $::spicewish::nodeDialog::selection($plotTypeName) $listPos $listPos]
|
||||
|
||||
|
||||
set spicewish::nodeDialog::selection($plotTypeName) [lreplace $::spicewish::nodeDialog::selection($plotTypeName) $listPos $listPos]
|
||||
}
|
||||
set spicewish::nodeDialog::selectionCnt [llength $::spicewish::nodeDialog::selection($plotTypeName)]
|
||||
}
|
||||
|
|
@ -100,6 +104,7 @@ namespace eval nodeDialog {
|
|||
bind $w.nodes.hb <Button-5> [list %W yview scroll 5 units]
|
||||
bind $w.nodes.hb <Button-4> [list %W yview scroll -5 units]
|
||||
|
||||
bind $w.filter.e <KeyPress-Return> { spicewish::nodeDialog::Update }
|
||||
wm protocol $w WM_TAKE_FOCUS { spicewish::nodeDialog::Update }
|
||||
|
||||
Update
|
||||
|
|
@ -112,7 +117,6 @@ namespace eval nodeDialog {
|
|||
set plotTypeName [spice::plot_typename $plotNum]
|
||||
|
||||
if {$selection($plotTypeName) == ""} {return}
|
||||
|
||||
eval "spicewish::viewer::oplot $plotTypeName $selection($plotTypeName)"
|
||||
}
|
||||
|
||||
|
|
@ -190,19 +194,32 @@ namespace eval nodeDialog {
|
|||
|
||||
proc populateTree { index } {
|
||||
|
||||
variable vecFilter
|
||||
|
||||
set w ".nodeSelect.nodes.hb"
|
||||
$w delete 0
|
||||
|
||||
set defaultScale [spice::plot_defaultscale $index]
|
||||
|
||||
foreach node [spice::plot_variables $index] {
|
||||
set text ": [spicewish::vectors::type $index $node], real, [spice::plot_datapoints $index]"
|
||||
if {$node == $defaultScale} {
|
||||
set data [spice::plot_variablesInfo $index]
|
||||
set data [lsort -dictionary $data]
|
||||
|
||||
for {set i 0} {$i < [llength $data]} {incr i} {
|
||||
set v_data [lindex $data $i]
|
||||
set v_name [lindex $v_data 0]
|
||||
set v_type [lindex $v_data 1]
|
||||
set v_length [lindex $v_data 2]
|
||||
|
||||
if {(![string match $vecFilter $v_name]) && ($vecFilter != "")} { continue }
|
||||
|
||||
set text ": $v_type, real, $v_length"
|
||||
if {$v_name == $defaultScale} {
|
||||
set text "$text \[default scale\]"
|
||||
}
|
||||
|
||||
$w insert -at 0 end $node -labelfont {times 9} -text $text -labelcolor "black"
|
||||
$w insert -at 0 end $v_name -labelfont {times 9} -text $text -labelcolor "black"
|
||||
}
|
||||
|
||||
loadSelection
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ proc Loadspice { version dir } {
|
|||
puts "DefineLinestyle $linestyleid $mask"
|
||||
}
|
||||
|
||||
proc spice_init_gui { fileName {gui 0} {batchMode 0}} {
|
||||
proc spice_init_gui { fileName {gui 0} {batchMode 0} {rawFileName ""}} {
|
||||
|
||||
# source tclcode
|
||||
if {[info procs spicewish::plot] == ""} {
|
||||
|
|
@ -94,8 +94,11 @@ proc Loadspice { version dir } {
|
|||
spice::source $fileName
|
||||
|
||||
if {$batchMode} {
|
||||
spice::run
|
||||
spice::write out.raw
|
||||
spice::run
|
||||
if {$rawFileName != ""} {
|
||||
spice::set filetype=binary
|
||||
spice::write $rawFileName
|
||||
}
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ libdev_a_SOURCES = \
|
|||
cktbindnode.c \
|
||||
cktcrte.c \
|
||||
cktfinddev.c \
|
||||
cktinit.c
|
||||
cktinit.c \
|
||||
names.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ Author: 1985 Thomas L. Quarles
|
|||
#include <config.h>
|
||||
#include <devdefs.h>
|
||||
#include <sperror.h>
|
||||
|
||||
#include <cktdefs.h>
|
||||
#include "dev.h"
|
||||
#include "names.h"
|
||||
|
||||
int
|
||||
CKTcrtElt(void *ckt, void *inModPtr, void **inInstPtr, IFuid name)
|
||||
|
|
@ -60,5 +61,11 @@ CKTcrtElt(void *ckt, void *inModPtr, void **inInstPtr, IFuid name)
|
|||
if(inInstPtr != NULL)
|
||||
*inInstPtr = (void *)instPtr;
|
||||
|
||||
|
||||
{
|
||||
names_t *np= ((CKTcircuit *)ckt)->element_lookup_table;
|
||||
names_add(np,instPtr,(char*)(name));
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Author: 1985 Thomas L. Quarles
|
|||
#include <config.h>
|
||||
#include <cktdefs.h>
|
||||
#include <sperror.h>
|
||||
|
||||
#include "names.h"
|
||||
|
||||
int
|
||||
CKTfndDev(void *Ckt, int *type, void **fast, IFuid name, void *modfast, IFuid modname)
|
||||
|
|
@ -24,6 +24,30 @@ CKTfndDev(void *Ckt, int *type, void **fast, IFuid name, void *modfast, IFuid mo
|
|||
return(OK);
|
||||
}
|
||||
|
||||
/* LOG(N) lookup code: Conrad Ziesler */
|
||||
{
|
||||
GENinstance *p;
|
||||
names_t *np= ((CKTcircuit *)Ckt)->element_lookup_table;
|
||||
p= names_check(np,(char*)(name));
|
||||
if(p!=NULL)
|
||||
{
|
||||
if (modname == (char *)NULL || p->GENmodPtr->GENmodName == modname) {
|
||||
|
||||
if (p->GENname == name) {
|
||||
if (fast != 0)
|
||||
*(GENinstance **)fast = p;
|
||||
if(modfast) if (type)
|
||||
*type = p->GENmodPtr->GENmodType;
|
||||
return OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return E_NODEV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(modfast) {
|
||||
/* have model, just need device */
|
||||
mods = (GENmodel*)modfast;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Modifed: 2000 AlansFixes
|
|||
#include <fteext.h>
|
||||
#include <ifsim.h>
|
||||
#include <dev.h>
|
||||
#include "names.h"
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 11/26/90 - add include for MIF global data */
|
||||
|
|
@ -31,6 +32,7 @@ CKTinit(void **ckt) /* new circuit to create */
|
|||
sckt = (CKTcircuit *)(*ckt);
|
||||
if (sckt == NULL)
|
||||
return(E_NOMEM);
|
||||
sckt->element_lookup_table=names_new();
|
||||
/* gtri - begin - dynamically allocate the array of model lists */
|
||||
/* CKThead used to be statically sized in CKTdefs.h, but has been changed */
|
||||
/* to a ** pointer */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
/********************
|
||||
This file is part of the software library CADLIB written by Conrad Ziesler
|
||||
Copyright 2003, Conrad Ziesler, all rights reserved.
|
||||
|
||||
*************************
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
******************/
|
||||
/* names.c, efficient string table support
|
||||
Conrad Ziesler
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define __NAMES_PRIVATE__
|
||||
#include "names.h"
|
||||
|
||||
static namehash_t *names_newhash(names_t *nt, void * refp, const char *str)
|
||||
{
|
||||
namehash_t *b;
|
||||
int q=strlen(str);
|
||||
b=malloc(sizeof(namehash_t)+q);
|
||||
assert(b!=NULL);
|
||||
b->refp=refp;
|
||||
b->magic=NAME_MAGIC;
|
||||
strcpy(b->str,str);
|
||||
nt->bytesalloc+=sizeof(namehash_t)+q;
|
||||
nt->namebytes+=q;
|
||||
nt->qtynames++;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int names_ptrhash(names_t *nt, void * refp)
|
||||
{
|
||||
unsigned q=nt->qtybins;
|
||||
unsigned int v, r=0;
|
||||
|
||||
v=(unsigned)refp;
|
||||
/*
|
||||
v>>=2;
|
||||
r= ((v%(7*q+(q/3)+5))^v) % q;
|
||||
*/
|
||||
r= v ^ (v>>3) ^ ((v/3)>>15) ^ ((~v)>>11);
|
||||
return r%q;
|
||||
}
|
||||
|
||||
static unsigned int names_strhash(names_t *nt, const char *str)
|
||||
{
|
||||
unsigned q=nt->qtybins;
|
||||
unsigned int r=0;
|
||||
|
||||
while(*str!=0)
|
||||
{
|
||||
r+= (str[0]^(r%q));
|
||||
r%=q;
|
||||
str++;
|
||||
}
|
||||
|
||||
return r%q;
|
||||
}
|
||||
|
||||
|
||||
char *names_lookup(names_t *nt, void * refp)
|
||||
{
|
||||
unsigned int id;
|
||||
namehash_t *nh;
|
||||
int i=0;
|
||||
|
||||
id=names_ptrhash(nt,refp);
|
||||
|
||||
for(nh=nt->cref[id];nh!=NULL;nh=nh->cref,i++)
|
||||
{
|
||||
assert(nh->magic==NAME_MAGIC);
|
||||
if(refp==nh->refp){ return nh->str; }
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * names_check(names_t *nt, const char *name)
|
||||
{
|
||||
unsigned int id;
|
||||
namehash_t *nh;
|
||||
int i=0;
|
||||
|
||||
id=names_strhash(nt,name);
|
||||
|
||||
for(nh=nt->cstr[id];nh!=NULL;nh=nh->cstr,i++)
|
||||
{
|
||||
assert(nh->magic==NAME_MAGIC);
|
||||
if(strcmp(name,nh->str)==0){ return nh->refp; }
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void names_add(names_t *nt, void * refp, const char *name)
|
||||
{
|
||||
unsigned int idn,idr,id;
|
||||
namehash_t *nh,*nhref=NULL,*nhstr=NULL;
|
||||
int i=0;
|
||||
|
||||
if(nt->qtynames>((5*nt->qtybins)/4)) /* double table size each time we outgrow old table */
|
||||
names_rehash(nt, (2*nt->qtynames) );
|
||||
|
||||
idn=names_strhash(nt,name);
|
||||
idr=names_ptrhash(nt,refp);
|
||||
|
||||
for(nh=nt->cref[idr];nh!=NULL;nh=nh->cref,i++)
|
||||
{
|
||||
assert(nh->magic==NAME_MAGIC);
|
||||
if(refp==nh->refp){ nt->avg_refl=(nt->avg_refl+i)/2; nhref=nh; break; }
|
||||
}
|
||||
|
||||
for(nh=nt->cstr[idn];nh!=NULL;nh=nh->cstr,i++)
|
||||
{
|
||||
assert(nh->magic==NAME_MAGIC);
|
||||
if(strcmp(name,nh->str)==0){ nt->avg_strl=(nt->avg_strl+i)/2; nhstr=nh; break; }
|
||||
}
|
||||
|
||||
if(nhstr==NULL) /* adding new name entry */
|
||||
{
|
||||
if(nhref!=NULL) /* but refp was the same */
|
||||
{
|
||||
fprintf(stderr,"**** DUPLICATE KEY NAME ****\n");
|
||||
if(1)assert(0&&"duplicate key in names");
|
||||
}
|
||||
|
||||
nh=names_newhash(nt, refp, name);
|
||||
nh->cstr=nt->cstr[idn];
|
||||
nt->cstr[idn]=nh;
|
||||
nh->cref=nt->cref[idr];
|
||||
nt->cref[idr]=nh;
|
||||
}
|
||||
else /* replacing old name entry */
|
||||
{
|
||||
namehash_t *prev=NULL;
|
||||
assert(0 && "Replacing strings in names has a bug. do not use");
|
||||
/* lookup refp of old name and unlink */
|
||||
id=names_ptrhash(nt,nhstr->refp);
|
||||
for(nh=nt->cref[id];nh!=NULL;prev=nh,nh=nh->cref,i++)
|
||||
if(nhstr->refp==nh->refp)
|
||||
{
|
||||
if(prev==NULL)nt->cref[id]=nh->cref;
|
||||
else prev->cref=nh->cref;
|
||||
break;
|
||||
}
|
||||
/* relink new name, refp */
|
||||
nhstr->refp=refp;
|
||||
nhstr->cref=nt->cref[idr];
|
||||
nt->cref[idr]=nhstr;
|
||||
}
|
||||
}
|
||||
|
||||
char * names_stats(names_t *nt)
|
||||
{
|
||||
static char buf[1024];
|
||||
int i,qs=0,qp=0,ms=0,mp=0,j,ks=0,kp=0;
|
||||
namehash_t *nh;
|
||||
|
||||
for(i=0;i<nt->qtybins;i++)
|
||||
{
|
||||
|
||||
for(j=0,nh=nt->cstr[i];nh!=NULL;nh=nh->cstr,j++) assert(nh->magic==NAME_MAGIC);
|
||||
if(j>0)ks++;
|
||||
if(ms<j)ms=j;
|
||||
qs+=j;
|
||||
for(j=0,nh=nt->cref[i];nh!=NULL;nh=nh->cref,j++) assert(nh->magic==NAME_MAGIC);
|
||||
if(mp<j)mp=j;
|
||||
if(j>0)kp++;
|
||||
qp+=j;
|
||||
}
|
||||
|
||||
qp/=kp;
|
||||
qs/=ks;
|
||||
|
||||
sprintf(buf,"names: %i bins (%i totaling %i) , alloc %i, avg: %i %i max: %i %i",nt->qtybins,nt->qtynames,nt->namebytes,nt->bytesalloc,qp,qs,mp,ms);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* this should optimize our hash table for memory usage */
|
||||
void names_rehash(names_t *nt, int newbins)
|
||||
{
|
||||
int i;
|
||||
int oldqty;
|
||||
namehash_t *hp;
|
||||
|
||||
oldqty=nt->qtybins;
|
||||
nt->qtybins=newbins;
|
||||
|
||||
nt->bytesalloc+= ( (newbins-oldqty)*sizeof(void *)*2 );
|
||||
/* do cref first, using cstr */
|
||||
if(nt->cref!=NULL)
|
||||
free(nt->cref);
|
||||
nt->cref=malloc(sizeof(void *)*(nt->qtybins+1));
|
||||
assert(nt->cref!=NULL);
|
||||
memset(nt->cref,0,sizeof(void*)*nt->qtybins);
|
||||
|
||||
/* iterate through list of string hashes, adding to ref hashes */
|
||||
for(i=0;i<oldqty;i++)
|
||||
for(hp=nt->cstr[i];hp!=NULL;hp=hp->cstr)
|
||||
{
|
||||
unsigned id;
|
||||
id=names_ptrhash(nt,hp->refp);
|
||||
hp->cref=nt->cref[id];
|
||||
nt->cref[id]=hp;
|
||||
}
|
||||
|
||||
/* next do cstr, using new cref */
|
||||
if(nt->cstr!=NULL)
|
||||
free(nt->cstr);
|
||||
nt->cstr=malloc(sizeof(void *)*(nt->qtybins+1));
|
||||
assert(nt->cstr!=NULL);
|
||||
memset(nt->cstr,0,sizeof(void*)*nt->qtybins);
|
||||
|
||||
for(i=0;i<nt->qtybins;i++)
|
||||
for(hp=nt->cref[i];hp!=NULL;hp=hp->cref)
|
||||
{
|
||||
unsigned id;
|
||||
id=names_strhash(nt,hp->str);
|
||||
hp->cstr=nt->cstr[id];
|
||||
nt->cstr[id]=hp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
names_t *names_new(void)
|
||||
{
|
||||
names_t *p;
|
||||
p=malloc(sizeof(names_t));
|
||||
assert(p!=NULL);
|
||||
memset(p,0,sizeof(names_t));
|
||||
p->bytesalloc=sizeof(names_t);
|
||||
p->namebytes=0;
|
||||
p->qtynames=0;
|
||||
p->avg_strl=0;
|
||||
p->avg_refl=0;
|
||||
|
||||
p->qtybins=0;
|
||||
p->cstr=NULL;
|
||||
p->cref=NULL;
|
||||
names_rehash(p,13); /* start small, grow bigger */
|
||||
return p;
|
||||
}
|
||||
|
||||
void names_free(names_t *nt)
|
||||
{
|
||||
int i;
|
||||
namehash_t *nh,*next;
|
||||
if(nt!=NULL)
|
||||
{
|
||||
for(i=0;i<nt->qtybins;i++)
|
||||
{
|
||||
for(nh=nt->cstr[i];nh!=NULL;nh=next)
|
||||
{
|
||||
assert(nh->magic==NAME_MAGIC);
|
||||
next=nh->cstr;
|
||||
free(nh);
|
||||
}
|
||||
}
|
||||
free(nt->cstr);
|
||||
free(nt->cref);
|
||||
free(nt);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/********************
|
||||
This file is part of the software library CADLIB written by Conrad Ziesler
|
||||
Copyright 2003, Conrad Ziesler, all rights reserved.
|
||||
|
||||
*************************
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
******************/
|
||||
/* names.h, definitions for name storage
|
||||
Conrad Ziesler
|
||||
*/
|
||||
|
||||
#ifndef __NAMES_H__
|
||||
#define __NAMES_H__
|
||||
#ifdef __NAMES_PRIVATE__
|
||||
|
||||
#define NAME_MAGIC 0x52a01250
|
||||
typedef struct name_hash_st
|
||||
{
|
||||
int magic;
|
||||
struct name_hash_st *cref,*cstr;
|
||||
void * refp;
|
||||
char str[1];
|
||||
}namehash_t;
|
||||
|
||||
typedef struct names_st
|
||||
{
|
||||
namehash_t **cref,**cstr;
|
||||
int avg_refl;
|
||||
int avg_strl;
|
||||
int qtybins;
|
||||
int qtynames;
|
||||
int namebytes;
|
||||
int bytesalloc;
|
||||
}names_t;
|
||||
#else
|
||||
|
||||
struct names_st;
|
||||
typedef struct names_st names_t;
|
||||
#endif
|
||||
|
||||
char *names_stats(names_t *nt);
|
||||
char *names_lookup(names_t *nt, void * refp);
|
||||
void * names_check(names_t *nt, const char *name);
|
||||
void names_add(names_t *nt, void * refp, const char *name);
|
||||
names_t *names_new(void);
|
||||
void names_free(names_t *nt);
|
||||
void names_rehash(names_t *nt, int newbins); /* private-ish */
|
||||
|
||||
#endif
|
||||
|
|
@ -639,7 +639,7 @@ sub change_models {
|
|||
|
||||
|
||||
sub change_instances {
|
||||
local($i,$model,$l,$w,$p,$ad,$as,$pd,$ps);
|
||||
local($i,$model,$l,$w,$p,$m,$ad,$as,$pd,$ps);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_ = $deck[$i];
|
||||
if(/^m\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/) {
|
||||
|
|
@ -677,6 +677,10 @@ sub change_instances {
|
|||
next;
|
||||
model_found:
|
||||
#W & L mangling and acm stuff
|
||||
#Get m
|
||||
if($deck[$i] =~ s/(.*)\bm\s*=\s*([0-9]+)\b(.*)/$1$3/){
|
||||
$m = $2;}else {$m = 1;}
|
||||
|
||||
#get and remove pd, ps, ad, as
|
||||
if($deck[$i] =~ s/(.*)\bpd\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||
$pd = &unit($2);
|
||||
|
|
@ -699,7 +703,7 @@ sub change_instances {
|
|||
}else{ $ad = 0;}
|
||||
|
||||
#Calculate Leff and Weff
|
||||
$w = ($w * $$model{"wmlt"} + $$model{"xw"});
|
||||
$w = $m * ($w * $$model{"wmlt"} + $$model{"xw"});
|
||||
$l = $l * $$model{"lmlt"} + $$model{"xl"};
|
||||
|
||||
#Now do the ACM stuff......
|
||||
|
|
@ -709,10 +713,10 @@ sub change_instances {
|
|||
#calculated using hspice methods..
|
||||
if( $$model{"acm"} == 0){
|
||||
#pg 869, 19-33
|
||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$pd = $pd * $$model{"wmlt"};
|
||||
$ps = $ps * $$model{"wmlt"};
|
||||
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$pd = $m * $pd * $$model{"wmlt"};
|
||||
$ps = $m * $ps * $$model{"wmlt"};
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -725,23 +729,23 @@ sub change_instances {
|
|||
elsif( $$model{"acm"} == 2){
|
||||
#pg 874, 19-39
|
||||
if($ad){
|
||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$ad = $ad * $m * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else {
|
||||
$ad = 2 * $$model{"hdif"} * $w;}
|
||||
|
||||
if($as){
|
||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else{
|
||||
$as = 2 * $$model{"hdif"} * $w;}
|
||||
|
||||
if($pd){
|
||||
$pd = $pd * $$model{"wmlt"};
|
||||
$pd = $m * $pd * $$model{"wmlt"};
|
||||
}else {
|
||||
$pd = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
|
||||
if($ps){
|
||||
$ps = $ps * $$model{"wmlt"};
|
||||
$ps = $m * $ps * $$model{"wmlt"};
|
||||
}else{
|
||||
$ps = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
|
|
@ -750,7 +754,7 @@ sub change_instances {
|
|||
elsif( $$model{"acm"} == 3){
|
||||
#pg 879, 19-43
|
||||
if($ad){
|
||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||
$ad = 2 * $$model{"hdif"} * $w;
|
||||
}else{
|
||||
|
|
@ -758,7 +762,7 @@ sub change_instances {
|
|||
}
|
||||
|
||||
if($as){
|
||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||
$as = 2 * $$model{"hdif"} * $w;
|
||||
}else{
|
||||
|
|
@ -766,7 +770,7 @@ sub change_instances {
|
|||
}
|
||||
|
||||
if($pd){
|
||||
$pd = $pd * $$model{"wmlt"};}
|
||||
$pd = $m * $pd * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||
$pd = 4 * $$model{"hdif"} + $w;
|
||||
}else{
|
||||
|
|
@ -774,7 +778,7 @@ sub change_instances {
|
|||
}
|
||||
|
||||
if($ps){
|
||||
$ps = $ps * $$model{"wmlt"};}
|
||||
$ps = $m * $ps * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||
$ps = 4 * $$model{"hdif"} + $w;
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#
|
||||
#!/bin/sh
|
||||
# 22/6/04 -ad
|
||||
|
||||
# the next line starts SpiceWish interactively with the given file name \
|
||||
exec wish "$0" "$@"
|
||||
exec wish "$0" "$@"
|
||||
|
||||
package require spice
|
||||
package require tclreadline
|
||||
|
|
@ -41,6 +41,7 @@ proc run_spicepp { fileName } {
|
|||
|
||||
proc spicewish_load { argv argc } {
|
||||
set fileName ""
|
||||
set rawFileName ""
|
||||
set mode_batch 0
|
||||
set mode_spicePP 0
|
||||
|
||||
|
|
@ -57,7 +58,8 @@ proc spicewish_load { argv argc } {
|
|||
break
|
||||
}
|
||||
-h - -help { spicewish_usage }
|
||||
-b { set ::mode_batch 1 }
|
||||
-b { set mode_batch 1 }
|
||||
-r { set rawFileName $val; incr i}
|
||||
-version { spice::version; exit }
|
||||
-pp { set mode_spicePP 1 }
|
||||
default { spicewish_usage }
|
||||
|
|
@ -68,7 +70,7 @@ proc spicewish_load { argv argc } {
|
|||
}
|
||||
|
||||
if {$fileName == "" } {
|
||||
spice_init_gui "" 0 $mode_batch
|
||||
spice_init_gui "" 0 $mode_batch $rawFileName
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +80,7 @@ proc spicewish_load { argv argc } {
|
|||
set fileName [ run_spicepp $fileName ]
|
||||
}
|
||||
|
||||
spice_init_gui $fileName 0 $mode_batch
|
||||
spice_init_gui $fileName 0 $mode_batch $rawFileName
|
||||
}
|
||||
|
||||
proc Tclreadline { } {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,13 @@ namespace eval spicewish {
|
|||
spicewish::nodeDialog::create
|
||||
return
|
||||
}
|
||||
eval spicewish::viewer::plot $args
|
||||
|
||||
set l ""
|
||||
foreach p $args {
|
||||
set l "$l\\\"[spicewish::viewer::evaluate $p]\\\" "
|
||||
}
|
||||
#eval spice::bltplot $l
|
||||
eval spice::bltplot $args
|
||||
}
|
||||
|
||||
proc gui { } {
|
||||
|
|
@ -106,7 +112,7 @@ proc spice_gr_Plot { args } {
|
|||
set yType [lindex $args 4]
|
||||
set yUnits [lindex $args 5]
|
||||
set viewerCnt [lindex $args 6]
|
||||
|
||||
|
||||
set plotNum [spicewish::vectors::get_plotNum [spice::getplot]]
|
||||
|
||||
if {$spicewish::viewer::vecUpdate_flag} {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ typedef pthread_t threadId_t;
|
|||
#include <frontend/outitf.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <frontend/com_measure.h>
|
||||
|
||||
#ifndef HAVE_GETRUSAGE
|
||||
#ifdef HAVE_FTIME
|
||||
|
|
@ -667,6 +668,39 @@ static int plot_variables TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
|||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int plot_variablesInfo TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
||||
|
||||
struct plot *pl;
|
||||
int plot;
|
||||
struct dvec *v;
|
||||
char buf[256];
|
||||
char *name;
|
||||
int length;
|
||||
|
||||
if (argc != 2) {
|
||||
Tcl_SetResult(interp, "Wrong # args. spice::plot_variablesInfo plot",TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
plot = atoi(argv[1]);
|
||||
|
||||
if(!(pl = get_plot(plot))){
|
||||
Tcl_SetResult(interp,"Bad plot given",TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
for(v = pl->pl_dvecs;v;v = v->v_next){
|
||||
name = v->v_name;
|
||||
length = v->v_length;
|
||||
|
||||
sprintf(buf,"{%s %s %i} ",name, ft_typenames(v->v_type), length);
|
||||
Tcl_AppendResult(interp, (char *)buf, TCL_STATIC);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*returns the value of a variable */
|
||||
static int plot_get_value TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
||||
|
|
@ -1947,6 +1981,29 @@ static int listTriggers TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
|||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int tmeasure TCL_CMDPROCARGS(clientData,interp,argc,argv){
|
||||
|
||||
wordlist *wl= NULL;
|
||||
float mvalue;
|
||||
|
||||
if (argc <= 2) {
|
||||
Tcl_SetResult(interp, "Wrong # args. spice::listTriggers",TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
wl =wl_build(argv);
|
||||
|
||||
mvalue = get_measure(wl);
|
||||
|
||||
printf(" %e \n", mvalue);
|
||||
|
||||
Tcl_ResetResult(spice_interp);
|
||||
|
||||
Tcl_SetObjResult(interp,Tcl_NewDoubleObj((double) mvalue));
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************/
|
||||
/* Initialise spice and setup native methods */
|
||||
|
|
@ -2080,6 +2137,7 @@ bot:
|
|||
Tcl_CreateCommand(interp, TCLSPICE_prefix "delta", delta, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "maxstep", maxstep, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_variables", plot_variables, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_variablesInfo", plot_variablesInfo, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_get_value", plot_get_value, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_datapoints", plot_datapoints, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_title", plot_title, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
|
|
@ -2104,6 +2162,8 @@ bot:
|
|||
Tcl_CreateCommand(interp, TCLSPICE_prefix "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
#endif
|
||||
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "tmeasure", tmeasure, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
|
||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "registerStepCallback", registerStepCallback, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||
|
||||
Tcl_LinkVar(interp, TCLSPICE_prefix "steps_completed", (char *)&steps_completed, TCL_LINK_READ_ONLY|TCL_LINK_INT);
|
||||
|
|
|
|||
|
|
@ -56,8 +56,14 @@ namespace eval viewer {
|
|||
blt::table configure $w r0 r2 c0 c2 r3 -resize none
|
||||
|
||||
# graph settings
|
||||
Blt_ZoomStack $w.g
|
||||
Blt_Crosshairs $w.g
|
||||
Blt_Crosshairs $w.g
|
||||
if {0} {
|
||||
Blt_ZoomStack $w.g
|
||||
} else {
|
||||
blt::ZoomStack $w.g "ButtonPress-3" "ButtonPress-2"
|
||||
blt::ZoomStack $w.g "ButtonPress-3" "Shift-ButtonPress-3"
|
||||
}
|
||||
|
||||
$w.g grid on
|
||||
$w.g axis configure x -command { spicewish::viewer::axis_callback } -subdivisions 2
|
||||
|
||||
|
|
@ -68,6 +74,8 @@ namespace eval viewer {
|
|||
|
||||
eval "wm protocol $w WM_DELETE_WINDOW {spicewish::viewer::Destroy $w}"
|
||||
|
||||
bind $w <KeyPress-u> { spicewish::viewer::Update }
|
||||
|
||||
incr viewCnt
|
||||
return [expr $viewCnt -1]
|
||||
}
|
||||
|
|
@ -120,17 +128,25 @@ namespace eval viewer {
|
|||
pack [ label $w_meas.x1 -text "x1 :" -background "grey" ] -side right
|
||||
bind $w_meas.x1v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "x1 : $::spicewish::viewer::meas_x1($w.g)"}
|
||||
|
||||
# cursor motion bindings
|
||||
bind $w.g <Motion> {
|
||||
if { $::zoomInfo(%W,B,x) != "" } {
|
||||
set ::spicewish::viewer::meas_x2(%W) [%W xaxis invtransform $::zoomInfo(%W,B,x)]
|
||||
set ::spicewish::viewer::meas_y2(%W) [%W yaxis invtransform $::zoomInfo(%W,B,y)]
|
||||
set ::spicewish::viewer::meas_x1(%W) [%W xaxis invtransform $::zoomInfo(%W,A,x)]
|
||||
set ::spicewish::viewer::meas_y1(%W) [%W yaxis invtransform $::zoomInfo(%W,A,y)]
|
||||
set ::spicewish::viewer::meas_dx(%W) [expr ($::spicewish::viewer::meas_x2(%W) - $::spicewish::viewer::meas_x1(%W))]
|
||||
set ::spicewish::viewer::meas_dy(%W) [expr ($::spicewish::viewer::meas_y2(%W) - $::spicewish::viewer::meas_y1(%W))]
|
||||
}
|
||||
}
|
||||
if {1} {
|
||||
catch {::spicewish::motionMeasure::create $w.g}
|
||||
|
||||
} else {
|
||||
|
||||
# cursor motion bindings
|
||||
bind $w.g <Motion> {
|
||||
if { $::zoomInfo(%W,B,x) != "" } {
|
||||
set ::spicewish::viewer::meas_x2(%W) [%W xaxis invtransform $::zoomInfo(%W,B,x)]
|
||||
set ::spicewish::viewer::meas_y2(%W) [%W yaxis invtransform $::zoomInfo(%W,B,y)]
|
||||
set ::spicewish::viewer::meas_x1(%W) [%W xaxis invtransform $::zoomInfo(%W,A,x)]
|
||||
set ::spicewish::viewer::meas_y1(%W) [%W yaxis invtransform $::zoomInfo(%W,A,y)]
|
||||
set ::spicewish::viewer::meas_dx(%W) [expr ($::spicewish::viewer::meas_x2(%W) - $::spicewish::viewer::meas_x1(%W))]
|
||||
set ::spicewish::viewer::meas_dy(%W) [expr ($::spicewish::viewer::meas_y2(%W) - $::spicewish::viewer::meas_y1(%W))]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
proc names { } {
|
||||
|
|
@ -142,7 +158,6 @@ namespace eval viewer {
|
|||
proc plot { args } {
|
||||
|
||||
if {$args == ""} {return}
|
||||
|
||||
spice::bltplot $args
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +169,11 @@ namespace eval viewer {
|
|||
|
||||
spice::setplot $plotTypeName
|
||||
|
||||
spice::bltplot $args
|
||||
set l ""
|
||||
foreach p $args {
|
||||
set l "$l\\\"[spicewish::viewer::evaluate $p]\\\" "
|
||||
}
|
||||
eval spice::bltplot $l
|
||||
|
||||
spice::setplot $currentPlotType
|
||||
}
|
||||
|
|
@ -353,7 +372,7 @@ namespace eval viewer {
|
|||
spice::setplot $view_plotName($index)
|
||||
|
||||
::spice::X_Data set ""
|
||||
spice::bltplot $trace
|
||||
spice::bltplot [evaluate $trace]
|
||||
|
||||
eval $\{::$view_plotName($index):v:$trace\} set \"::spice::Y_Data\"
|
||||
|
||||
|
|
@ -378,6 +397,25 @@ namespace eval viewer {
|
|||
|
||||
destroy $w
|
||||
}
|
||||
|
||||
proc evaluate { list } {
|
||||
|
||||
foreach char "\[ \]" {
|
||||
set repList ""
|
||||
for {set i 0} {$i < [string length $list]} {incr i} {
|
||||
if {[string range $list $i $i] == $char} {
|
||||
lappend repList $i
|
||||
}
|
||||
}
|
||||
set cnt 0
|
||||
foreach index $repList {
|
||||
set list [string replace $list [expr $index + $cnt] [expr $index + $cnt] "\\$char"]
|
||||
incr cnt
|
||||
}
|
||||
}
|
||||
|
||||
return $list
|
||||
}
|
||||
}
|
||||
|
||||
namespace eval vectors {
|
||||
|
|
@ -396,7 +434,7 @@ namespace eval vectors {
|
|||
return $name
|
||||
} else {
|
||||
::spice::Y_Data set ""
|
||||
uplevel #0 ::spice::bltplot $name
|
||||
uplevel #0 ::spice::bltplot [spicewish::viewer::evaluate $name]
|
||||
|
||||
if {[::spice::Y_Data length] != 0} {
|
||||
return $name
|
||||
|
|
|
|||
Loading…
Reference in New Issue