3 changed files with 793 additions and 0 deletions
@ -0,0 +1,426 @@ |
|||||
|
/* Spice hooks */ |
||||
|
#include <ngspice.h> |
||||
|
#ifdef CLUSTER |
||||
|
#include <inpdefs.h> |
||||
|
#include "cluster.h" |
||||
|
#include <cktdefs.h> |
||||
|
#include <gendefs.h> |
||||
|
|
||||
|
/* Misc stuff */ |
||||
|
#include <pthread.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
/*Network stuff*/ |
||||
|
#include <arpa/inet.h> |
||||
|
#include <netinet/in.h> |
||||
|
#include <sys/socket.h> |
||||
|
#include <netdb.h> |
||||
|
#include <unistd.h> |
||||
|
|
||||
|
|
||||
|
struct input_pipe { |
||||
|
/*the names of the local and remote nodes*/ |
||||
|
char remote[32]; |
||||
|
char local[32]; |
||||
|
int fd; |
||||
|
FILE *stream; |
||||
|
/* the data recieved */ |
||||
|
double time; |
||||
|
double data; |
||||
|
/*resistance of this link*/ |
||||
|
double res; |
||||
|
/* The value controled */ |
||||
|
double *currentPtr; |
||||
|
/*The output it is linked to*/ |
||||
|
struct output_pipe *link; |
||||
|
struct input_pipe *next; |
||||
|
}; |
||||
|
|
||||
|
struct output_pipe { |
||||
|
int fd; |
||||
|
FILE *stream; |
||||
|
/*the names of the local and remote nodes*/ |
||||
|
char local[32]; |
||||
|
char remote[32]; |
||||
|
/* The index of the local node value in the ckt->CKTrhsOld array */ |
||||
|
int outIndex; |
||||
|
/*Last values sent*/ |
||||
|
double time,data; |
||||
|
struct input_pipe *link; |
||||
|
struct output_pipe *next; |
||||
|
}; |
||||
|
|
||||
|
static double lastTimeSent=0; |
||||
|
|
||||
|
static int time_sock=0; |
||||
|
static FILE *time_outfile=NULL; |
||||
|
static FILE *time_infile=NULL; |
||||
|
|
||||
|
static struct input_pipe* input_pipes=NULL; |
||||
|
static struct output_pipe* output_pipes=NULL; |
||||
|
|
||||
|
/* sets up deamon which waits for connections |
||||
|
*and sets up input pipes as it recieves them */ |
||||
|
static void *start_listener(void *); |
||||
|
|
||||
|
/* Setup the output pipes*/ |
||||
|
static int setup_output(CKTcircuit *ckt); |
||||
|
static int setup_input(CKTcircuit *ckt); |
||||
|
static int setup_time(); |
||||
|
|
||||
|
int CLUsetup(CKTcircuit *ckt){ |
||||
|
pthread_t tid; |
||||
|
struct input_pipe *curr; |
||||
|
int i, connections=0; |
||||
|
GENmodel *mod; |
||||
|
GENinstance *inst; |
||||
|
|
||||
|
/* count the number of connections expected */ |
||||
|
i = INPtypelook("Isource"); |
||||
|
for(mod = (GENmodel *)ckt->CKThead[i]; |
||||
|
mod != NULL; |
||||
|
mod = mod->GENnextModel) |
||||
|
for (inst = mod->GENinstances; |
||||
|
inst != NULL; |
||||
|
inst = inst->GENnextInstance) |
||||
|
if(strncmp("ipcx",inst->GENname,4) == 0) |
||||
|
connections++; |
||||
|
|
||||
|
/* allocate the input connections */ |
||||
|
for(i=0;i<connections;i++) { |
||||
|
curr = (struct input_pipe *)tmalloc(sizeof(struct input_pipe)); |
||||
|
if(input_pipes) |
||||
|
curr->next = input_pipes; |
||||
|
else |
||||
|
curr->next = NULL; |
||||
|
input_pipes = curr; |
||||
|
} |
||||
|
|
||||
|
pthread_create(&tid,NULL,start_listener,(void *)&connections); |
||||
|
setup_output(ckt); |
||||
|
pthread_join(tid,NULL); |
||||
|
setup_input(ckt); |
||||
|
setup_time(); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
#include "../devices/isrc/isrcdefs.h" |
||||
|
/*Connect to remote machine and find the data*/ |
||||
|
static int setup_output(CKTcircuit *ckt){ |
||||
|
int type; |
||||
|
GENmodel *mod; |
||||
|
GENinstance *inst; |
||||
|
char hostname[64]; |
||||
|
|
||||
|
lastTimeSent = 0; |
||||
|
type = INPtypelook("Isource"); |
||||
|
|
||||
|
for(mod = (GENmodel *)ckt->CKThead[type]; |
||||
|
mod != NULL; |
||||
|
mod = mod->GENnextModel) |
||||
|
|
||||
|
for (inst = mod->GENinstances; |
||||
|
inst != NULL; |
||||
|
inst = inst->GENnextInstance) |
||||
|
|
||||
|
if(strncmp("ipcx",inst->GENname,4) == 0){ |
||||
|
ISRCinstance *isrc = (ISRCinstance *)inst; |
||||
|
CKTnode *node; |
||||
|
struct output_pipe *curr; |
||||
|
struct sockaddr_in address; |
||||
|
struct hostent *host=NULL; |
||||
|
int sock,nodeNum,i; |
||||
|
|
||||
|
/*Create the struct*/ |
||||
|
curr = (struct output_pipe *)tmalloc(sizeof(struct output_pipe)); |
||||
|
if(output_pipes) |
||||
|
curr->next = output_pipes; |
||||
|
else |
||||
|
curr->next = NULL; |
||||
|
output_pipes = curr; |
||||
|
|
||||
|
/* The node names */ |
||||
|
strcpy(curr->local,CKTnodName(ckt,isrc->ISRCnegNode));/*weird*/ |
||||
|
strcpy(curr->remote,isrc->ISRCname); |
||||
|
|
||||
|
/* extract remote node number */ |
||||
|
nodeNum = /*Xcoord*/(curr->remote[4] - '0') * CLUSTER_WIDTH |
||||
|
+ /*Ycoord*/(curr->remote[9] - '0'); |
||||
|
sprintf(hostname,"n%d."DOMAIN_NAME,nodeNum); |
||||
|
|
||||
|
/* network stuff */ |
||||
|
host = gethostbyname(hostname); |
||||
|
if(!host){ |
||||
|
printf("Host not found in setup_output\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
||||
|
printf("Socket open in setup_output\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
address.sin_family = AF_INET; |
||||
|
address.sin_port = htons(PORT); |
||||
|
memcpy(&address.sin_addr,host->h_addr_list[0], |
||||
|
sizeof(address.sin_addr)); |
||||
|
|
||||
|
printf("connecting to %s ...... ",hostname); |
||||
|
fflush(stdout); |
||||
|
|
||||
|
while(connect(sock,(struct sockaddr *)&address,sizeof(address))){ |
||||
|
usleep(500);/*wait for the sever to start*/ |
||||
|
} |
||||
|
|
||||
|
printf("connected\n"); |
||||
|
|
||||
|
curr->fd = sock; |
||||
|
|
||||
|
/* send stuff */ |
||||
|
/* buffer */ |
||||
|
i = (strlen(curr->remote) + strlen(curr->local) + 2)*sizeof(char); |
||||
|
setsockopt(sock,SOL_SOCKET,SO_SNDBUF,&i,sizeof(i)); |
||||
|
|
||||
|
curr->stream = fdopen(curr->fd,"w"); |
||||
|
|
||||
|
fwrite(curr->remote,sizeof(char),strlen(curr->remote),curr->stream); |
||||
|
fputc('\0',curr->stream); |
||||
|
fwrite(curr->local,sizeof(char),strlen(curr->local),curr->stream); |
||||
|
fputc('\0',curr->stream); |
||||
|
fflush(curr->stream); |
||||
|
|
||||
|
/* buffer, what is done per time point */ |
||||
|
i = sizeof(double)*2; |
||||
|
setsockopt(sock,SOL_SOCKET,SO_SNDBUF,&i,sizeof(i)); |
||||
|
|
||||
|
/* find the index in ckt->rhsOld which contains the local node */ |
||||
|
i = 0; |
||||
|
for(node = ckt->CKTnodes->next;node;node = node->next){ |
||||
|
i++; |
||||
|
if(strcmp(node->name,curr->local)==0){ |
||||
|
curr->outIndex = i; |
||||
|
goto next; |
||||
|
} |
||||
|
} |
||||
|
printf("Local node %s not found\n",curr->local); |
||||
|
exit(0); |
||||
|
next: |
||||
|
|
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/*Processes the connections recieved by start_listener*/ |
||||
|
static int setup_input(CKTcircuit *ckt){ |
||||
|
int type; |
||||
|
GENmodel *mod; |
||||
|
GENinstance *inst; |
||||
|
struct input_pipe *input; |
||||
|
type = INPtypelook("Isource"); |
||||
|
|
||||
|
for(input = input_pipes;input;input = input->next){ |
||||
|
int i; |
||||
|
|
||||
|
input->stream = fdopen(input->fd,"r"); |
||||
|
|
||||
|
/*Get the local and remote node names*/ |
||||
|
i=0; |
||||
|
do { |
||||
|
while(fread(&input->local[i],sizeof(char),1,input->stream) != 1); |
||||
|
}while(input->local[i++] != '\0'); |
||||
|
|
||||
|
i=0; |
||||
|
do { |
||||
|
while(fread(&input->remote[i],sizeof(char),1,input->stream) != 1); |
||||
|
}while(input->remote[i++] != '\0'); |
||||
|
|
||||
|
/* initilise */ |
||||
|
input->time = -1; |
||||
|
|
||||
|
/*Find the Isource to control*/ |
||||
|
for(mod = (GENmodel *)ckt->CKThead[type]; |
||||
|
mod != NULL; |
||||
|
mod = mod->GENnextModel) |
||||
|
|
||||
|
for (inst = mod->GENinstances; |
||||
|
inst != NULL; |
||||
|
inst = inst->GENnextInstance) |
||||
|
|
||||
|
if(strcmp(input->remote,&inst->GENname[11]) == 0){ |
||||
|
|
||||
|
ISRCinstance *isrc = (ISRCinstance *)inst; |
||||
|
input->res = isrc->ISRCdcValue; |
||||
|
isrc->ISRCdcValue = 0; |
||||
|
input->currentPtr = &isrc->ISRCdcValue; |
||||
|
goto next; |
||||
|
} |
||||
|
/* We get here if no Isource matches */ |
||||
|
printf("Current source %s not found\n",input->remote); |
||||
|
exit(0); |
||||
|
|
||||
|
next: |
||||
|
|
||||
|
/* Now find the corresponding output */ |
||||
|
{ |
||||
|
struct output_pipe *output; |
||||
|
for(output = output_pipes;output;output = output->next) |
||||
|
if(strcmp(&input->local[11],output->local)==0){ |
||||
|
input->link = output; |
||||
|
output->link = input; |
||||
|
goto next2; |
||||
|
} |
||||
|
printf("Parent to %s not found\n",&input->local[11]); |
||||
|
exit(0); |
||||
|
next2: |
||||
|
} |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/* This starts a server and waits for connections, number given by argument*/ |
||||
|
static void *start_listener(void *v){ |
||||
|
int *connections = (int *)v; |
||||
|
int count=0; |
||||
|
struct sockaddr_in address; |
||||
|
int sock, conn,i; |
||||
|
size_t addrLength = sizeof(struct sockaddr_in); |
||||
|
struct input_pipe *curr; |
||||
|
|
||||
|
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
||||
|
printf("socket in start_listener\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
/* Allow reuse of the socket */ |
||||
|
i = 1; |
||||
|
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)); |
||||
|
|
||||
|
/* port, inferface ..*/ |
||||
|
address.sin_family = AF_INET; |
||||
|
address.sin_port = htons(PORT); |
||||
|
memset(&address.sin_addr,0,sizeof(address.sin_addr)); |
||||
|
|
||||
|
if(bind(sock, (struct sockaddr *)&address,sizeof(address))){ |
||||
|
printf("bind in start_listener\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
if(listen(sock,5)){ |
||||
|
printf("listen in start_listener\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
/* Loop till recieved all connections */ |
||||
|
curr = input_pipes; |
||||
|
while (count < *connections){ |
||||
|
if((conn = accept(sock, (struct sockaddr *)&address,&addrLength)) < 0){ |
||||
|
printf("accept in start_listener\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
curr->fd = conn; |
||||
|
/* will fill rest of structure later in setup_input*/ |
||||
|
count ++; |
||||
|
curr = curr->next; |
||||
|
} |
||||
|
|
||||
|
close(sock); |
||||
|
|
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
/*Writes data to remote computer*/ |
||||
|
int CLUoutput(CKTcircuit *ckt){ |
||||
|
struct output_pipe *output; |
||||
|
lastTimeSent = ckt->CKTtime; |
||||
|
for(output = output_pipes; |
||||
|
output; |
||||
|
output = output->next){ |
||||
|
output->time = ckt->CKTtime; |
||||
|
output->data = ckt->CKTrhsOld[output->outIndex]; |
||||
|
fwrite(&output->time,sizeof(double),1,output->stream); |
||||
|
fwrite(&output->data, |
||||
|
sizeof(double),1,output->stream); |
||||
|
fflush(output->stream); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/*Maniputates the local circuit based on the links*/ |
||||
|
int CLUinput(CKTcircuit *ckt){ |
||||
|
struct input_pipe *input; |
||||
|
double tmp; |
||||
|
for(input= input_pipes;input;input = input->next){ |
||||
|
/*recieve data till we get a good time point*/ |
||||
|
while (input->time < lastTimeSent){ |
||||
|
while(fread(&input->time, sizeof(double), 1, input->stream) != 1){} |
||||
|
while(fread(&input->data, sizeof(double), 1, input->stream) != 1){} |
||||
|
} |
||||
|
tmp = (input->link->data - input->data) / input->res; |
||||
|
|
||||
|
/*dampen out large currents*/ |
||||
|
if(tmp > 0) |
||||
|
*input->currentPtr = 0.2 * (1 - exp(-tmp/0.2)); |
||||
|
else |
||||
|
*input->currentPtr = -0.2 * (1 - exp(tmp/0.2)); |
||||
|
|
||||
|
/*GND is the posNode, local node is the negNode*/ |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
static int setup_time(){ |
||||
|
struct sockaddr_in address; |
||||
|
struct hostent *host=NULL; |
||||
|
char *hostname = TIME_HOST; |
||||
|
int sock,i; |
||||
|
|
||||
|
/* network stuff */ |
||||
|
host = gethostbyname(hostname); |
||||
|
if(!host){ |
||||
|
printf("Host not found in setup_time\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
||||
|
printf("Socket open in setup_time\n"); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
i = sizeof(double)*2; |
||||
|
setsockopt(sock,SOL_SOCKET,SO_SNDBUF ,&i,sizeof(i)); |
||||
|
|
||||
|
address.sin_family = AF_INET; |
||||
|
address.sin_port = htons(TIME_PORT); |
||||
|
memcpy(&address.sin_addr,host->h_addr_list[0], |
||||
|
sizeof(address.sin_addr)); |
||||
|
|
||||
|
|
||||
|
while(connect(sock,(struct sockaddr *)&address,sizeof(address))){ |
||||
|
usleep(500);/*wait for the sever to start*/ |
||||
|
} |
||||
|
time_sock=sock; |
||||
|
time_outfile=fdopen(sock,"w"); |
||||
|
time_infile=fdopen(sock,"r"); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int CLUsync(double time,double *delta, int error){ |
||||
|
double tmp; |
||||
|
if(error) |
||||
|
tmp = *delta * (-1); |
||||
|
else |
||||
|
tmp = *delta; |
||||
|
fwrite(&time,sizeof(double),1,time_outfile); |
||||
|
fwrite(&tmp,sizeof(double),1,time_outfile); |
||||
|
fflush(time_outfile); |
||||
|
while(fread(&tmp,sizeof(double),1,time_infile) != 1); |
||||
|
if(tmp < 0){ |
||||
|
*delta = -tmp; |
||||
|
return 0; |
||||
|
} else { |
||||
|
*delta = tmp; |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
@ -0,0 +1,131 @@ |
|||||
|
/********** |
||||
|
Copyright 1992 Regents of the University of California. All rights |
||||
|
reserved. |
||||
|
Author: 1992 Charles Hough |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
#include <stdio.h> |
||||
|
#include "ifsim.h" |
||||
|
#include "inpdefs.h" |
||||
|
#include "inpmacs.h" |
||||
|
#include "fteext.h" |
||||
|
#include "inp.h" |
||||
|
|
||||
|
void |
||||
|
INP2P(ckt,tab,current) |
||||
|
void *ckt; |
||||
|
INPtables *tab; |
||||
|
card *current; |
||||
|
|
||||
|
{ |
||||
|
|
||||
|
int mytype; /* the type we determine cpls are */ |
||||
|
int type; /* the type the model says it is */ |
||||
|
char *line; /* the part of the current line left to parse */ |
||||
|
char *name, *tempname; /* the cpl's name */ |
||||
|
char *model; /* the name of the cpl's model */ |
||||
|
char **nname1; /* the first node's name */ |
||||
|
char **nname2; /* the second node's name */ |
||||
|
char *ground; |
||||
|
void **node1; /* the first node's node pointer */ |
||||
|
void **node2; /* the second node's node pointer */ |
||||
|
void *groundnode; |
||||
|
int error; /* error code temporary */ |
||||
|
int error1; /* secondary error code temporary */ |
||||
|
INPmodel *thismodel; /* pointer to model structure describing our model */ |
||||
|
void *mdfast; /* pointer to the actual model */ |
||||
|
void *fast; /* pointer to the actual instance */ |
||||
|
IFvalue ptemp; /* a value structure to package cpl into */ |
||||
|
IFuid uid; /* uid for default model */ |
||||
|
double lenval = 0; |
||||
|
int lenvalgiven = 0; |
||||
|
int num, i; |
||||
|
|
||||
|
mytype = INPtypelook("CplLines"); |
||||
|
if(mytype < 0 ) { |
||||
|
LITERR("Device type CplLines not supported by this binary\n") |
||||
|
return; |
||||
|
} |
||||
|
line = current->line; |
||||
|
INPgetTok(&line,&name,1); |
||||
|
INPinsert(&name,tab); |
||||
|
/* num = (int) INPevaluate(&line,&error1,1); */ |
||||
|
num = 0; |
||||
|
|
||||
|
/* first pass to determine the dimension */ |
||||
|
while (*line != '\0') { |
||||
|
INPgetTok(&line, &tempname,1); |
||||
|
if (strcmp(tempname, "len") == 0) break; |
||||
|
num ++; |
||||
|
} |
||||
|
num = (num - 2) / 2; |
||||
|
line = current->line; |
||||
|
INPgetTok(&line,&name,1); |
||||
|
|
||||
|
nname1 = (char **) malloc(num * sizeof(char *)); |
||||
|
nname2 = (char **) malloc(num * sizeof(char *)); |
||||
|
node1 = (void **) malloc(num * sizeof(void *)); |
||||
|
node2 = (void **) malloc(num * sizeof(void *)); |
||||
|
|
||||
|
|
||||
|
for (i = 0; i < num; i++) { |
||||
|
INPgetNetTok(&line,&(nname1[i]),1); |
||||
|
INPtermInsert(ckt,&(nname1[i]),tab,&(node1[i])); |
||||
|
} |
||||
|
INPgetTok(&line,&ground,1); |
||||
|
INPtermInsert(ckt,&ground,tab,&groundnode); |
||||
|
for (i = 0; i < num; i++) { |
||||
|
INPgetNetTok(&line,&(nname2[i]),1); |
||||
|
INPtermInsert(ckt,&(nname2[i]),tab,&(node2[i])); |
||||
|
} |
||||
|
INPgetTok(&line,&ground,1); |
||||
|
INPtermInsert(ckt,&ground,tab,&groundnode); |
||||
|
|
||||
|
INPgetTok(&line,&model,1); |
||||
|
if (strcmp(model, "len") == 0) { |
||||
|
lenval = INPevaluate(&line,&error1,1); |
||||
|
lenvalgiven = 1; |
||||
|
INPgetTok(&line,&model,1); |
||||
|
} |
||||
|
if(*model) { /* token isn't null */ |
||||
|
INPinsert(&model,tab); |
||||
|
thismodel = (INPmodel *)NULL; |
||||
|
current->error = INPgetMod(ckt,model,&thismodel,tab); |
||||
|
if(thismodel != NULL) { |
||||
|
if(mytype != thismodel->INPmodType) { |
||||
|
LITERR("incorrect model type") |
||||
|
return; |
||||
|
} |
||||
|
mdfast = thismodel->INPmodfast; |
||||
|
type = thismodel->INPmodType; |
||||
|
} else { |
||||
|
type = mytype; |
||||
|
if(!tab->defPmod) { |
||||
|
/* create default P model */ |
||||
|
IFnewUid(ckt,&uid,(IFuid)NULL,"P",UID_MODEL,(void**)NULL); |
||||
|
IFC(newModel, (ckt,type,&(tab->defPmod),uid)) |
||||
|
} |
||||
|
mdfast = tab->defPmod; |
||||
|
} |
||||
|
IFC(newInstance,(ckt,mdfast,&fast,name)) |
||||
|
} else { |
||||
|
LITERR("model name is not found") |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/* IFC(bindNode,(ckt,fast,1,fakename)) */ |
||||
|
|
||||
|
ptemp.iValue = num; |
||||
|
GCA(INPpName,("dimension", &ptemp,ckt,type,fast)) |
||||
|
ptemp.v.vec.sVec = nname1; |
||||
|
GCA(INPpName,("pos_nodes", &ptemp,ckt,type,fast)) |
||||
|
ptemp.v.vec.sVec = nname2; |
||||
|
GCA(INPpName,("neg_nodes", &ptemp,ckt,type,fast)) |
||||
|
if (error1 == 0 && lenvalgiven) { |
||||
|
ptemp.rValue = lenval; |
||||
|
GCA(INPpName,("length",&ptemp,ckt,type,fast)) |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
@ -0,0 +1,236 @@ |
|||||
|
/********** |
||||
|
Copyright 1992 Regents of the University of California. All rights |
||||
|
reserved. |
||||
|
Author: 1992 Charles Hough |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
#include <stdio.h> |
||||
|
#include "ifsim.h" |
||||
|
#include "inpdefs.h" |
||||
|
#include "inpmacs.h" |
||||
|
#include "fteext.h" |
||||
|
#include "inp.h" |
||||
|
|
||||
|
void |
||||
|
INP2Y(ckt,tab,current) |
||||
|
void *ckt; |
||||
|
INPtables *tab; |
||||
|
card *current; |
||||
|
|
||||
|
{ |
||||
|
/* parse a txl card */ |
||||
|
/* Yxxxx node1 node2 name */ |
||||
|
|
||||
|
int mytype; /* the type to determine txl */ |
||||
|
int mytype2; /* the type to determine cpl */ |
||||
|
int type; /* the type the model says it is */ |
||||
|
char *line; /* the part of the current line left to parse */ |
||||
|
char *name; /* the resistor's name */ |
||||
|
char *buf; /* temporary buffer for parsing */ |
||||
|
char *model; /* the name of the resistor's model */ |
||||
|
char *nname1; /* the first node's name */ |
||||
|
char *nname2; /* the second node's name */ |
||||
|
char rname1[10], rname2[10], rname3[10]; |
||||
|
char cname1[10], cname2[10], cname3[10], cname4[10]; |
||||
|
char *internal1, *internal2; |
||||
|
char *ground1, *ground2; |
||||
|
void *node1; /* the first node's node pointer */ |
||||
|
void *node2; /* the second node's node pointer */ |
||||
|
void *gnode1, *gnode2, *inode1, *inode2; |
||||
|
int error; /* error code temporary */ |
||||
|
int error1; /* secondary error code temporary */ |
||||
|
INPmodel *thismodel; /* pointer to model structure describing our model */ |
||||
|
void *mdfast; /* pointer to the actual model */ |
||||
|
void *fast; /* pointer to the actual instance */ |
||||
|
void *mdfast2, *mdfast3, *mdfast4, *mdfast5, *mdfast6; |
||||
|
void *fast2, *fast3, *fast4, *fast5, *fast6; |
||||
|
IFuid uid; /* uid for default model */ |
||||
|
GENinstance *txl; |
||||
|
IFvalue ptemp; /* a value structure to package into */ |
||||
|
double lval=0, rval=0, cval=0, lenval=0; |
||||
|
int lenvalgiven = 0; |
||||
|
|
||||
|
mytype = INPtypelook("TransLine"); |
||||
|
mytype2 = INPtypelook("CplLines"); |
||||
|
|
||||
|
if(mytype < 0 ) { |
||||
|
LITERR("Device type TransLine not supported by this binary\n") |
||||
|
return; |
||||
|
} |
||||
|
line = current->line; |
||||
|
INPgetTok(&line,&name,1); |
||||
|
INPinsert(&name,tab); |
||||
|
INPgetNetTok(&line,&nname1,1); |
||||
|
INPtermInsert(ckt,&nname1,tab,&node1); |
||||
|
INPgetNetTok(&line,&ground1,1); |
||||
|
INPtermInsert(ckt,&ground1,tab,&gnode1); |
||||
|
INPgetNetTok(&line,&nname2,1); |
||||
|
INPtermInsert(ckt,&nname2,tab,&node2); |
||||
|
INPgetNetTok(&line,&ground2,1); |
||||
|
INPtermInsert(ckt,&ground2,tab,&gnode2); |
||||
|
|
||||
|
INPgetTok(&line,&model,1); |
||||
|
if (strcmp(model, "len") == 0) { |
||||
|
lenval = INPevaluate(&line,&error1,1); |
||||
|
lenvalgiven = 1; |
||||
|
INPgetTok(&line,&model,1); |
||||
|
} |
||||
|
if(*model) { /* token isn't null */ |
||||
|
INPinsert(&model,tab); |
||||
|
thismodel = (INPmodel *)NULL; |
||||
|
current->error = INPgetMod(ckt,model,&thismodel,tab); |
||||
|
if(thismodel != NULL) { |
||||
|
if (thismodel->INPmodType == mytype2) { |
||||
|
INP2P(ckt,tab,current); |
||||
|
return; |
||||
|
} |
||||
|
else if (mytype != thismodel->INPmodType) { |
||||
|
LITERR("incorrect model type") |
||||
|
return; |
||||
|
} |
||||
|
line = thismodel->INPmodLine->line; |
||||
|
INPgetTok(&line,&buf,1); /* throw out .model */ |
||||
|
INPgetTok(&line,&buf,1); /* throw out model name */ |
||||
|
INPgetTok(&line,&buf,1); /* throw out txl */ |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
while (*line != '\0') { |
||||
|
if (*buf == 'R' || *buf == 'r') { |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
rval = atof(buf); |
||||
|
} |
||||
|
if ((strcmp(buf,"L") == 0) || (strcmp(buf,"l") == 0)) { |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
lval = atof(buf); |
||||
|
} |
||||
|
if ((strcmp(buf,"C") == 0) || (strcmp(buf,"c") == 0)) { |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
cval = atof(buf); |
||||
|
} |
||||
|
if (lenvalgiven == 0) { |
||||
|
if (strcmp(buf,"length")== 0) { |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
lenval = atof(buf); |
||||
|
} |
||||
|
} |
||||
|
INPgetTok(&line,&buf,1); |
||||
|
} |
||||
|
if (lenval && rval && lval && rval/lval > 1.6e10) { |
||||
|
/* use 3-pi model */ |
||||
|
rval = 3.0 / (rval * lenval); |
||||
|
cval = cval * lenval / 6.0; |
||||
|
|
||||
|
type = INPtypelook("Resistor"); |
||||
|
|
||||
|
/* resistor between node1 and internal1 */ |
||||
|
internal1 = (char *) malloc (10); |
||||
|
strcpy(internal1, "txlnd1"); |
||||
|
INPtermInsert(ckt, &internal1, tab, &inode1); |
||||
|
if(!tab->defRmod) { |
||||
|
/* create default R model */ |
||||
|
IFnewUid(ckt,&uid,(IFuid)NULL,"R",UID_MODEL,(void**)NULL); |
||||
|
IFC(newModel, (ckt,type,&(tab->defRmod),uid)) |
||||
|
} |
||||
|
mdfast = tab->defRmod; |
||||
|
strcpy(rname1, "txlres1"); |
||||
|
IFC(newInstance,(ckt,mdfast,&fast,rname1)) |
||||
|
IFC(bindNode,(ckt,fast,1,node1)) |
||||
|
IFC(bindNode,(ckt,fast,2,inode1)) |
||||
|
ptemp.rValue = rval; |
||||
|
GCA(INPpName,("resistance",&ptemp,ckt,type,fast)) |
||||
|
|
||||
|
/* resistor between internal1 and internal2 */ |
||||
|
internal2 = (char *) malloc (10); |
||||
|
strcpy(internal2, "txlnd2"); |
||||
|
INPtermInsert(ckt, &internal2, tab, &inode2); |
||||
|
strcpy(rname2, "txlres2"); |
||||
|
mdfast2 = tab->defRmod; |
||||
|
IFC(newInstance,(ckt,mdfast2,&fast2,rname2)) |
||||
|
IFC(bindNode,(ckt,fast2,1,inode1)) |
||||
|
IFC(bindNode,(ckt,fast2,2,inode2)) |
||||
|
ptemp.rValue = rval; |
||||
|
GCA(INPpName,("resistance",&ptemp,ckt,type,fast2)) |
||||
|
|
||||
|
/* resistor between internal2 and node2 */ |
||||
|
strcpy(rname3, "txlres3"); |
||||
|
mdfast3 = tab->defRmod; |
||||
|
IFC(newInstance,(ckt,mdfast3,&fast3,rname3)) |
||||
|
IFC(bindNode,(ckt,fast3,1,inode2)) |
||||
|
IFC(bindNode,(ckt,fast3,2,node2)) |
||||
|
ptemp.rValue = rval; |
||||
|
GCA(INPpName,("resistance",&ptemp,ckt,type,fast3)) |
||||
|
|
||||
|
/* capacitor on node1 */ |
||||
|
type = INPtypelook("Capacitor"); |
||||
|
if(!tab->defCmod) { |
||||
|
IFnewUid(ckt,&uid,(IFuid)NULL,"C",UID_MODEL,(void**)NULL); |
||||
|
IFC(newModel,(ckt,type,&(tab->defCmod),uid)) |
||||
|
} |
||||
|
mdfast4 = tab->defCmod; |
||||
|
strcpy(cname1, "txlcap1"); |
||||
|
IFC(newInstance,(ckt,mdfast4,&fast4,cname1)) |
||||
|
IFC(bindNode,(ckt,fast4,1,node1)) |
||||
|
IFC(bindNode,(ckt,fast4,2,gnode1)) |
||||
|
ptemp.rValue = cval; |
||||
|
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) |
||||
|
|
||||
|
/* capacitor on internal1 */ |
||||
|
strcpy(cname2, "txlcap2"); |
||||
|
mdfast4 = tab->defCmod; |
||||
|
IFC(newInstance,(ckt,mdfast4,&fast4,cname2)) |
||||
|
IFC(bindNode,(ckt,fast4,1,inode1)) |
||||
|
IFC(bindNode,(ckt,fast4,2,gnode1)) |
||||
|
ptemp.rValue = cval * 2; |
||||
|
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) |
||||
|
|
||||
|
/* capacitor on internal2 */ |
||||
|
strcpy(cname3, "txlcap3"); |
||||
|
mdfast5 = tab->defCmod; |
||||
|
IFC(newInstance,(ckt,mdfast5,&fast5,cname3)) |
||||
|
IFC(bindNode,(ckt,fast5,1,inode2)) |
||||
|
IFC(bindNode,(ckt,fast5,2,gnode1)) |
||||
|
ptemp.rValue = cval * 2; |
||||
|
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast5)) |
||||
|
|
||||
|
/* capacitor on node2 */ |
||||
|
strcpy(cname4, "txlcap4"); |
||||
|
mdfast6 = tab->defCmod; |
||||
|
IFC(newInstance,(ckt,mdfast6,&fast6,cname4)) |
||||
|
IFC(bindNode,(ckt,fast6,1,node2)) |
||||
|
IFC(bindNode,(ckt,fast6,2,gnode1)) |
||||
|
ptemp.rValue = cval; |
||||
|
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast6)) |
||||
|
return; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* use regular txl model */ |
||||
|
mdfast = thismodel->INPmodfast; |
||||
|
type = thismodel->INPmodType; |
||||
|
} else { |
||||
|
type = mytype; |
||||
|
if(!tab->defYmod) { |
||||
|
/* create default Y model */ |
||||
|
IFnewUid(ckt,&uid,(IFuid)NULL,"Y",UID_MODEL,(void**)NULL); |
||||
|
IFC(newModel, (ckt,type,&(tab->defYmod),uid)) |
||||
|
} |
||||
|
mdfast = tab->defYmod; |
||||
|
} |
||||
|
IFC(newInstance,(ckt,mdfast,&fast,name)) |
||||
|
} else { |
||||
|
LITERR("model name is not found") |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (error1 == 0 && lenvalgiven) { |
||||
|
ptemp.rValue = lenval; |
||||
|
GCA(INPpName,("length",&ptemp,ckt,type,fast)) |
||||
|
} |
||||
|
|
||||
|
IFC(bindNode,(ckt,fast,1,node1)) |
||||
|
IFC(bindNode,(ckt,fast,2,node2)) |
||||
|
|
||||
|
txl = (GENinstance *)fast; |
||||
|
|
||||
|
return; |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue