This is gck_lib.c in view mode; [Download] [Up]
/* ******************************************************************** */
/* * GCK * */
/* * A Circuit Simulation Program * */
/* * by Tanju Cataltepe * */
/* * (c) Copyright 1989 * */
/* ******************************************************************** */
/* (c) Copyright 1989, Tanju Cataltepe */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef Macintosh
#include <console.h>
#include <Files.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include <math.h>
#include <float.h>
#include "gck.h"
#include "gck_vars.h"
#include "gck_protos.h"
#include "gck_errors.h"
void *c_malloc(n)
long n;
{
void *ptr;
if (n == 0)
errorReport(ERROR_C_MALLOC_SIZE_ZERO,0,ERR_VOID,0);
ptr = calloc(n,1);
if (ptr == NULL)
errorReport(ERROR_C_MALLOC_VOID,0,ERR_VOID,0);
return (ptr);
}
int P_eof(f)
FILE *f;
{
register int ch;
if (feof(f))
return 1;
if (f == stdin)
return 0;
ch = getc(f);
if (ch == EOF)
return 1;
ungetc(ch, f);
return 0;
}
int P_eoln(f)
FILE *f;
{
register int ch;
ch = getc(f);
if (ch == EOF)
return 1;
ungetc(ch, f);
return (ch == '\n');
}
double gck_random()
{
return((double)((double)rand() / (double)(RAND_MAX >> 1)) - 1.0);
}
void initializeGlobals()
{
long i;
rfile.depth = 0;
for (i = 0; i < MAX_FILE_DEPTH; i++)
rfile.filePtr[i] = NULL;
strcpy(rfile.filename,"\0");
for (i = 0; i < MAX_SUBCKT_DEPTH; i++)
strcpy(sd[i],"\0");
ID_nindex_size = DYNAMIC_INITIAL_SIZE;
ID_nindex = (long *)c_malloc(sizeof(long) * (ID_nindex_size + 1));
nodeNames.max_nodes = DYNAMIC_INITIAL_SIZE;
nodeNames.node_size = 1;
nodeNames.node = (nodeNameStruct *)
c_malloc(sizeof(nodeNameStruct) * DYNAMIC_INITIAL_SIZE);
strcpy(nodeNames.node[0].name,"0");
for (i = 1; i < DYNAMIC_INITIAL_SIZE; i++)
nodeNames.node[i].name[0] = NULL_CHAR;
symbolNames.max_symbols = DYNAMIC_INITIAL_SIZE;
symbolNames.symbol_size = 0;
commandNames.max_symbols = DYNAMIC_INITIAL_SIZE;
commandNames.symbol_size = 0;
symbolNames.symbol = (symbolNameStruct *)
c_malloc(sizeof(symbolNameStruct) * DYNAMIC_INITIAL_SIZE);
commandNames.symbol = (symbolNameStruct *)
c_malloc(sizeof(symbolNameStruct) * DYNAMIC_INITIAL_SIZE);
for (i = 0; i < DYNAMIC_INITIAL_SIZE; i++) {
symbolNames.symbol[i].name[0] = NULL_CHAR;
commandNames.symbol[i].name[0] = NULL_CHAR;
}
up_to_date = TRUE;
cmdline_symbols = FALSE;
sample_card_found = FALSE;
#ifdef Macintosh
object_stamp = (long) 0;
#else
object_stamp = (time_t) 0;
#endif
flag_dialog = DIALOG_NORMAL;
flag_compiler = COMPILER_FORCE_COMPILATION;
deltaT = 1.0;
periodT = 0.0;
samplesOn = 1;
The_Time = 0.0;
lastTime = 0.0;
GND = (double *)c_malloc(sizeof(double));
*GND = 0.0;
sampleTicks = (clockRec *)c_malloc(sizeof(clockRec));
NoOfTicks = 1;
TicksRegistered = FALSE;
presentTick = 1;
NoOfVars = 0;
baseOfBranch = NULL;
baseOfClock = NULL;
baseOfNode = NULL;
baseOfNonlin = NULL;
baseOfDigital = NULL;
baseOfLogic = NULL;
baseOfTable = NULL;
baseOfModel = NULL;
baseOfSource = NULL;
baseOfPrint = NULL;
baseOfFFT = NULL;
baseOfMFFT = NULL;
baseOfStatus = NULL;
baseOfSubckt = NULL;
twoTerminal = (1L << ((long)resistor)) | (1L << ((long)capacitor)) |
(1L << ((long)inductor)) | (1L << ((long)switch_)) |
(1L << ((long)vs)) | (1L << ((long)cs));
fourTerminal = (1L << ((long)coupledInductor)) | (1L << ((long)opamp)) |
(1L << ((long)quantizer)) | (1L << ((long)comparator));
fourTerminal |= (1L << ((long)vcvs)) | (1L << ((long)vccs)) |
(1L << ((long)adder));
nonlinears = (1L << ((long)opamp)) | (1L << ((long)quantizer)) |
(1L << ((long)comparator));
globalControl = (1L << ((long)switch_)) | (1L << ((long)opamp)) |
(1L << ((long)quantizer)) | (1L << ((long)subckt)) |
(1L << ((long)delay)) | (1L << ((long)vs)) |
(1L << ((long)cs)) | (1L << ((long)l_general));
digitals = (1L << ((long)delay)) | (1L << ((long)adder)) |
(1L << ((long)multiplier));
logicals = 1L << ((long)l_general);
print_to_file = FALSE;
strcpy(prn_filename,"\0");
fft_to_file = FALSE;
strcpy(fft_filename,"\0");
fft_window = WINDOW_RECTANGULAR;
fft_must_reorder = TRUE; /* FFT vs. DFT */
shortPrint = TRUE;
timePrint = TRUE;
runDiag = FALSE;
binaryArray[0] = 1;
for (i = 1; i <= BINARY_LEN; i++)
binaryArray[i] = binaryArray[i - 1] * 2;
terminate_on_eof = FALSE;
terminate = FALSE;
}
void MakeValueList(base, n)
flex *base;
long n;
{
MakeSymbolList(base, n);
base->dim = n;
base->UU.c = c_malloc(sizeof(double) * n);
}
void MakeIDList(base, n)
flex *base;
long n;
{
MakeSymbolList(base, n);
base->dim = n;
base->UU.c = c_malloc(sizeof(long) * n);
}
long GetID(np, n)
flex np;
long n;
{
return (np.UU.n[n - 1]);
}
double GetValue(vp, n)
flex vp;
long n;
{
return (vp.UU.x[n - 1]);
}
/* this function is never called.... */
void PutToID(p, n, d)
flex *p;
long n, d;
{
p->UU.n[n - 1] = d;
}
void PutToValue(p, n, x)
flex *p;
long n;
double x;
{
p->UU.x[n - 1] = x;
}
long CloneID(src, res)
flex src, *res;
{
long i;
res->dim = src.dim;
res->UU.c = c_malloc(sizeof(long) * src.dim);
for (i = 0; i < src.dim; i++)
res->UU.n[i] = src.UU.n[i];
return (res->dim);
}
void GetBranchByID(there, n_ID)
branchRec **there;
long n_ID;
{
/*Finds the branch with ID number n_ID in the linked list*/
*there = baseOfBranch;
while (*there != NULL && (*there)->ID.UU.n[0] != n_ID)
*there = (*there)->next;
}
void GetBranchByName(there, bname)
branchRec **there;
char *bname;
{
/*Finds the branch with name bname in the linked list*/
boolean found;
*there = baseOfBranch;
found = FALSE;
while (*there != NULL && !found) {
if (strcmp((*there)->name, bname) == 0)
found = TRUE;
else
*there = (*there)->next;
}
if (!found)
errorReport(ERROR_UNRESOLVED_BRANCH, bname, ERR_VOID, 0);
}
void newBranch(b, no_ID, no_val)
branchRec **b;
long no_ID, no_val;
{
*b = (branchRec *)c_malloc(sizeof(branchRec));
(*b)->next = NULL;
MakeIDList(&(*b)->ID, no_ID);
MakeValueList(&(*b)->value, no_val);
}
void GetModelByName(there, mname)
modelRec **there;
char *mname;
{
/*Finds the model with name mname in the linked list*/
boolean found;
*there = baseOfModel;
found = FALSE;
while (*there != NULL && !found) {
if (strcmp((*there)->name, mname) == 0)
found = TRUE;
else
*there = (*there)->next;
}
if (!found)
errorReport(ERROR_UNRESOLVED_MODEL, mname, ERR_VOID, 0);
}
void GetClockByName(there, pname)
clockRec **there;
char *pname;
{
/*Finds the clock waveform named pname in the linked list*/
boolean found;
*there = baseOfClock;
found = FALSE;
while (*there != NULL && !found) {
if (strcmp((*there)->name, pname) == 0)
found = TRUE;
else
*there = (*there)->next;
}
if (!found)
errorReport(ERROR_UNRESOLVED_CLOCK, pname, ERR_VOID, 0);
}
void GetSubcktByName(there, sname)
subcktRec **there;
char *sname;
{
/*Finds the subcircuit names sname in the linked list*/
boolean found;
*there = baseOfSubckt;
found = FALSE;
while (*there != NULL && !found) {
if (strcmp((*there)->name, sname) == 0)
found = TRUE;
else
*there = (*there)->next;
}
if (!found)
errorReport(ERROR_UNRESOLVED_SUBCKT, sname, ERR_VOID, 0);
}
void GetFromSystem(there, n)
systemRec **there;
long n;
{
/*Finds the system record for the nth clock tick*/
long i;
*there = baseOfSystem;
for (i = 2; i <= n; i++)
*there = (*there)->next;
}
void InitializeSystem()
{
systemRec *tmp;
long matrix_loop;
long i, FORLIM;
baseOfSystem = NULL;
FORLIM = NoOfTicks;
for (i = 1; i <= FORLIM; i++) {
tmp = (systemRec *)c_malloc(sizeof(systemRec));
tmp->next = baseOfSystem;
/* No longer dependent upon VAR limitation ... 1 Mar 92 RdH */
/* Initialize new tmpSystem records */
tmp->N = (double **) c_malloc(NoOfVars * sizeof (double *));
tmp->B = (double **) c_malloc(NoOfVars * sizeof (double *));
for (matrix_loop = 0; matrix_loop < NoOfVars; matrix_loop++) {
tmp->N[matrix_loop] = (double *) c_malloc(NoOfVars * sizeof (double));
tmp->B[matrix_loop] = (double *) c_malloc(NoOfVars * sizeof (double));
}
baseOfSystem = tmp;
}
}
/* branchID returns a new branch number for every time it's called. */
long branchID()
{
NoOfVars++;
/* error checking eliminated ... no such limit exists */
return NoOfVars;
}
/************ Reading Utilities *************************/
void readCard(f, l)
FILE **f;
char *l;
{
char ch;
char dead_char; /* RdH */
long i, j;
boolean null_encountered;
int wordnum;
int aa;
int found; /* used to ignore blanks preceeding 1st char */
i = 1;
found = FALSE;
while (!P_eoln(*f)) {
ch = getc(*f);
if (ch == '\n')
ch = SPACE_CHAR;
if (ch == TAB_CHAR)
ch = SPACE_CHAR;
if (found == TRUE) {
l[i - 1] = ch;
i++;
}
else if ((ch != SPACE_CHAR) && (ch != TAB_CHAR)) {
found = TRUE;
l[i-1] = ch;
i++;
}
}
fscanf(*f, "%*[^\n]");
dead_char = getc(*f);
l[i-1] = '\0';
/* The following junk performs "getwords" on the entire card...
the function getword may now perform a single lookup... */
rcard.FIRSTCHAR = toupper(l[0]);
for (j = 0; j < 80; j++)
rcard.Card[j] = NULL_CHAR;
strcpy(rcard.Card,l);
/* get ALL words! */
for (wordnum = 0; wordnum < MAX_WORDS; wordnum++)
for (aa = 0; aa < MAX_WORD_LENGTH; aa++) {
rcard.Word[wordnum][aa] = NULL_CHAR;
rcard.WORD[wordnum][aa] = NULL_CHAR;
}
for (j = 0; j < 80; j++)
rcard.CARD[j] = l[j] = toupper(rcard.Card[j]);
if (&(rcard.Card[0]) != NULL_CHAR) {
wordnum = 0;
i = 0;
aa = 0;
null_encountered = FALSE;
do {
while ((rcard.Card[i] != NULL_CHAR)
&& (rcard.Card[i] != '=')
&& (rcard.Card[i] != SPACE_CHAR)
&& (rcard.Card[i] != TAB_CHAR)
&& (i < 80)
&& (wordnum < MAX_WORDS)) {
if (rcard.Card[i] == NULL_CHAR)
null_encountered = TRUE;
rcard.Word[wordnum][aa] = rcard.Card[i];
rcard.WORD[wordnum][aa] = rcard.CARD[i];
aa++;
i++;
}
rcard.Word[wordnum][aa] = NULL_CHAR;
rcard.WORD[wordnum][aa] = NULL_CHAR;
wordnum++;
i++;
aa = 0;
while ((rcard.Card[i] != NULL_CHAR)
&& ((rcard.Card[i] == '=')
|| (rcard.Card[i] == SPACE_CHAR)
|| (rcard.Card[i] == TAB_CHAR))
&& (i < 80)
&& (wordnum < MAX_WORDS)) {
if (rcard.Card[i] == NULL_CHAR)
null_encountered = TRUE;
rcard.Word[wordnum][i] = rcard.Card[i];
rcard.WORD[wordnum][i] = rcard.CARD[i];
i++;
}
} while ((i < 80) && (wordnum < MAX_WORDS) && (null_encountered == FALSE));
}
for (i = 0; i < MAX_WORDS; i++)
if ((rcard.Word[i][0] == NULL_CHAR) ||
(rcard.Word[i][0] == ';') ||
(rcard.Word[i][0] == '#'))
break;
rcard.word_count = i;
}
char *GetWord(Result,n)
char *Result;
long n;
{
return strcpy(Result,rcard.Word[n-1]);
}
char *GetWORD(Result,n)
char *Result;
long n;
{
return strcpy(Result,rcard.WORD[n-1]);
}
void readNNode(b, l, n)
branchRec **b;
char *l;
long n;
{
aWord tmp;
long i;
GetWORD(tmp,1L);
for (i = 0; i < NAME_LEN; i++)
(*b)->name[i] = tmp[i];
(*b)->ID.UU.n[0] = branchID();
for (i = 2; i <= n + 1; i++) {
GetWORD(tmp,i);
/* assigns a position for the given node RdH */
(*b)->ID.UU.n[i - 1] = nodeID(tmp);
}
}
/* Reads 2 more nodes from card */
void read2Node(b, l)
branchRec **b;
char *l;
{
readNNode(b, l, 2L);
}
void read4Node(b, l)
branchRec **b;
char *l;
{
readNNode(b, l, 4L);
}
void read2NodeName(b, l)
branchRec **b;
char *l;
{
/*NAME1 N+ N- NAME2*/
aWord tmp;
long i;
read2Node(b, l);
GetWORD(tmp,4L);
strcpy((*b)->cname,tmp);
(*b)->next = baseOfBranch;
baseOfBranch = *b;
}
void read4NodeName(b, l)
branchRec **b;
char *l;
{
/*NAME1 N+ N- NC+ NC- NAME2*/
aWord tmp;
long i;
read4Node(b, l);
GetWORD(tmp,6L);
for (i = 0; i < NAME_LEN; i++)
(*b)->cname[i] = tmp[i];
(*b)->next = baseOfBranch;
baseOfBranch = *b;
}
void read2NodeValue(b, l)
branchRec **b;
char *l;
{
/*NAME N+ N- VALUE*/
aWord tmp;
read2Node(b, l);
GetWORD(tmp,4L);
if (isalpha(tmp[0]))
(*b)->value.UU.x[0] = parseSymbol(b,0,4L);
else
(*b)->value.UU.x[0] = gck_atod(tmp);
(*b)->next = baseOfBranch;
baseOfBranch = *b;
}
void read4NodeValue(b, l)
branchRec **b;
char *l;
{
/*NAME N+ N- NC+ NC- VALUE*/
aWord tmp;
read4Node(b, l);
GetWORD(tmp,6L);
if (isalpha(tmp[0]))
(*b)->value.UU.x[0] = parseSymbol(b,0,6L);
else
(*b)->value.UU.x[0] = gck_atod(tmp);
(*b)->next = baseOfBranch;
baseOfBranch = *b;
}
/************ Specific Components ***********************/
/********** Clock Specifications ************/
void readLibrary()
{
aWord tmp;
GetWord(tmp,2L);
if (rfile.depth == (MAX_FILE_DEPTH - 1))
errorReport(ERROR_LIBRARY_DEPTH,0,ERR_VOID,0);
if ((rfile.filePtr[++rfile.depth] = fopen(tmp,"r")) == NULL)
errorReport(ERROR_LIBRARY_NOT_FOUND,tmp,ERR_VOID,0);
if (object_stamp < FileAge(tmp))
up_to_date = FALSE;
}
void readClock(l)
char *l;
{
/*.CLOCK NAME 11100001*/
clockRec *b;
aWord tmp;
long i, j, FORLIM;
b = (clockRec *)c_malloc(sizeof(clockRec));
GetWORD(tmp,2L);
strcpy(b->name,tmp);
GetWORD(tmp,3L);
i = 0;
do {
i++;
} while (tmp[i - 1] != NULL_CHAR); /* was SPACE */
i--;
if ((TicksRegistered == TRUE) && (NoOfTicks != i))
errorReport(ERROR_INCONSISTENT_CLOCKS,0,ERR_VOID,0);
if (TicksRegistered == FALSE) {
TicksRegistered = TRUE;
NoOfTicks = i;
}
MakeValueList(&b->value, NoOfTicks);
FORLIM = NoOfTicks;
for (j = 0; j < FORLIM; j++) {
if (tmp[j] == '1')
b->value.UU.x[j] = 1.0;
else
b->value.UU.x[j] = 0.0;
}
b->next = baseOfClock;
baseOfClock = b;
}
/*********** Node Specifications ******************/
void readNode(l)
char *l;
{
/*.NODE <NODE_NUMBER> LOW = <VSAT_LOW> HIGH = <VSAT_HIGH> SR = <SLEW_RATE>*/
nodeRec *b;
aWord tmp;
long i;
aWord TEMP;
b = (nodeRec *)c_malloc(sizeof(nodeRec));
GetWORD(tmp,2L);
b->ID = nodeID(tmp);
b->flo = FALSE;
b->fhi = FALSE;
b->fsr = FALSE;
i = 3;
GetWORD(tmp,i);
while (tmp[0] != NULL_CHAR) { /* was SPACE_CHAR RdH */
if (strncmp(tmp,"LOW",3) == 0) {
i++;
b->lo = gck_atod(GetWORD(TEMP,i));
b->flo = TRUE;
} else if (strncmp(tmp,"HIGH",4) == 0) {
i++;
b->hi = gck_atod(GetWORD(TEMP,i));
b->fhi = TRUE;
} else if (strncmp(tmp,"SR",2) == 0) {
i++;
b->sr = gck_atod(GetWORD(TEMP,i));
b->fsr = TRUE;
}
i++;
GetWORD(tmp,i);
}
b->next = baseOfNode;
baseOfNode = b;
}
void SetUpNodes()
{
nodeRec *tmpNode;
tmpNode = baseOfNode;
while (tmpNode != NULL) {
tmpNode->me = &vv_x[tmpNode->ID];
/* tmpNode->me = var_vector_x[tmpNode->ID]; */
tmpNode = tmpNode->next;
}
}
void RunNodes()
{
nodeRec *tmpN;
double d;
tmpN = baseOfNode;
while (tmpN != NULL) {
if (tmpN->flo) {
if (*tmpN->me < tmpN->lo)
*tmpN->me = tmpN->lo;
}
if (tmpN->fhi) {
if (*tmpN->me > tmpN->hi)
*tmpN->me = tmpN->hi;
}
if (tmpN->fsr) {
d = *tmpN->me - tmpN->oldme;
if (fabs(d) > tmpN->sr) {
if (d > 0)
*tmpN->me = tmpN->oldme + tmpN->sr;
else
*tmpN->me = tmpN->oldme - tmpN->sr;
}
tmpN->oldme = *tmpN->me;
}
tmpN = tmpN->next;
}
}
/********** Simulation Time ***************/
void readTimeStep(l)
char *l;
{
/*.STEP <VALUE>*/
aWord symbol;
aWord value;
GetWORD(symbol,2L);
if (isalpha(symbol[0])) {
GetWORD(value,3L);
createSymbol(symbol,value);
deltaT_sv.is_symbol = TRUE;
strcpy(deltaT_sv.sName,symbol);
if (strlen(value) == 0)
deltaT = 0.0;
else
deltaT = gck_atod(value);
}
else {
deltaT_sv.is_symbol = FALSE;
deltaT_sv.sName[0] = NULL_CHAR;
deltaT = gck_atod(GetWORD(symbol,2L));
}
}
void readClockPeriod(l)
char *l;
{
/*.PERIOD <VALUE>*/
aWord symbol;
aWord value;
GetWORD(symbol,2L);
if (isalpha(symbol[0])) {
GetWORD(value,3L);
createSymbol(symbol,value);
periodT_sv.is_symbol = TRUE;
strcpy(periodT_sv.sName,symbol);
if (strlen(value) == 0)
periodT = 0.0;
else
periodT = gck_atod(value);
}
else {
periodT_sv.is_symbol = FALSE;
periodT_sv.sName[0] = NULL_CHAR;
periodT = gck_atod(GetWORD(symbol,2L));
}
}
void readTime(l)
char *l;
{
/*.TIME <SIMULATION_TIME>*/
aWord symbol;
aWord value;
GetWORD(symbol,2L);
if (isalpha(symbol[0])) {
GetWORD(value,3L);
createSymbol(symbol,value);
lastTime_sv.is_symbol = TRUE;
strcpy(lastTime_sv.sName,symbol);
if (strlen(value) == 0)
lastTime = 0.0;
else
lastTime = gck_atod(value);
}
else {
lastTime_sv.is_symbol = FALSE;
lastTime_sv.sName[0] = NULL_CHAR;
lastTime = gck_atod(GetWORD(symbol,2L));
}
}
void readSample(l)
char *l;
{
/*.SAMPLE 00100*/
aWord tmp;
long i, j, FORLIM;
sample_card_found = TRUE;
GetWORD(tmp,2L);
i = 0;
do {
i++;
} while (tmp[i - 1] != NULL_CHAR); /* was SPACE_CHAR */
i--;
if ((TicksRegistered == TRUE) && (NoOfTicks != i))
errorReport(ERROR_INCONSISTENT_CLOCKS,0,ERR_VOID,0);
if (TicksRegistered == FALSE) {
TicksRegistered = TRUE;
NoOfTicks = i;
}
MakeValueList(&sampleTicks->value, NoOfTicks);
FORLIM = NoOfTicks;
samplesOn = 0;
for (j = 0; j < FORLIM; j++) {
if (tmp[j] == '1') {
sampleTicks->value.UU.x[j] = 1.0;
samplesOn++;
}
else
sampleTicks->value.UU.x[j] = 0.0;
}
}
void SetUpStubSample()
{
long j;
if (!sample_card_found) {
MakeValueList(&sampleTicks->value, NoOfTicks);
for (j = 0; j < NoOfTicks; j++) {
sampleTicks->value.UU.x[j] = 1.0;
}
}
}
void readPrint(l)
char *l;
{
/*.PRINT V(n1, n2) I(name) ...*/
printRec *tmpP, *lastP;
aWord tmpW;
nameString tmpN;
long i, j, k;
long counter;
i = 2;
GetWORD(tmpW,i);
while (tmpW[0] != NULL_CHAR) {
switch (tmpW[0]) {
case '>': /* new option */
print_to_file = TRUE;
if (tmpW[1] == NULL_CHAR) {
i++;
GetWord(prn_filename,i);
}
else {
GetWord(tmpW,i);
strcpy(prn_filename,&tmpW[1]);
}
break;
case 'V':
tmpP = (printRec *)c_malloc(sizeof(printRec));
tmpP->outType = branchVoltage;
strcpy(tmpN,"\0");
j = 3;
while ((tmpW[j - 1] != ',') && (tmpW[j - 1] != ')')) {
tmpN[j - 3] = tmpW[j - 1];
j++;
}
tmpN[j - 3] = NULL_CHAR;
tmpP->n1 = nodeRecordFromList(tmpN,REQUEST_NODE);
if (tmpW[j - 1] == ')') /* Remembering Ayse! */
tmpP->n2 = nodeRecordFromList("0",REQUEST_NODE);
else {
strcpy(tmpN,"\0");
k = j + 1;
while (tmpW[k - 1] != ')') {
tmpN[k - j - 1] = tmpW[k - 1];
k++;
}
tmpN[k - j - 1] = NULL_CHAR;
tmpP->n2 = nodeRecordFromList(tmpN,REQUEST_NODE);
}
if (baseOfPrint == NULL) {
baseOfPrint = tmpP;
lastP = tmpP;
} else {
lastP->next = tmpP;
lastP = tmpP;
}
break;
case 'I':
tmpP = (printRec *)c_malloc(sizeof(printRec));
tmpP->outType = branchCurrent;
strcpy(tmpN,"\0");
j = 3;
while (tmpW[j - 1] != ')') {
tmpN[j - 3] = tmpW[j - 1];
j++;
}
strcpy(tmpP->name,tmpN);
if (baseOfPrint == NULL) {
baseOfPrint = tmpP;
lastP = tmpP;
} else {
lastP->next = tmpP;
lastP = tmpP;
}
break;
default:
errorReport(ERROR_BAD_PRINTSPEC, progName, ERR_VOID, 0);
break;
}
i++;
GetWORD(tmpW,i);
}
}
void SetUpPrint()
{
printRec *tmp;
branchRec *b;
tmp = baseOfPrint;
while (tmp != NULL) {
switch (tmp->outType) {
case branchVoltage:
if (tmp->n1 == 0)
tmp->vo1 = GND;
else
tmp->vo1 = &vv_x[ID_nindex[tmp->n1]];
if (tmp->n2 == 0)
tmp->vo2 = GND;
else
tmp->vo2 = &vv_x[ID_nindex[tmp->n2]];
break;
case branchCurrent:
GetBranchByName(&b, tmp->name);
tmp->vo1 = &vv_x[b->ID.UU.n[0]];
tmp->vo2 = GND;
break;
}
tmp = tmp->next;
}
if (print_to_file) {
print_file = fopen(prn_filename,"w");
if (print_file == NULL)
errorReport(ERROR_FILE_PRINT_CANNOT_OPEN,prn_filename,ERR_VOID,0);
}
else {
print_file = stdout;
}
}
void RunPrint()
{
printRec *tmp;
float shTmp;
if (baseOfPrint == NULL)
return;
tmp = baseOfPrint;
if (shortPrint) {
if (timePrint) {
shTmp = The_Time;
fprintf(print_file,"% .5E%c", shTmp, TAB_CHAR);
}
} else {
if (timePrint)
fprintf(print_file,"% .5E%c", The_Time, TAB_CHAR);
}
while (tmp != NULL) {
if (shortPrint) {
shTmp = *tmp->vo1 - *tmp->vo2;
fprintf(print_file,"% .5E", shTmp);
} else
fprintf(print_file,"% .5E", *tmp->vo1 - *tmp->vo2);
if (tmp->next != NULL)
fprintf(print_file,"%c",TAB_CHAR);
else
fprintf(print_file,"\n");
tmp = tmp->next;
}
}
/*********** Model Specifications ********************/
void readModelSection(f, firstLine)
FILE **f;
char *firstLine;
{
/*.MODEL MODEL_NAME
VAL1 VAL2 ...
..
.END*/
card l;
aWord tmp;
nameString tmpName;
modelRec *tmpModel;
flex tmpV;
long i;
long symbol_count, position, op_amp_stub; /* RdH */
long model_size;
model_size = 10;
strcpy(l,firstLine);
GetWORD(tmp,2L);
strcpy(tmpName,tmp);
tmpModel = baseOfModel;
while (tmpModel != NULL) {
if (strcmp(tmpModel->name, tmpName) == 0)
errorReport(ERROR_DUPLICATE_MODEL, tmpName, ERR_VOID, 0);
else
tmpModel = tmpModel->next;
}
if (tmpModel != NULL)
return;
tmpModel = (modelRec *)c_malloc(sizeof(modelRec));
tmpModel->next = baseOfModel;
MakeSymbolList(&tmpV,2); /* symbols only work for op amps */
baseOfModel = tmpModel;
strcpy(baseOfModel->name,tmpName);
/*start reading the data section*/
readCard(f, l);
GetWORD(tmp,1L);
/* this next line limits ADC size ... Grrr */
tmpV.UU.c = c_malloc(sizeof(double) * model_size);
tmpV.dim = 0;
op_amp_stub = 0;
while (strncmp(tmp,".END",4) != 0) {
position = 1;
symbol_count = 0;
while (tmp[0] != NULL_CHAR) {
tmpV.dim++;
if (tmpV.dim == model_size) {
model_size += 10L;
tmpV.UU.c = realloc(tmpV.UU.c,sizeof(double) * model_size);
if (tmpV.UU.c == NULL)
errorReport(ERROR_REALLOC_MODEL,0,ERR_VOID,0);
}
GetWORD(tmp,position);
if ((isalpha(tmp[0])) && (op_amp_stub < 2)) {
symbol_count++;
tmpV.UU.x[tmpV.dim - 1] = parseSymbolModel(&tmpModel,tmpV.dim - 1,position++);
}
else
tmpV.UU.x[tmpV.dim - 1] = gck_atod(tmp);
position++;
op_amp_stub++;
GetWORD(tmp,position); /* stub, but necessary */
}
readCard(f, l);
GetWORD(tmp,1L);
}
baseOfModel->value.dim = tmpV.dim;
baseOfModel->value.UU.c = c_malloc(sizeof(double) * tmpV.dim);
for (i = 0; i < tmpV.dim; i++)
baseOfModel->value.UU.x[i] = tmpV.UU.x[i];
if (tmpV.UU.c != NULL)
free(tmpV.UU.c);
}
/********** Subcircuit *********/
void readXCard(l)
char *l;
{
/*XYYYYYYY N1 N2 ... SUBCKT_NAME*/
branchRec *b;
aWord tmp;
long i, nc;
aWord TEMP;
b = (branchRec *)c_malloc(sizeof(branchRec));
GetWORD(tmp,1L);
strcpy(b->name,tmp);
b->element = subckt;
nc = rcard.word_count - 2; /* number of nodes to pass to subckt */
MakeIDList(&b->ID, nc);
for (i = 1; i <= nc; i++)
b->ID.UU.n[i - 1] = nodeID(GetWORD(TEMP,i + 1));
GetWORD(tmp,nc + 2);
strcpy(b->cname,tmp);
b->next = baseOfBranch;
baseOfBranch = b;
}
void substituteSubckt(b)
branchRec **b;
{
long i, k, bn, newn;
branchRec *tmp, *tmpC;
subcktRec *s;
long depth;
char the_name[32];
depth = (*b)->depth + 1;
strcpy(the_name,(*b)->name);
GetSubcktByName(&s, (*b)->cname);
if (s == NULL)
errorReport(ERROR_UNRESOLVED_SUBCKT, (*b)->cname, ERR_VOID, 0);
tmp = s->base; /*branch(es) to be copied*/
while (tmp != NULL) {
if (tmp->element == subckt) {
if (strcmp(tmp->cname,s->name) == 0)
errorReport(ERROR_RECURSIVE_SUBCKT, s->name, ERR_VOID, 0);
}
tmpC = (branchRec *)c_malloc(sizeof(branchRec));
tmpC->element = tmp->element;
/*obtain unique names by concanating to the 1st
8 characters of the subckt branch name the 1st
8 characters of the calling branch name (i.e. XYYY)*/
for (i = 0; i < NAME_HAF; i++)
tmpC->name[i] = tmp->name[i];
for (i = NAME_HAF + 1; i <= NAME_LEN; i++)
tmpC->name[i - 1] = (*b)->name[i - 5];
if (((1L << ((long)tmpC->element)) & globalControl) != 0) {
for (i = 0; i < NAME_LEN; i++)
tmpC->cname[i] = tmp->cname[i];
} else {
for (i = 0; i < NAME_HAF; i++)
tmpC->cname[i] = tmp->cname[i];
for (i = NAME_HAF + 1; i <= NAME_LEN; i++)
tmpC->cname[i - 1] = (*b)->name[i - 5];
}
/*no need to replicate the value list*/
tmpC->value = tmp->value;
/*adjust the IDs*/
k = CloneID(tmp->ID, &tmpC->ID);
for (i = 0; i < k; i++) {
bn = GetID(tmpC->ID, i + 1);
if (bn != 0) {
if (bn <= s->NConn) /*external nodes*/
tmpC->ID.UU.n[i] = (*b)->ID.UU.n[bn - 1];
else {
newn = NoOfVars + bn - s->NConn;
tmpC->ID.UU.n[i] = newn;
}
}
}
/* RdH March 24, 1992 */
tmpC->depth = depth;
strcpy(tmpC->cktname,the_name);
tmpC->next = (*b)->next;
(*b)->next = tmpC;
tmp = tmp->next;
}
NoOfVars += s->NVar - s->NConn;
}
/************** Capacitor **************/
void MakeCapacitor(b)
branchRec **b;
{
newBranch(b, 3L, 1L);
(*b)->element = capacitor;
}
void readCapacitor(l)
char *l;
{
/*CXXXX N+ N- VALUE*/
branchRec *b;
MakeCapacitor(&b);
read2NodeValue(&b, l);
}
/************** Inductor **************/
void MakeInductor(b)
branchRec **b;
{
newBranch(b, 3L, 1L);
(*b)->element = inductor;
}
void readInductor(l)
char *l;
{
/*LXXXX N+ N- VALUE*/
branchRec *b;
MakeInductor(&b);
read2NodeValue(&b, l);
}
/************** Resistor **************/
void MakeResistor(b)
branchRec **b;
{
newBranch(b, 3L, 1L);
(*b)->element = resistor;
}
void readResistor(l)
char *l;
{
/*RXXXX N+ N- VALUE*/
branchRec *b;
MakeResistor(&b);
read2NodeValue(&b, l);
}
/************** Sources **************/
void readSource(l)
char *l;
{
/* vars help FILE implementation */
char tmpfn[64];
int nn;
/* RdH December 18 1991 v0.2.0 changes reflected here */
/*VXXXX N+ N-
SIN <amp> <freq>
| DC <amp>
| STDIN
| FILE <filename>
| RND <lim>
| PULSE <unpulsed_amp> <pulsed_amp> <period> <delay> <rise_time> <duration> <fall_time>
| IMPULSE <amplitude>
| COMB <amp> <start_freq> <delta_freq> <no_of_freq>
*/
/*IXXXX N+ N- <source_specification> */
branchRec *b;
aWord tmp, tmpd;
long i;
aWord TEMP;
aWord T2;
long position;
long loop;
long symbol_count;
newBranch(&b, 3L, 1L); /* was 0L on 3rd parameter...3 Mar 92 RdH */
read2Node(&b, l);
GetWORD(tmp,4L);
if (strncmp(tmp,"SIN",3) == 0) {
MakeValueList(&b->value, 3L);
position = 5;
symbol_count = 0;
for (loop = 0; loop < 3; loop++) {
GetWORD(T2,position);
if ((loop == 2) && (T2[0] == NULL_CHAR))
b->value.UU.x[2] = 0.0;
else if (isalpha(T2[0])) {
symbol_count++;
b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
}
else
b->value.UU.x[loop] = gck_atod(T2);
position++;
if ((loop == 2) && (T2[0] != NULL_CHAR))
symbol_count++; /* not really, just error checking! */
}
strcpy(b->cname,"SIN");
if (rcard.word_count < (6 + symbol_count))
errorReport(ERROR_SIN_CARD_BROKEN,0,ERR_VOID,0);
} else if (strncmp(tmp,"COMB",4) == 0) {
MakeValueList(&b->value, 4L);
position = 5;
symbol_count = 0;
for (loop = 0; loop < 4; loop++) {
GetWORD(T2,position);
if (isalpha(T2[0])) {
symbol_count++;
b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
}
else
b->value.UU.x[loop] = gck_atod(T2);
position++;
}
strcpy(b->cname,"COMB");
if (rcard.word_count < (8 + symbol_count))
errorReport(ERROR_COMB_CARD_BROKEN,0,ERR_VOID,0);
} else if (strncmp(tmp,"DC",2) == 0) {
MakeValueList(&b->value, 1L);
GetWORD(T2,5L);
if (isalpha(T2[0]))
b->value.UU.x[0] = parseSymbol(&b,0,5L);
else
b->value.UU.x[0] = gck_atod(T2);
strcpy(b->cname,"DC");
} else if (strncmp(tmp,"IMPULSE",7) == 0) {
MakeValueList(&b->value, 1L);
GetWORD(T2,5L);
if (isalpha(T2[0]))
b->value.UU.x[0] = parseSymbol(&b,0,5L);
else
b->value.UU.x[0] = gck_atod(T2);
strcpy(b->cname,"IMPULSE");
} else if (strncmp(tmp,"RND",3) == 0) {
MakeValueList(&b->value, 1L);
GetWORD(T2,5L);
if (isalpha(T2[0]))
b->value.UU.x[0] = parseSymbol(&b,0,5L);
else
b->value.UU.x[0] = gck_atod(T2);
strcpy(b->cname,"RND");
} else if (strncmp(tmp,"STDIN",5) == 0)
strcpy(b->cname,"STDIN");
else if (strncmp(tmp,"FILE",4) == 0) {
MakeValueList(&b->value, 32L);
strcpy(tmpfn,GetWord(TEMP,5L));
strcpy(&(b->value.UU.w[0]),tmpfn);
strcpy(b->cname,"FILE");
} else if (strncmp(tmp, "PULSE",5) == 0) {
MakeValueList(&b->value, 7L);
position = 5;
symbol_count = 0;
for (loop = 0; loop < 7; loop++) {
GetWORD(T2,position);
if (isalpha(T2[0])) {
symbol_count++;
b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
}
else
b->value.UU.x[loop] = gck_atod(T2);
position++;
}
strcpy(b->cname,"PULSE");
if (rcard.word_count < (11 + symbol_count))
errorReport(ERROR_PULSE_CARD_BROKEN,0,ERR_VOID,0);
} else
errorReport(ERROR_UNRESOLVED_SOURCE, progName, ERR_VOID, 0);
GetWORD(tmp,1L);
if (tmp[0] == 'v' || tmp[0] == 'V')
b->element = vs;
else if (tmp[0] == 'i' || tmp[0] == 'I')
b->element = cs;
b->next = baseOfBranch;
baseOfBranch = b;
}
void CreateSourceList()
{
/* This function is completely new, in hopes that it will assist
in shattering the MaX_VARS requirement ... 1 Mar 92 RdH */
/* Now that the number of Vars is known, create an array for them */
long i, FORLIM;
FORLIM = NoOfVars;
vv_s = (double *) c_malloc((NoOfVars + 1) * sizeof(double));
/* limits should include "NoOfVars + 1"-th element */
for (i = 0; i <= FORLIM; i++) { /* Init not really necessary */
vv_s[i] = 0.0;
}
}
void SetUpSources()
{
branchRec *b;
sourceRec *tmpS;
long i, dummy;
sourceRec *WITH;
b = baseOfBranch;
while (b != NULL) {
if (((1L << ((long)b->element)) &
((1L << ((long)vs)) | (1L << ((long)cs)))) != 0) {
tmpS = (sourceRec *)c_malloc(sizeof(sourceRec));
tmpS->next = baseOfSource;
baseOfSource = tmpS;
if (!strncmp(b->cname, "SIN", sizeof(nameString))) {
baseOfSource->signal = sinusoid;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.U0.amp = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.U0.amp = b->value.UU.x[0];
if (b->value.sv[1].is_symbol)
baseOfSource->VV.U0.freq = TWOPI * getSymbolValueByName(b->value.sv[1].sName);
else
baseOfSource->VV.U0.freq = TWOPI * b->value.UU.x[1];
if (b->value.sv[2].is_symbol)
baseOfSource->VV.U0.dly = getSymbolValueByName(b->value.sv[2].sName);
else
baseOfSource->VV.U0.dly = b->value.UU.x[2];
} else if (!strncmp(b->cname, "COMB", sizeof(nameString))) {
baseOfSource->signal = comb;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.U5.amp0 = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.U5.amp0 = b->value.UU.x[0];
if (b->value.sv[1].is_symbol)
baseOfSource->VV.U5.freq0 = TWOPI * getSymbolValueByName(b->value.sv[1].sName);
else
baseOfSource->VV.U5.freq0 = TWOPI * b->value.UU.x[1];
if (b->value.sv[2].is_symbol)
baseOfSource->VV.U5.deltaF = TWOPI * getSymbolValueByName(b->value.sv[2].sName);
else
baseOfSource->VV.U5.deltaF = TWOPI * b->value.UU.x[2];
if (b->value.sv[3].is_symbol)
baseOfSource->VV.U5.noFreq = (long) floor(getSymbolValueByName(b->value.sv[3].sName) + 0.5);
else
baseOfSource->VV.U5.noFreq = (long) floor(b->value.UU.x[3] + 0.5);
} else if (!strncmp(b->cname, "DC", sizeof(nameString))) {
baseOfSource->signal = dc;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.A = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.A = b->value.UU.x[0];
} else if (!strncmp(b->cname, "IMPULSE", sizeof(nameString))) {
baseOfSource->signal = impulse;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.A = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.A = b->value.UU.x[0];
} else if (!strncmp(b->cname, "STDIN", sizeof(nameString))) {
baseOfSource->signal = fromStdin;
terminate_on_eof = TRUE;
}
else if (!strncmp(b->cname, "FILE", sizeof(nameString))) {
baseOfSource->signal = fromFile;
terminate_on_eof = TRUE;
baseOfSource->VV.U7.FilePtr = fopen(&(b->value.UU.w[0]),"r");
if (baseOfSource->VV.U7.FilePtr == 0)
errorReport(ERROR_INPUT_FILE_NOT_FOUND,&(b->value.UU.w[0]),ERR_VOID,0);
} else if (!strncmp(b->cname, "RND", sizeof(nameString))) {
baseOfSource->signal = rndm;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.L = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.L = b->value.UU.x[0];
} else if (!strncmp(b->cname, "PULSE", sizeof(nameString))) {
baseOfSource->signal = pulse;
if (b->value.sv[0].is_symbol)
baseOfSource->VV.U3.unpls = getSymbolValueByName(b->value.sv[0].sName);
else
baseOfSource->VV.U3.unpls = b->value.UU.x[0];
if (b->value.sv[1].is_symbol)
baseOfSource->VV.U3.pls = getSymbolValueByName(b->value.sv[1].sName);
else
baseOfSource->VV.U3.pls = b->value.UU.x[1];
if (b->value.sv[2].is_symbol)
baseOfSource->VV.U3.T = getSymbolValueByName(b->value.sv[2].sName);
else
baseOfSource->VV.U3.T = b->value.UU.x[2];
if (b->value.sv[3].is_symbol)
baseOfSource->VV.U3.td = getSymbolValueByName(b->value.sv[3].sName);
else
baseOfSource->VV.U3.td = b->value.UU.x[3];
if (b->value.sv[4].is_symbol)
baseOfSource->VV.U3.tr = getSymbolValueByName(b->value.sv[4].sName);
else
baseOfSource->VV.U3.tr = b->value.UU.x[4];
if (b->value.sv[5].is_symbol)
baseOfSource->VV.U3.tp = getSymbolValueByName(b->value.sv[5].sName);
else
baseOfSource->VV.U3.tp = b->value.UU.x[5];
if (b->value.sv[6].is_symbol)
baseOfSource->VV.U3.tf = getSymbolValueByName(b->value.sv[6].sName);
else
baseOfSource->VV.U3.tf = b->value.UU.x[6];
WITH = baseOfSource;
if (WITH->VV.U3.tr != 0)
WITH->VV.U3.mr = (WITH->VV.U3.pls - WITH->VV.U3.unpls) / WITH->VV.U3.tr;
if (WITH->VV.U3.tf != 0)
/* was mf ... since Pascal ... RdH */
WITH->VV.U3.mf = (WITH->VV.U3.unpls - WITH->VV.U3.pls) / WITH->VV.U3.tf;
} else
errorReport(ERROR_UNRESOLVED_SOURCE, progName, ERR_VOID, 0);
baseOfSource->branch = b;
i = b->ID.UU.n[0];
baseOfSource->value = &vv_s[i];
}
b = b->next;
}
/* RdH Modified the following:
the line:
dummy := seed(wallclock);
was changed to
dummy := 0;
the current compiler / system does not recognize neither the
seed function, or the "wallclock" variable.....
I must look into this more.
*/
dummy = 0;
}
void RunSources()
{
char dead_char; /* RdH */
sourceRec *tmpS;
double tmp;
long i, FORLIM;
double t;
tmpS = baseOfSource;
while (tmpS != NULL) {
switch (tmpS->signal) {
case sinusoid:
*tmpS->value = tmpS->VV.U0.amp *
sin(tmpS->VV.U0.freq * (The_Time - tmpS->VV.U0.dly));
break;
case comb:
tmp = sin(tmpS->VV.U5.freq0 * The_Time);
FORLIM = tmpS->VV.U5.noFreq;
for (i = 2; i <= FORLIM; i++)
tmp += sin((tmpS->VV.U5.freq0 + i * tmpS->VV.U5.deltaF) * The_Time);
*tmpS->value = tmpS->VV.U5.amp0 * tmp;
break;
case dc:
*tmpS->value = tmpS->VV.A;
break;
case impulse:
if (The_Time == 0)
*tmpS->value = tmpS->VV.A;
else
*tmpS->value = 0.0;
break;
case fromStdin:
if (!P_eof(stdin)) {
scanf("%lg%*[^\n]", tmpS->value);
dead_char = getchar();
}
if (P_eof(stdin))
terminate = TRUE;
break;
case fromFile:
if (!feof(tmpS->VV.U7.FilePtr)) {
fscanf(tmpS->VV.U7.FilePtr,"%lg%*[^\n]", tmpS->value);
}
if (feof(tmpS->VV.U7.FilePtr))
terminate = TRUE;
break;
case pulse:
t = The_Time - floor(The_Time / tmpS->VV.U3.T) * tmpS->VV.U3.T;
if (t < tmpS->VV.U3.td)
*tmpS->value = tmpS->VV.U3.unpls;
else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp + tmpS->VV.U3.tf)
*tmpS->value = tmpS->VV.U3.unpls;
else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr &&
t < tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp)
*tmpS->value = tmpS->VV.U3.pls;
else if (t >= tmpS->VV.U3.td &&
t < tmpS->VV.U3.td + tmpS->VV.U3.tr)
*tmpS->value = (t - tmpS->VV.U3.td) * tmpS->VV.U3.mr +
tmpS->VV.U3.unpls;
else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp &&
t <
tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp + tmpS->VV.U3.tf)
*tmpS->value = (t - tmpS->VV.U3.td - tmpS->VV.U3.tr - tmpS->VV.U3.tp)
* tmpS->VV.U3.mf + tmpS->VV.U3.pls;
break;
case rndm:
*tmpS->value = gck_random() * tmpS->VV.L;
break;
}
tmpS = tmpS->next;
}
}
/************** VCVS **************/
void MakeVCVS(b)
branchRec **b;
{
newBranch(b, 5L, 1L);
(*b)->element = vcvs;
}
void readVCVS(l)
char *l;
{
/*EXXXX N+ N- NC+ NC- VALUE*/
branchRec *b;
MakeVCVS(&b);
read4NodeValue(&b, l);
}
/************** VCCS **************/
void MakeVCCS(b)
branchRec **b;
{
newBranch(b, 5L, 1L);
(*b)->element = vccs;
}
void readVCCS(l)
char *l;
{
/*GXXXX N+ N- NC+ NC- VALUE*/
branchRec *b;
MakeVCCS(&b);
read4NodeValue(&b, l);
}
/************** CCVS **************/
void MakeCCVS(b)
branchRec **b;
{
newBranch(b, 4L, 1L);
(*b)->element = ccvs; /* OH CRAP ? A BUG ? RdH Was "vccs" */
}
void readCCVS(l)
char *l;
{
/*HYYY N+ N- CONTROL_NAME VALUE*/
aWord tmp;
branchRec *b;
MakeCCVS(&b);
read2NodeName(&b, l);
GetWORD(tmp,5L);
if (isalpha(tmp[0]))
b->value.UU.x[0] = parseSymbol(&b,0,5L);
else
b->value.UU.x[0] = gck_atod(tmp);
}
/************** CCCS **************/
void MakeCCCS(b)
branchRec **b;
{
newBranch(b, 4L, 1L);
(*b)->element = cccs;
}
void readCCCS(l)
char *l;
{
/*FYYY N+ N- CONTROL_NAME VALUE*/
aWord tmp;
branchRec *b;
MakeCCCS(&b);
read2NodeName(&b, l);
GetWORD(tmp,5L);
if (isalpha(tmp[0]))
b->value.UU.x[0] = parseSymbol(&b,0,5L);
else
b->value.UU.x[0] = gck_atod(tmp);
}
/************** Switch **************/
void MakeSwitch(b)
branchRec **b;
{ /* value points to a clock sequence */
newBranch(b, 3L, 1L); /* was 0L on 3rd parameter...3 Mar 92 RdH */
(*b)->element = switch_;
}
void readSwitch(l)
char *l;
{
/*SXXXX N+ N- CLOCK_NAME*/
branchRec *b;
MakeSwitch(&b);
read2NodeName(&b, l);
}
void SetUpClock(b)
branchRec **b;
{
clockRec *clk;
GetClockByName(&clk, (*b)->cname);
(*b)->value = clk->value;
}
void SetUpModel(b)
branchRec **b;
{
modelRec *mdl;
GetModelByName(&mdl, (*b)->cname);
(*b)->value = mdl->value;
}
/************** Opamp **************/
void MakeOpamp(b)
branchRec **b;
{
newBranch(b, 5L, 1L); /* was 0L on 3rd parameter...3 Mar 92 RdH */
/*
value_1 = gain,
value_2 = slew rate a special case of vcvs
*/
(*b)->element = opamp;
}
void readOpamp(l)
char *l;
{
/*OXXXX N+ N- NC+ NC- MODEL_NAME*/
branchRec *b;
MakeOpamp(&b);
read4NodeName(&b, l);
}
void RunOpamp(op)
nonlinRec **op;
{
double tmp1, tmp2, sr;
sr = (*op)->branch->value.UU.x[1] * deltaT;
tmp1 = *(*op)->out1 - *GND - (*op)->xdata1;
tmp2 = *(*op)->out2 - *GND - (*op)->xdata2;
*(*op)->src = 0.0;
if (fabs(tmp1) > sr) {
if (tmp1 > 0)
*(*op)->out1 = (*op)->xdata1 + sr;
else
*(*op)->out1 = (*op)->xdata1 - sr;
}
if (fabs(tmp2) > sr) {
if (tmp2 > 0)
*(*op)->out2 = (*op)->xdata2 + sr;
else
*(*op)->out2 = (*op)->xdata2 - sr;
}
(*op)->xdata1 = *(*op)->out1;
(*op)->xdata2 = *(*op)->out2;
}
/************** Quantizer **************/
void MakeQuantizer(b)
branchRec **b;
{ /* upper threshold and output level */
newBranch(b, 5L, 1L); /* was 0L on 3rd parameter...3 Mar 92 RdH */
(*b)->element = quantizer;
}
void readQuantizer(l)
char *l;
{
/*QXXXX N+ N- NC+ NC- MODEL_NAME*/
branchRec *b;
MakeQuantizer(&b);
read4NodeName(&b, l);
}
void RunQuantizer(qt)
nonlinRec **qt;
{
double tmpIn;
boolean done;
long i;
tmpIn = *(*qt)->in1 - *(*qt)->in2;
i = 1;
done = FALSE;
while (!done && i <= (*qt)->branch->value.dim) {
if (tmpIn >= (*qt)->branch->value.UU.x[i - 1])
done = TRUE;
i++;
if (i > (*qt)->branch->value.dim)
errorReport(ERROR_QUANTIZER, (*qt)->branch->name, ERR_VOID, 0);
if (done)
*(*qt)->src = (*qt)->branch->value.UU.x[i - 1];
}
}
/************* General Nonlinear Stuff ****************/
void MakeNonlinList()
{
/*goes through the completed branch list to find nonlinear elements*/
nonlinRec *tmpNonlin;
branchRec *tmpBranch;
modelRec *tmpModel;
tmpBranch = baseOfBranch;
while (tmpBranch != NULL) {
switch (tmpBranch->element) {
case opamp:
if (tmpBranch->value.dim > 1) {
tmpNonlin = (nonlinRec *)c_malloc(sizeof(nonlinRec));
GetModelByName(&tmpModel, tmpBranch->cname);
tmpBranch->value.dim = tmpModel->value.dim;
/* op amp gain */
if (tmpModel->value.sv[0].is_symbol)
tmpBranch->value.UU.x[0] = getSymbolValueByName(tmpModel->value.sv[0].sName);
else
tmpBranch->value.UU.x[0] = tmpModel->value.UU.x[0];
/* slew rate */
if (tmpModel->value.sv[0].is_symbol)
tmpBranch->value.UU.x[1] = getSymbolValueByName(tmpModel->value.sv[1].sName);
else
tmpBranch->value.UU.x[1] = tmpModel->value.UU.x[1];
tmpNonlin->branch = tmpBranch;
tmpNonlin->next = baseOfNonlin;
baseOfNonlin = tmpNonlin;
}
break;
case quantizer:
tmpNonlin = (nonlinRec *)c_malloc(sizeof(nonlinRec));
GetModelByName(&tmpModel, tmpBranch->cname);
tmpBranch->value.dim = tmpModel->value.dim;
/* might have to fix ... RdH */
tmpBranch->value.UU.x = tmpModel->value.UU.x;
tmpNonlin->branch = tmpBranch;
tmpNonlin->next = baseOfNonlin;
baseOfNonlin = tmpNonlin;
/* var_vector_s[tmpBranch->ID.UU.n[0]] = (double *)c_malloc(sizeof(double)); */
/* call is redundant now ... RdH 1 Mar 92 */
break;
}
tmpBranch = tmpBranch->next;
}
}
void SetUpNonlins()
{
nonlinRec *tmpNon;
long bn, n1, n2, nc1, nc2;
tmpNon = baseOfNonlin;
while (tmpNon != NULL) {
bn = tmpNon->branch->ID.UU.n[0];
n1 = tmpNon->branch->ID.UU.n[1];
n2 = tmpNon->branch->ID.UU.n[2];
nc1 = tmpNon->branch->ID.UU.n[3];
nc2 = tmpNon->branch->ID.UU.n[4];
tmpNon->src = &vv_s[bn];
tmpNon->out1 = &vv_x[n1];
tmpNon->out2 = &vv_x[n2];
tmpNon->in1 = &vv_x[nc1];
tmpNon->in2 = &vv_x[nc2];
tmpNon = tmpNon->next;
}
}
void RunNonlins()
{
nonlinRec *tmpN;
tmpN = baseOfNonlin;
while (tmpN != NULL) {
switch (tmpN->branch->element) {
case opamp:
RunOpamp(&tmpN);
break;
case quantizer:
RunQuantizer(&tmpN);
break;
}
tmpN = tmpN->next;
}
}
/********** Digital Stuff **********/
/************** Delay **************/
void MakeDelay(b)
branchRec **b;
{
newBranch(b, 5L, 1L);
(*b)->element = delay;
}
void readDelay(l)
char *l;
{
/*@DXXXX N_OUT N_IN NO_OF_TICKS_OF_DELAY*/
branchRec *b;
long nr;
aWord tmpW;
MakeDelay(&b);
read2NodeValue(&b, l);
b->ID.UU.n[3] = b->ID.UU.n[2];
b->ID.UU.n[2] = 0;
b->ID.UU.n[4] = 0;
b->value.UU.x[0] = 0.0;
GetWORD(tmpW,4L);
if (isalpha(tmpW[0])) {
nr = (long) parseSymbol(&b,0,4L);
}
else
nr = atol(tmpW);
if (nr <= 0)
errorReport(ERROR_DELAY_ZERO, b->name, ERR_VOID, 0);
b->value.dim = nr;
b->value.UU.c = c_malloc(sizeof(double) * nr);
}
void SetUpDelay(dl)
digitalRec **dl;
{
long bn, nc1;
long new_size;
long counter;
/* get new dimension from symbol */
if ((*dl)->branch->value.sv[0].is_symbol) {
new_size = (long) (*dl)->branch->value.sv[0].delay;
/* reallocate size */
if (new_size != (*dl)->branch->value.dim) {
(*dl)->branch->value.UU.c =
realloc((*dl)->branch->value.UU.c,sizeof(double) * new_size);
if ((*dl)->branch->value.UU.c == NULL)
errorReport(ERROR_REALLOC_DELAY,0,ERR_VOID,0);
/* causes realloc to "calloc" new region */
for (counter = (*dl)->branch->value.dim; counter < new_size; counter++)
(*dl)->branch->value.UU.x[counter] = (double) 0.0;
(*dl)->branch->value.dim = new_size;
}
}
bn = (*dl)->branch->ID.UU.n[0];
nc1 = (*dl)->branch->ID.UU.n[3];
(*dl)->out1 = &vv_s[bn];
if (nc1 == 0)
(*dl)->in1 = GND;
else
(*dl)->in1 = &vv_x[nc1];
}
void RunDelay(dl)
digitalRec **dl;
{
long i;
for (i = (*dl)->branch->value.dim; i >= 2; i--)
(*dl)->branch->value.UU.x[i - 1] = (*dl)->branch->value.UU.x[i - 2];
(*dl)->branch->value.UU.x[0] = *(*dl)->in1;
*(*dl)->out1 = (*dl)->branch->value.UU.x[(*dl)->branch->value.dim - 1];
}
/************** Adder **************/
void MakeAdder(b)
branchRec **b;
{
newBranch(b, 5L, 2L);
(*b)->element = adder;
}
void readAdder(l)
char *l;
{
/*@AXXXX N_OUT N_IN1 N_IN2 VAL_1 VAL_2*/
branchRec *b;
aWord tmp;
long i;
aWord TEMP,T2;
long position, symbol_count, loop;
MakeAdder(&b);
GetWORD(tmp,1L);
strcpy(b->name,tmp);
b->ID.UU.n[0] = branchID();
b->ID.UU.n[1] = nodeID(GetWORD(TEMP,2L));
b->ID.UU.n[2] = 0;
b->ID.UU.n[3] = nodeID(GetWORD(TEMP,3L));
b->ID.UU.n[4] = nodeID(GetWORD(TEMP,4L));
position = 5;
symbol_count = 0;
for (loop = 0; loop < 2; loop++) {
GetWORD(T2,position);
if (isalpha(T2[0])) {
symbol_count++;
b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
}
else
b->value.UU.x[loop] = gck_atod(T2);
position++;
}
if (rcard.word_count < (6 + symbol_count))
errorReport(ERROR_ADDER_CARD_BROKEN,0,ERR_VOID,0);
b->next = baseOfBranch;
baseOfBranch = b;
}
/************** Multiplier **************/
void MakeMult(b)
branchRec **b;
{
newBranch(b, 5L, 2L);
(*b)->element = multiplier;
}
void readMult(l)
char *l;
{
/*@MXXXX N_OUT N_IN1 N_IN2*/
branchRec *b;
aWord tmp;
long i;
aWord TEMP;
MakeMult(&b);
GetWORD(tmp,1L);
strcpy(b->name,tmp);
b->ID.UU.n[0] = branchID();
b->ID.UU.n[1] = nodeID(GetWORD(TEMP,2L));
b->ID.UU.n[2] = 0;
b->ID.UU.n[3] = nodeID(GetWORD(TEMP,3L));
b->ID.UU.n[4] = nodeID(GetWORD(TEMP,4L));
b->next = baseOfBranch;
baseOfBranch = b;
}
void SetUpMult(mlt)
digitalRec **mlt;
{
long bn, nc1, nc2;
bn = (*mlt)->branch->ID.UU.n[0];
nc1 = (*mlt)->branch->ID.UU.n[3];
nc2 = (*mlt)->branch->ID.UU.n[4];
/* var_vector_s[bn] = (double *)c_malloc(sizeof(double)); */
/* (*mlt)->out1 = var_vector_s[bn]; */
(*mlt)->out1 = &vv_s[bn];
if (nc1 == 0)
(*mlt)->in1 = GND;
else
/* (*mlt)->in1 = var_vector_x[nc1]; */
(*mlt)->in1 = &vv_x[nc1];
if (nc2 == 0)
(*mlt)->in2 = GND;
else
/* (*mlt)->in2 = var_vector_x[nc2]; */
(*mlt)->in2 = &vv_x[nc2];
}
void RunMult(mlt)
digitalRec **mlt;
{
*(*mlt)->out1 = *(*mlt)->in1 * *(*mlt)->in2;
}
void readDigital(l)
char *l;
{
aWord tmp;
GetWORD(tmp,1L);
switch (tmp[1]) {
case 'D':
readDelay(l);
break;
case 'A':
readAdder(l);
break;
case 'M':
readMult(l);
break;
default:
errorReport(ERROR_DIGITAL_UNKNOWN, progName, ERR_VOID, 0);
break;
}
}
void MakeDigitalList()
{
digitalRec *tmpDigital;
branchRec *tmpBranch;
tmpBranch = baseOfBranch;
while (tmpBranch != NULL) {
if (((1L << ((long)tmpBranch->element)) & digitals) != 0) {
tmpDigital = (digitalRec *)c_malloc(sizeof(digitalRec));
tmpDigital->branch = tmpBranch;
tmpDigital->next = baseOfDigital;
baseOfDigital = tmpDigital;
}
tmpBranch = tmpBranch->next;
}
}
void SetUpDigital()
{
digitalRec *tmpDigital;
tmpDigital = baseOfDigital;
while (tmpDigital != NULL) {
switch (tmpDigital->branch->element) {
case delay:
SetUpDelay(&tmpDigital);
break;
case multiplier:
SetUpMult(&tmpDigital);
break;
}
tmpDigital = tmpDigital->next;
}
}
void RunDigital()
{
digitalRec *tmpN;
tmpN = baseOfDigital;
while (tmpN != NULL) {
switch (tmpN->branch->element) {
case delay:
RunDelay(&tmpN);
break;
case multiplier:
RunMult(&tmpN);
break;
}
tmpN = tmpN->next;
}
}
/***********************************************************/
/************* LOGIC ELEMENTS ******************************/
void readLogical(l)
char *l;
{
/*$YYYY n_out n_0 n_1 .. n_M <table_name> <0|1> <v_th> <v_low> <v_high>*/
long i, bn, n_out, nn;
iArray n_in;
branchRec *b;
aWord tmp, TEMP;
long FORLIM;
long position;
long symbol_count;
/* figure out where the '1' or '0' is. */
/* minimum position for this is position 5. An inverter */
for (position = 6; position < rcard.word_count; position++) {
if ((strcmp(rcard.WORD[position-1],"1") == 0)
|| (strcmp(rcard.WORD[position-1],"0") == 0)
|| (strcmp(rcard.WORD[position-1],"H") == 0)
|| (strcmp(rcard.WORD[position-1],"L") == 0))
break;
}
if (position >= rcard.word_count)
errorReport(ERROR_LOGIC_CARD_BROKEN,0,ERR_VOID,0);
GetWORD(tmp,1L);
b = (branchRec *)c_malloc(sizeof(branchRec));
strcpy(b->name,tmp);
b->element = l_general;
bn = branchID();
n_out = nodeID(GetWORD(TEMP,2L));
nn = 1;
GetWORD(tmp,nn + 2);
while (nn <= (position - 4)) {
n_in[nn - 1] = nodeID(tmp);
nn++;
GetWORD(tmp,nn + 2);
}
strcpy(b->cname,tmp);
/*bn, n_out, GND, nn-1 input nodes -> nn+2 nodes*/
MakeIDList(&b->ID, nn + 2);
b->ID.UU.n[0] = bn;
b->ID.UU.n[1] = n_out;
b->ID.UU.n[2] = 0;
FORLIM = b->ID.dim;
for (i = 4; i <= FORLIM; i++)
b->ID.UU.n[i - 1] = n_in[i - 4];
MakeValueList(&b->value, 4L);
GetWORD(TEMP,nn + 3);
if ((TEMP[0] == 'H') || (TEMP[0] == '1'))
b->value.UU.x[0] = 1.0;
else
b->value.UU.x[0] = 0.0;
symbol_count = 0;
for (i = 2; i <= 4; i++) {
GetWORD(TEMP,nn + i + 2 + symbol_count);
if (isalpha(TEMP[0]))
b->value.UU.x[i - 1] = parseSymbol(&b,i - 1,nn + i + 2 + symbol_count++);
else
b->value.UU.x[i - 1] = gck_atod(GetWORD(TEMP,nn + i + 2 + symbol_count));
}
b->next = baseOfBranch;
baseOfBranch = b;
}
void readTable(f, firstLine)
FILE **f;
char *firstLine;
{
/*.TABLE <table_name>
01..11
11..01
.
.
.END*/
card l;
aWord tmp;
nameString tmpName;
tableRec *tmpTable;
iArray tmpEntry;
long i, j, r, FORLIM;
strcpy(l,firstLine);
GetWORD(tmp,2L);
strcpy(tmpName,tmp);
tmpTable = baseOfTable;
while (tmpTable != NULL) {
if (strcmp(tmpTable->name, tmpName) == 0)
errorReport(ERROR_DUPLICATE_TABLE, tmpName, ERR_VOID, 0);
else
tmpTable = tmpTable->next;
}
tmpTable = NULL;
tmpTable = (tableRec *)c_malloc(sizeof(tableRec));
tmpTable->next = baseOfTable;
baseOfTable = tmpTable;
strcpy(baseOfTable->name,tmpName);
readCard(f, l);
GetWORD(tmp,1L);
i = 0;
while (strncmp(tmp,".END",4) != 0) {
i++;
j = 1;
r = 0;
while (tmp[j - 1] != NULL_CHAR) {
if (tmp[j - 1] == '1')
r += binaryArray[j - 1];
j++;
}
tmpEntry[i - 1] = r;
readCard(f, l);
GetWORD(tmp,1L);
}
baseOfTable->data.dim = i;
baseOfTable->data.UU.c = c_malloc(sizeof(long) * i);
FORLIM = baseOfTable->data.dim;
for (j = 0; j < FORLIM; j++)
baseOfTable->data.UU.n[j] = tmpEntry[j];
}
void GetTableByName(there, mname)
tableRec **there;
char *mname;
{
/*Finds the table with name mname in the linked list*/
boolean found;
*there = baseOfTable;
found = FALSE;
while (*there != NULL && !found) {
if (strcmp((*there)->name, mname) == 0)
found = TRUE;
else
*there = (*there)->next;
}
if (!found)
errorReport(ERROR_UNRESOLVED_TABLE, mname, ERR_VOID, 0);
}
void MakeLogicalList()
{
logicRec *tmpLogical;
branchRec *tmpBranch;
tableRec *tmpTable;
long bn;
long counter;
tmpBranch = baseOfBranch;
while (tmpBranch != NULL) {
if (((1L << ((long)tmpBranch->element)) & logicals) != 0) {
tmpLogical = (logicRec *)c_malloc(sizeof(logicRec));
tmpLogical->branch = tmpBranch;
bn = GetID(tmpLogical->branch->ID, 1L);
/*if (var_vector_s[bn] == NULL)
var_vector_s[bn] = (double *)c_malloc(sizeof(double)); */
/* changed dramatically */
if (bn > NoOfVars)
errorReport(ERROR_LOGICAL_LIST_COMPILER_ERROR,0,ERR_VOID,0);
tmpLogical->out = &vv_s[bn];
GetTableByName(&tmpTable, tmpBranch->cname);
tmpLogical->truthTable = tmpTable->data;
if (tmpBranch->value.UU.x[0] != 0)
tmpLogical->default_out = TRUE;
else
tmpLogical->default_out = FALSE;
/* update symbols */
for (counter = 1; counter <= 3; counter++)
if (tmpBranch->value.sv[counter].is_symbol)
tmpBranch->value.UU.x[counter] = getSymbolValueByName(tmpBranch->value.sv[counter].sName);
tmpLogical->next = baseOfLogic;
baseOfLogic = tmpLogical;
}
tmpBranch = tmpBranch->next;
}
}
void RunLogical()
{
logicRec *tmpL;
long i, inSig;
double vth, vout;
boolean done;
long FORLIM;
tmpL = baseOfLogic;
while (tmpL != NULL) {
inSig = 0;
vth = tmpL->branch->value.UU.x[1];
FORLIM = tmpL->branch->ID.dim;
for (i = 4; i <= FORLIM; i++) {
/* if (*var_vector_x[tmpL->branch->ID.UU.n[i - 1]] > vth) */
if (vv_x[tmpL->branch->ID.UU.n[i - 1]] > vth)
inSig += binaryArray[i - 4];
}
if (tmpL->default_out)
vout = tmpL->branch->value.UU.x[2];
else
vout = tmpL->branch->value.UU.x[3];
i = 1;
done = FALSE;
while (i <= tmpL->truthTable.dim && !done) {
if (inSig == tmpL->truthTable.UU.n[i - 1]) {
done = TRUE;
if (tmpL->default_out)
vout = tmpL->branch->value.UU.x[3];
else
vout = tmpL->branch->value.UU.x[2];
}
i++;
}
*tmpL->out = vout;
tmpL = tmpL->next;
}
}
/************* Building of the system matrices ******************/
void SetUpCircuit()
{
branchRec *b;
dsymbol_base();
b = baseOfBranch;
while (b != NULL) {
if (b->element == subckt) {
substituteSubckt(&b);
}
expandSymbols(&b);
b = b->next;
}
b = baseOfBranch;
while (b != NULL) {
switch (b->element) {
case switch_:
SetUpClock(&b);
break;
case opamp:
case quantizer:
SetUpModel(&b);
break;
}
b = b->next;
}
/* update symbols for step, period, time */
if (deltaT_sv.is_symbol)
deltaT = getSymbolValueByName(deltaT_sv.sName);
if (periodT_sv.is_symbol)
periodT = getSymbolValueByName(periodT_sv.sName);
if (lastTime_sv.is_symbol)
lastTime = getSymbolValueByName(lastTime_sv.sName);
if (periodT > 0)
deltaT = periodT / NoOfTicks;
}
char *componentType_NAMES[] = {
"RESISTOR", "CAPACITOR", "INDUCTOR", "SWITCH", "VS", "CS",
"COUPLEDINDUCTOR", "VCSW", "VCVS", "VCCS", "CCVS", "CCCS", "OPAMP",
"COMPARATOR", "QUANTIZER", "SUBCKT", "DELAY", "ADDER", "MULTIPLIER",
"L_GENERAL"
} ;
/* RdH Prototype for Diagnostic Changed, due to new memory management
* system for M, N, and B....It appears this is just debug code anyways.
*/
void Diagnostic()
/* double (*M)[], (*N)[], (*B)[]; */
{
long i, j;
/* RdH ... Due to case insensitivity, the variable b: branchPtr is replaced
with bptr...removes collisions! */
branchRec *bptr;
float v;
long FORLIM, FORLIM1;
fprintf(stderr,"M = \n");
FORLIM = NoOfVars;
for (i = 0; i < FORLIM; i++) {
FORLIM1 = NoOfVars;
for (j = 0; j < FORLIM1; j++) {
v = M[i][j];
if (v != (double) 0.0) /* RdH */
fprintf(stderr,"% .5E%c", v, TAB_CHAR);
}
fprintf(stderr,"\n");
}
fprintf(stderr,"\nN = \n");
FORLIM = NoOfVars;
for (i = 0; i < FORLIM; i++) {
FORLIM1 = NoOfVars;
for (j = 0; j < FORLIM1; j++) {
v = N[i][j];
if (v != (double) 0.0) /* RdH */
fprintf(stderr,"% .5E%c", v, TAB_CHAR);
}
fprintf(stderr,"\n");
}
fprintf(stderr,"\nB = \n");
FORLIM = NoOfVars;
for (i = 0; i < FORLIM; i++) {
FORLIM1 = NoOfVars;
for (j = 0; j < FORLIM1; j++) {
v = B[i][j];
if (v != (double) 0.0) /* RdH */
fprintf(stderr,"% .5E%c", v, TAB_CHAR);
}
fprintf(stderr,"\n");
}
bptr = baseOfBranch;
while (bptr != NULL) {
fprintf(stderr,"Branch : %.8s\n", bptr->name);
fprintf(stderr," Type : %s\n", componentType_NAMES[(long)bptr->element]);
fprintf(stderr," Branch no: %12ld\n", GetID(bptr->ID, 1L));
fprintf(stderr," Pos. node: %12ld\n", GetID(bptr->ID, 2L));
fprintf(stderr," Neg. node: %12ld\n", GetID(bptr->ID, 3L));
bptr = bptr->next;
}
}
void SetUpVariables()
{
long i, FORLIM;
FORLIM = NoOfVars;
vv_x = (double *) c_malloc((NoOfVars + 1) * sizeof(double));
for (i = 1; i <= FORLIM; i++) {
vv_x[i] = 0.0;
}
vv_x[0] = *GND;
}
void RunSystem(ps)
systemRec **ps;
{
long i, j;
/* sysVector y; 1 Mar 92 RdH */
double *y;
double N_i_j, B_i_j;
long FORLIM, FORLIM1;
y = (double *) c_malloc(NoOfVars * sizeof(double));
FORLIM = NoOfVars;
for (i = 0; i < FORLIM; i++) {
y[i] = 0.0;
FORLIM1 = NoOfVars;
for (j = 0; j < FORLIM1; j++) {
N_i_j = (*ps)->N[i][j];
if (N_i_j != 0)
y[i] += N_i_j * vv_x[j + 1];
}
FORLIM1 = NoOfVars;
for (j = 0; j < FORLIM1; j++) {
B_i_j = (*ps)->B[i][j];
if (B_i_j != 0)
y[i] += B_i_j * vv_s[j + 1];
}
}
FORLIM = NoOfVars;
for (i = 1; i <= FORLIM; i++)
vv_x[i] = y[i - 1];
free(y); /* RdH 1 Mar 92 */
}
/***** Reading the input file *****/
void readInputFile()
{
card l;
aWord tmp;
strcpy(tmp,rfile.filename);
strcat(tmp,".gck");
object_stamp = FileAge(tmp);
if (object_stamp == 0)
up_to_date = FALSE;
if (FileAge(rfile.filename) > object_stamp)
up_to_date = FALSE;
do {
do {
readCard(&(rfile.filePtr[rfile.depth]), l);
GetWORD(tmp,1L);
switch (tmp[0]) {
case 'C': readCapacitor(l); break;
case 'L': readInductor(l); break;
case 'R': readResistor(l); break;
case 'O': readOpamp(l); break;
case 'Q': readQuantizer(l); break;
case 'S': readSwitch(l); break;
case 'V':
case 'I':
readSource(l);
break;
case 'E': readVCVS(l); break;
case 'G': readVCCS(l); break;
case 'H': readCCVS(l); break;
case 'F': readCCCS(l); break;
case 'X': readXCard(l); break;
case '@': readDigital(l); break;
case '$': readLogical(l); break;
case '.':
if ((strncmp(tmp,".LIB",4) == 0) || (strncmp(tmp,".INC",4) == 0))
readLibrary();
else if ((strncmp(tmp,".DEF",4) == 0) || (strncmp(tmp,".SYM",4) == 0))
readSymbolDef();
else if (strncmp(tmp,".CLOCK",6) == 0)
readClock(l);
else if (strncmp(tmp,".NODE",5) == 0)
readNode(l);
else if (strncmp(tmp,".MODEL",6) == 0)
readModelSection(&(rfile.filePtr[rfile.depth]), l);
else if (strncmp(tmp,".SUBCKT",7) == 0)
openSubckt(l);
else if (strncmp(tmp,".ENDSUB",7) == 0)
closeSubckt(l);
else if (strncmp(tmp,".PRINT",6) == 0)
readPrint(l);
else if (strncmp(tmp,".LPRINT",7) == 0) {
shortPrint = FALSE;
readPrint(l);
} else if (strncmp(tmp,".NPRINT",7) == 0) {
shortPrint = TRUE;
timePrint = FALSE;
readPrint(l);
} else if (strncmp(tmp,".NLPRINT",8) == 0) {
shortPrint = FALSE;
timePrint = FALSE;
readPrint(l);
} else if (strncmp(tmp,".FFT",4) == 0) {
readFFT();
} else if (strncmp(tmp,".TIME",5) == 0)
readTime(l);
else if (strncmp(tmp,".SAMPLE",7) == 0)
readSample(l);
else if (strncmp(tmp,".STEP",5) == 0)
readTimeStep(l);
else if (strncmp(tmp,".PERIOD",7) == 0)
readClockPeriod(l);
else if (strncmp(tmp,".TABLE",6) == 0)
readTable(&(rfile.filePtr[rfile.depth]), l);
else if (strncmp(tmp,".DIAGNOSE",9) == 0) {
runDiag = TRUE;
}
break;
case '*':
case '#':
/* blank case */
break;
}
} while (!P_eof(rfile.filePtr[rfile.depth]));
fclose(rfile.filePtr[rfile.depth]);
if (rfile.depth >= 0)
rfile.depth--;
} while (rfile.depth >= 0);
}
void exit_now()
{
/* place handlers for closing all possibly open files */
exit(EXIT_SUCCESS);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.