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>
|
2004-08-04 Stefan Jones <stefan.jones@multigig.com>
|
||||||
|
|
||||||
* src/tclspice.c:
|
* src/tclspice.c:
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ libfte_a_SOURCES = \
|
||||||
com_dl.h \
|
com_dl.h \
|
||||||
com_plot.c \
|
com_plot.c \
|
||||||
com_plot.h \
|
com_plot.h \
|
||||||
|
com_measure.c \
|
||||||
|
com_measure.h \
|
||||||
com_rehash.c \
|
com_rehash.c \
|
||||||
com_set.c \
|
com_set.c \
|
||||||
com_set.h \
|
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_setscale.h"
|
||||||
#include "com_xgraph.h"
|
#include "com_xgraph.h"
|
||||||
#include "com_state.h"
|
#include "com_state.h"
|
||||||
|
#include "com_measure.h"
|
||||||
#include "fourier.h"
|
#include "fourier.h"
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_CODE
|
#ifdef EXPERIMENTAL_CODE
|
||||||
|
|
@ -116,6 +117,10 @@ struct comm spcp_coms[] = {
|
||||||
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
||||||
arg_plot,
|
arg_plot,
|
||||||
"expr ... [vs expr] [xl xlo xhi] [yl ylo yhi] : Plot things." },
|
"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,
|
{ "plot", com_bltplot, FALSE, FALSE, TRUE,
|
||||||
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
{ 041000, 041000, 041000, 041000 }, E_BEGINNING | E_HASPLOTS, 1, LOTS,
|
||||||
arg_plot,
|
arg_plot,
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,10 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
/* gtri - evt - wbk - 5/20/91 - add event-driven and enhancements data */
|
/* 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;
|
} CKTcircuit;
|
||||||
|
|
||||||
/* Now function prottypes */
|
/* 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-F2> { spicewish::meas_markers::riseTime %W.g %x %y }
|
||||||
bind $w <Key-F3> { spicewish::meas_markers::propDelay %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 selection
|
||||||
variable selected "const"
|
variable selected "const"
|
||||||
variable selectionCnt
|
variable selectionCnt
|
||||||
|
variable vecFilter ""
|
||||||
|
|
||||||
proc create { } {
|
proc create { } {
|
||||||
variable w
|
variable w
|
||||||
|
|
@ -21,7 +22,6 @@ namespace eval nodeDialog {
|
||||||
wm title $w "Vectors"
|
wm title $w "Vectors"
|
||||||
|
|
||||||
# Plot names
|
# Plot names
|
||||||
#pack [frame $w.plots] -fill x
|
|
||||||
frame $w.plots
|
frame $w.plots
|
||||||
pack [listbox $w.plots.lst -height 4 \
|
pack [listbox $w.plots.lst -height 4 \
|
||||||
-width 50 \
|
-width 50 \
|
||||||
|
|
@ -34,7 +34,6 @@ namespace eval nodeDialog {
|
||||||
] -fill y -side right
|
] -fill y -side right
|
||||||
|
|
||||||
# vector names
|
# vector names
|
||||||
#pack [frame $w.nodes] -fill both -expand 1
|
|
||||||
frame $w.nodes
|
frame $w.nodes
|
||||||
pack [blt::hierbox $w.nodes.hb -hideroot 1 \
|
pack [blt::hierbox $w.nodes.hb -hideroot 1 \
|
||||||
-yscrollcommand {.nodeSelect.nodes.sx set} \
|
-yscrollcommand {.nodeSelect.nodes.sx set} \
|
||||||
|
|
@ -46,8 +45,14 @@ namespace eval nodeDialog {
|
||||||
-command {.nodeSelect.nodes.hb yview} \
|
-command {.nodeSelect.nodes.hb yview} \
|
||||||
] -fill y -side right
|
] -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
|
# control frame
|
||||||
#pack [frame $w.fcont] -fill x
|
|
||||||
frame $w.fcont
|
frame $w.fcont
|
||||||
pack [label $w.fcont.lselected -text "Selected: "] -side left
|
pack [label $w.fcont.lselected -text "Selected: "] -side left
|
||||||
pack [button $w.fcont.bNodeCnt -textvariable spicewish::nodeDialog::selectionCnt \
|
pack [button $w.fcont.bNodeCnt -textvariable spicewish::nodeDialog::selectionCnt \
|
||||||
|
|
@ -62,9 +67,10 @@ namespace eval nodeDialog {
|
||||||
blt::table $w \
|
blt::table $w \
|
||||||
0,0 $w.plots -fill x \
|
0,0 $w.plots -fill x \
|
||||||
1,0 $w.nodes -fill both \
|
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
|
# bindings
|
||||||
$w.nodes.hb bind all <Button-1> {
|
$w.nodes.hb bind all <Button-1> {
|
||||||
|
|
@ -72,7 +78,7 @@ namespace eval nodeDialog {
|
||||||
set index [$hierbox_path index current]
|
set index [$hierbox_path index current]
|
||||||
set nodeName [$hierbox_path entry cget $index -label]
|
set nodeName [$hierbox_path entry cget $index -label]
|
||||||
set plotTypeName [spice::plot_typename [.nodeSelect.plots.lst curselection]]
|
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"} {
|
if { [ $hierbox_path entry cget $index -labelcolor] == "black"} {
|
||||||
$hierbox_path entry configure $index -labelcolor "blue"
|
$hierbox_path entry configure $index -labelcolor "blue"
|
||||||
|
|
@ -85,9 +91,7 @@ namespace eval nodeDialog {
|
||||||
$hierbox_path entry configure $index -labelcolor "black"
|
$hierbox_path entry configure $index -labelcolor "black"
|
||||||
$hierbox_path configure -selectforeground 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)]
|
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-5> [list %W yview scroll 5 units]
|
||||||
bind $w.nodes.hb <Button-4> [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 }
|
wm protocol $w WM_TAKE_FOCUS { spicewish::nodeDialog::Update }
|
||||||
|
|
||||||
Update
|
Update
|
||||||
|
|
@ -112,7 +117,6 @@ namespace eval nodeDialog {
|
||||||
set plotTypeName [spice::plot_typename $plotNum]
|
set plotTypeName [spice::plot_typename $plotNum]
|
||||||
|
|
||||||
if {$selection($plotTypeName) == ""} {return}
|
if {$selection($plotTypeName) == ""} {return}
|
||||||
|
|
||||||
eval "spicewish::viewer::oplot $plotTypeName $selection($plotTypeName)"
|
eval "spicewish::viewer::oplot $plotTypeName $selection($plotTypeName)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,19 +194,32 @@ namespace eval nodeDialog {
|
||||||
|
|
||||||
proc populateTree { index } {
|
proc populateTree { index } {
|
||||||
|
|
||||||
|
variable vecFilter
|
||||||
|
|
||||||
set w ".nodeSelect.nodes.hb"
|
set w ".nodeSelect.nodes.hb"
|
||||||
$w delete 0
|
$w delete 0
|
||||||
|
|
||||||
set defaultScale [spice::plot_defaultscale $index]
|
set defaultScale [spice::plot_defaultscale $index]
|
||||||
|
|
||||||
foreach node [spice::plot_variables $index] {
|
set data [spice::plot_variablesInfo $index]
|
||||||
set text ": [spicewish::vectors::type $index $node], real, [spice::plot_datapoints $index]"
|
set data [lsort -dictionary $data]
|
||||||
if {$node == $defaultScale} {
|
|
||||||
|
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\]"
|
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
|
loadSelection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ proc Loadspice { version dir } {
|
||||||
puts "DefineLinestyle $linestyleid $mask"
|
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
|
# source tclcode
|
||||||
if {[info procs spicewish::plot] == ""} {
|
if {[info procs spicewish::plot] == ""} {
|
||||||
|
|
@ -94,8 +94,11 @@ proc Loadspice { version dir } {
|
||||||
spice::source $fileName
|
spice::source $fileName
|
||||||
|
|
||||||
if {$batchMode} {
|
if {$batchMode} {
|
||||||
spice::run
|
spice::run
|
||||||
spice::write out.raw
|
if {$rawFileName != ""} {
|
||||||
|
spice::set filetype=binary
|
||||||
|
spice::write $rawFileName
|
||||||
|
}
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,8 @@ libdev_a_SOURCES = \
|
||||||
cktbindnode.c \
|
cktbindnode.c \
|
||||||
cktcrte.c \
|
cktcrte.c \
|
||||||
cktfinddev.c \
|
cktfinddev.c \
|
||||||
cktinit.c
|
cktinit.c \
|
||||||
|
names.c
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
|
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 <config.h>
|
||||||
#include <devdefs.h>
|
#include <devdefs.h>
|
||||||
#include <sperror.h>
|
#include <sperror.h>
|
||||||
|
#include <cktdefs.h>
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "names.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
CKTcrtElt(void *ckt, void *inModPtr, void **inInstPtr, IFuid name)
|
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)
|
if(inInstPtr != NULL)
|
||||||
*inInstPtr = (void *)instPtr;
|
*inInstPtr = (void *)instPtr;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
names_t *np= ((CKTcircuit *)ckt)->element_lookup_table;
|
||||||
|
names_add(np,instPtr,(char*)(name));
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Author: 1985 Thomas L. Quarles
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <cktdefs.h>
|
#include <cktdefs.h>
|
||||||
#include <sperror.h>
|
#include <sperror.h>
|
||||||
|
#include "names.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
CKTfndDev(void *Ckt, int *type, void **fast, IFuid name, void *modfast, IFuid modname)
|
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);
|
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) {
|
if(modfast) {
|
||||||
/* have model, just need device */
|
/* have model, just need device */
|
||||||
mods = (GENmodel*)modfast;
|
mods = (GENmodel*)modfast;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ Modifed: 2000 AlansFixes
|
||||||
#include <fteext.h>
|
#include <fteext.h>
|
||||||
#include <ifsim.h>
|
#include <ifsim.h>
|
||||||
#include <dev.h>
|
#include <dev.h>
|
||||||
|
#include "names.h"
|
||||||
|
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
/* gtri - add - wbk - 11/26/90 - add include for MIF global data */
|
/* 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);
|
sckt = (CKTcircuit *)(*ckt);
|
||||||
if (sckt == NULL)
|
if (sckt == NULL)
|
||||||
return(E_NOMEM);
|
return(E_NOMEM);
|
||||||
|
sckt->element_lookup_table=names_new();
|
||||||
/* gtri - begin - dynamically allocate the array of model lists */
|
/* gtri - begin - dynamically allocate the array of model lists */
|
||||||
/* CKThead used to be statically sized in CKTdefs.h, but has been changed */
|
/* CKThead used to be statically sized in CKTdefs.h, but has been changed */
|
||||||
/* to a ** pointer */
|
/* 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 {
|
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++) {
|
for ($i=0;$i<@deck;$i++) {
|
||||||
$_ = $deck[$i];
|
$_ = $deck[$i];
|
||||||
if(/^m\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/) {
|
if(/^m\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/) {
|
||||||
|
|
@ -677,6 +677,10 @@ sub change_instances {
|
||||||
next;
|
next;
|
||||||
model_found:
|
model_found:
|
||||||
#W & L mangling and acm stuff
|
#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
|
#get and remove pd, ps, ad, as
|
||||||
if($deck[$i] =~ s/(.*)\bpd\s*=\s*(\S+)\b(.*)/$1$3/){
|
if($deck[$i] =~ s/(.*)\bpd\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||||
$pd = &unit($2);
|
$pd = &unit($2);
|
||||||
|
|
@ -699,7 +703,7 @@ sub change_instances {
|
||||||
}else{ $ad = 0;}
|
}else{ $ad = 0;}
|
||||||
|
|
||||||
#Calculate Leff and Weff
|
#Calculate Leff and Weff
|
||||||
$w = ($w * $$model{"wmlt"} + $$model{"xw"});
|
$w = $m * ($w * $$model{"wmlt"} + $$model{"xw"});
|
||||||
$l = $l * $$model{"lmlt"} + $$model{"xl"};
|
$l = $l * $$model{"lmlt"} + $$model{"xl"};
|
||||||
|
|
||||||
#Now do the ACM stuff......
|
#Now do the ACM stuff......
|
||||||
|
|
@ -709,10 +713,10 @@ sub change_instances {
|
||||||
#calculated using hspice methods..
|
#calculated using hspice methods..
|
||||||
if( $$model{"acm"} == 0){
|
if( $$model{"acm"} == 0){
|
||||||
#pg 869, 19-33
|
#pg 869, 19-33
|
||||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};
|
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||||
$pd = $pd * $$model{"wmlt"};
|
$pd = $m * $pd * $$model{"wmlt"};
|
||||||
$ps = $ps * $$model{"wmlt"};
|
$ps = $m * $ps * $$model{"wmlt"};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,23 +729,23 @@ sub change_instances {
|
||||||
elsif( $$model{"acm"} == 2){
|
elsif( $$model{"acm"} == 2){
|
||||||
#pg 874, 19-39
|
#pg 874, 19-39
|
||||||
if($ad){
|
if($ad){
|
||||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
$ad = $ad * $m * $$model{"wmlt"} * $$model{"wmlt"};
|
||||||
}else {
|
}else {
|
||||||
$ad = 2 * $$model{"hdif"} * $w;}
|
$ad = 2 * $$model{"hdif"} * $w;}
|
||||||
|
|
||||||
if($as){
|
if($as){
|
||||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};
|
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||||
}else{
|
}else{
|
||||||
$as = 2 * $$model{"hdif"} * $w;}
|
$as = 2 * $$model{"hdif"} * $w;}
|
||||||
|
|
||||||
if($pd){
|
if($pd){
|
||||||
$pd = $pd * $$model{"wmlt"};
|
$pd = $m * $pd * $$model{"wmlt"};
|
||||||
}else {
|
}else {
|
||||||
$pd = 4 * $$model{"hdif"} + 2 * $w;
|
$pd = 4 * $$model{"hdif"} + 2 * $w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ps){
|
if($ps){
|
||||||
$ps = $ps * $$model{"wmlt"};
|
$ps = $m * $ps * $$model{"wmlt"};
|
||||||
}else{
|
}else{
|
||||||
$ps = 4 * $$model{"hdif"} + 2 * $w;
|
$ps = 4 * $$model{"hdif"} + 2 * $w;
|
||||||
}
|
}
|
||||||
|
|
@ -750,7 +754,7 @@ sub change_instances {
|
||||||
elsif( $$model{"acm"} == 3){
|
elsif( $$model{"acm"} == 3){
|
||||||
#pg 879, 19-43
|
#pg 879, 19-43
|
||||||
if($ad){
|
if($ad){
|
||||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};}
|
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||||
$ad = 2 * $$model{"hdif"} * $w;
|
$ad = 2 * $$model{"hdif"} * $w;
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -758,7 +762,7 @@ sub change_instances {
|
||||||
}
|
}
|
||||||
|
|
||||||
if($as){
|
if($as){
|
||||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};}
|
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||||
$as = 2 * $$model{"hdif"} * $w;
|
$as = 2 * $$model{"hdif"} * $w;
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -766,7 +770,7 @@ sub change_instances {
|
||||||
}
|
}
|
||||||
|
|
||||||
if($pd){
|
if($pd){
|
||||||
$pd = $pd * $$model{"wmlt"};}
|
$pd = $m * $pd * $$model{"wmlt"};}
|
||||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||||
$pd = 4 * $$model{"hdif"} + $w;
|
$pd = 4 * $$model{"hdif"} + $w;
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -774,7 +778,7 @@ sub change_instances {
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ps){
|
if($ps){
|
||||||
$ps = $ps * $$model{"wmlt"};}
|
$ps = $m * $ps * $$model{"wmlt"};}
|
||||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||||
$ps = 4 * $$model{"hdif"} + $w;
|
$ps = 4 * $$model{"hdif"} + $w;
|
||||||
}else{
|
}else{
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#
|
#!/bin/sh
|
||||||
# 22/6/04 -ad
|
# 22/6/04 -ad
|
||||||
|
|
||||||
# the next line starts SpiceWish interactively with the given file name \
|
# the next line starts SpiceWish interactively with the given file name \
|
||||||
exec wish "$0" "$@"
|
exec wish "$0" "$@"
|
||||||
|
|
||||||
package require spice
|
package require spice
|
||||||
package require tclreadline
|
package require tclreadline
|
||||||
|
|
@ -41,6 +41,7 @@ proc run_spicepp { fileName } {
|
||||||
|
|
||||||
proc spicewish_load { argv argc } {
|
proc spicewish_load { argv argc } {
|
||||||
set fileName ""
|
set fileName ""
|
||||||
|
set rawFileName ""
|
||||||
set mode_batch 0
|
set mode_batch 0
|
||||||
set mode_spicePP 0
|
set mode_spicePP 0
|
||||||
|
|
||||||
|
|
@ -57,7 +58,8 @@ proc spicewish_load { argv argc } {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
-h - -help { spicewish_usage }
|
-h - -help { spicewish_usage }
|
||||||
-b { set ::mode_batch 1 }
|
-b { set mode_batch 1 }
|
||||||
|
-r { set rawFileName $val; incr i}
|
||||||
-version { spice::version; exit }
|
-version { spice::version; exit }
|
||||||
-pp { set mode_spicePP 1 }
|
-pp { set mode_spicePP 1 }
|
||||||
default { spicewish_usage }
|
default { spicewish_usage }
|
||||||
|
|
@ -68,7 +70,7 @@ proc spicewish_load { argv argc } {
|
||||||
}
|
}
|
||||||
|
|
||||||
if {$fileName == "" } {
|
if {$fileName == "" } {
|
||||||
spice_init_gui "" 0 $mode_batch
|
spice_init_gui "" 0 $mode_batch $rawFileName
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +80,7 @@ proc spicewish_load { argv argc } {
|
||||||
set fileName [ run_spicepp $fileName ]
|
set fileName [ run_spicepp $fileName ]
|
||||||
}
|
}
|
||||||
|
|
||||||
spice_init_gui $fileName 0 $mode_batch
|
spice_init_gui $fileName 0 $mode_batch $rawFileName
|
||||||
}
|
}
|
||||||
|
|
||||||
proc Tclreadline { } {
|
proc Tclreadline { } {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,13 @@ namespace eval spicewish {
|
||||||
spicewish::nodeDialog::create
|
spicewish::nodeDialog::create
|
||||||
return
|
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 { } {
|
proc gui { } {
|
||||||
|
|
@ -106,7 +112,7 @@ proc spice_gr_Plot { args } {
|
||||||
set yType [lindex $args 4]
|
set yType [lindex $args 4]
|
||||||
set yUnits [lindex $args 5]
|
set yUnits [lindex $args 5]
|
||||||
set viewerCnt [lindex $args 6]
|
set viewerCnt [lindex $args 6]
|
||||||
|
|
||||||
set plotNum [spicewish::vectors::get_plotNum [spice::getplot]]
|
set plotNum [spicewish::vectors::get_plotNum [spice::getplot]]
|
||||||
|
|
||||||
if {$spicewish::viewer::vecUpdate_flag} {
|
if {$spicewish::viewer::vecUpdate_flag} {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ typedef pthread_t threadId_t;
|
||||||
#include <frontend/outitf.h>
|
#include <frontend/outitf.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
|
#include <frontend/com_measure.h>
|
||||||
|
|
||||||
#ifndef HAVE_GETRUSAGE
|
#ifndef HAVE_GETRUSAGE
|
||||||
#ifdef HAVE_FTIME
|
#ifdef HAVE_FTIME
|
||||||
|
|
@ -667,6 +668,39 @@ static int plot_variables TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
||||||
}
|
}
|
||||||
return TCL_OK;
|
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 */
|
/*returns the value of a variable */
|
||||||
static int plot_get_value TCL_CMDPROCARGS(clientData,interp,argc,argv) {
|
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;
|
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 */
|
/* 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 "delta", delta, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "maxstep", maxstep, (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_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_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_datapoints", plot_datapoints, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||||
Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_title", plot_title, (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);
|
Tcl_CreateCommand(interp, TCLSPICE_prefix "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
|
||||||
#endif
|
#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_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);
|
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
|
blt::table configure $w r0 r2 c0 c2 r3 -resize none
|
||||||
|
|
||||||
# graph settings
|
# 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 grid on
|
||||||
$w.g axis configure x -command { spicewish::viewer::axis_callback } -subdivisions 2
|
$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}"
|
eval "wm protocol $w WM_DELETE_WINDOW {spicewish::viewer::Destroy $w}"
|
||||||
|
|
||||||
|
bind $w <KeyPress-u> { spicewish::viewer::Update }
|
||||||
|
|
||||||
incr viewCnt
|
incr viewCnt
|
||||||
return [expr $viewCnt -1]
|
return [expr $viewCnt -1]
|
||||||
}
|
}
|
||||||
|
|
@ -120,17 +128,25 @@ namespace eval viewer {
|
||||||
pack [ label $w_meas.x1 -text "x1 :" -background "grey" ] -side right
|
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)"}
|
bind $w_meas.x1v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "x1 : $::spicewish::viewer::meas_x1($w.g)"}
|
||||||
|
|
||||||
# cursor motion bindings
|
if {1} {
|
||||||
bind $w.g <Motion> {
|
catch {::spicewish::motionMeasure::create $w.g}
|
||||||
if { $::zoomInfo(%W,B,x) != "" } {
|
|
||||||
set ::spicewish::viewer::meas_x2(%W) [%W xaxis invtransform $::zoomInfo(%W,B,x)]
|
} else {
|
||||||
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)]
|
# cursor motion bindings
|
||||||
set ::spicewish::viewer::meas_y1(%W) [%W yaxis invtransform $::zoomInfo(%W,A,y)]
|
bind $w.g <Motion> {
|
||||||
set ::spicewish::viewer::meas_dx(%W) [expr ($::spicewish::viewer::meas_x2(%W) - $::spicewish::viewer::meas_x1(%W))]
|
if { $::zoomInfo(%W,B,x) != "" } {
|
||||||
set ::spicewish::viewer::meas_dy(%W) [expr ($::spicewish::viewer::meas_y2(%W) - $::spicewish::viewer::meas_y1(%W))]
|
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 { } {
|
proc names { } {
|
||||||
|
|
@ -142,7 +158,6 @@ namespace eval viewer {
|
||||||
proc plot { args } {
|
proc plot { args } {
|
||||||
|
|
||||||
if {$args == ""} {return}
|
if {$args == ""} {return}
|
||||||
|
|
||||||
spice::bltplot $args
|
spice::bltplot $args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +169,11 @@ namespace eval viewer {
|
||||||
|
|
||||||
spice::setplot $plotTypeName
|
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
|
spice::setplot $currentPlotType
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +372,7 @@ namespace eval viewer {
|
||||||
spice::setplot $view_plotName($index)
|
spice::setplot $view_plotName($index)
|
||||||
|
|
||||||
::spice::X_Data set ""
|
::spice::X_Data set ""
|
||||||
spice::bltplot $trace
|
spice::bltplot [evaluate $trace]
|
||||||
|
|
||||||
eval $\{::$view_plotName($index):v:$trace\} set \"::spice::Y_Data\"
|
eval $\{::$view_plotName($index):v:$trace\} set \"::spice::Y_Data\"
|
||||||
|
|
||||||
|
|
@ -378,6 +397,25 @@ namespace eval viewer {
|
||||||
|
|
||||||
destroy $w
|
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 {
|
namespace eval vectors {
|
||||||
|
|
@ -396,7 +434,7 @@ namespace eval vectors {
|
||||||
return $name
|
return $name
|
||||||
} else {
|
} else {
|
||||||
::spice::Y_Data set ""
|
::spice::Y_Data set ""
|
||||||
uplevel #0 ::spice::bltplot $name
|
uplevel #0 ::spice::bltplot [spicewish::viewer::evaluate $name]
|
||||||
|
|
||||||
if {[::spice::Y_Data length] != 0} {
|
if {[::spice::Y_Data length] != 0} {
|
||||||
return $name
|
return $name
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue