This commit is contained in:
stefanjones 2004-08-10 23:28:45 +00:00
parent 789091b928
commit 8dc8bb950b
20 changed files with 1648 additions and 59 deletions

View File

@ -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:

View File

@ -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 \

943
src/frontend/com_measure.c Normal file
View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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 */

View File

@ -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]
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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

View File

@ -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{

View File

@ -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 { } {

View File

@ -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} {

View File

@ -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);

View File

@ -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