Corrected a long-standing error in which ending text with a literal
[xcircuit.git] / spiceparser / netlist_spice.c
blob4d15f7734bf1e8bfbaa0cfbb3310721dc6fee78c
1 /********************
2 This file is part of the software library CADLIB written by Conrad Ziesler
3 Copyright 2003, Conrad Ziesler, all rights reserved.
5 *************************
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 ******************/
21 /* spice.c: read hierachical spice deck composed of M and C and X
23 Conrad Ziesler
27 #include <math.h>
28 #include <ctype.h>
29 #include <stdio.h>
30 #include "debug.h"
32 /* The following is copied from xcircuit.h */
33 #ifdef TCL_WRAPPER
34 #define Fprintf tcl_printf
35 #define Flush tcl_stdflush
36 #else
37 #define Fprintf fprintf
38 #define Flush fflush
39 #endif
42 int __debug_spice__=2;
44 #ifndef STRIP_DEBUGGING
45 #define D(level,a) do { if(__debug_spice__>(level)) a; } while(0)
46 #else
47 #define D(level,a)
48 #endif
50 /* spice deck
52 .SUBCKT CKT1 3 4 5
53 M0 6 3 1 1 NMOS W=1.025U L=0.350U AD=0.0 AS=0.0 PD=0.0 PS=0.0
54 M1 7 4 6 1 NMOS W=1.025U L=0.350U AD=0.0 AS=0.0 PD=0.0 PS=0.0
56 C0 3 1 1.92627e-15
57 C1 4 1 1.8152e-15
59 .ENDS
61 *comment
63 X1464 3 583 589 CKT6
66 #define __NETLIST_SPICE_C__ 1
69 #ifndef __NETLIST_H__
70 #include "netlist_dev.h"
71 #endif
75 #ifndef __NETLIST_SPICE_H__
76 #include "netlist_spice.h"
77 #endif
79 tokenmap_t spice_tokens[]=SPICE_TOKENS;
81 /******* Hashing Clients *******/
83 uint paramclient_hash(int max, void *data, int size)
85 return hash_strhash(max, ((char *)data)+sizeof(paramload_t), size-sizeof(paramload_t));
89 int paramclient_cmp(int sizea, void *a, int sizeb, void *b)
91 if(a==NULL)return 1;
92 if(b==NULL)return -1;
93 if(sizea > sizeb) return 1;
94 if(sizea < sizeb) return -1;
95 return memcmp( ((char *) a) + sizeof(paramload_t), ((char *)b ) + sizeof(paramload_t),sizeb-sizeof(paramload_t) );
98 static callparam_t *new_callparam(char *str, eqn_t eqn)
100 callparam_t *pc;
101 pc=malloc(sizeof(callparam_t)+strlen(str));
102 assert(pc!=NULL);
103 strcpy(pc->str,str);
104 pc->eqn=eqn;
105 return pc;
109 static paramclient_t *add_param(hash_t *h, char *str, eqn_t eqn)
111 int l;
112 char data[4096];
113 paramclient_t *pc;
114 pc=(void *)data;
115 l=strlen(str)+1;
116 if(l>(sizeof(data)-sizeof(paramclient_t)))
117 l=sizeof(data)-sizeof(paramclient_t);
118 pc->payload.eqn=eqn;
119 pc->payload.patch_call=NULL;
120 pc->payload.global_i=-1;
121 memcpy(pc->str,str,l);
122 return hash_add(h,pc,l+sizeof(paramload_t));
125 uint nodeclient_hash(int max, void *data, int size)
127 return hash_strhash(max, ((char *)data)+sizeof(hashload_t), size-sizeof(hashload_t));
130 int nodeclient_cmp(int sizea, void *a, int sizeb, void *b)
132 if(a==NULL)return 1;
133 if(b==NULL)return -1;
134 if(sizea > sizeb) return 1;
135 if(sizea < sizeb) return -1;
136 return memcmp( ((char *) a) + sizeof(hashload_t), ((char *)b ) + sizeof(hashload_t), sizea-sizeof(hashload_t) );
139 /* some helper functions for hash clients */
141 static nodeclient_t *find_hashtab(hash_t *tab, uchar *str)
143 int l;
144 l=strlen(str)+1;
145 return hash_find(tab,str-sizeof(hashload_t),sizeof(hashload_t)+l);
148 subckt_t *spice_find_subckt(subckt_t *parent, char *name)
150 nodeclient_t *tc;
151 tc=find_hashtab(parent->cktdir,(uchar *)name);
152 return tc->payload.data.subckt;
156 list_t spice_list_subckt(subckt_t *parent)
158 list_t foo;
159 subckt_t *ckt;
160 int i;
161 hash_t *tab;
162 hashbin_t *bp;
163 node_t p;
165 list_init(&foo,sizeof(subckt_t *),LIST_EXPMODE);
166 if(parent==NULL)return foo;
168 tab=parent->cktdir;
169 FORALL_HASH(tab,i,bp)
171 p=hash_bin2user(bp);
172 ckt=p->payload.data.subckt;
173 list_add (&foo,&ckt);
175 return foo;
179 static nodeclient_t *add_hashtab(hash_t *tab, uchar *str, hashload_t payload)
181 int l;
182 uchar *strp=str;
183 nodeclient_t *cp;
184 static unsigned data[16000];
185 nodeclient_t *nd=(void *)data;
186 assert(tab!=NULL);
187 nd->payload=payload;
188 l=0;
189 while(strp[0]!=0)
191 nd->str[l]=strp[0];
192 strp++; l++;
194 nd->str[l]=0;
195 l++;
196 assert(l< (16000-sizeof(nodeclient_t)));
197 if(tab->hashfunc!=nodeclient_hash)assert(0);
198 cp=hash_add(tab,nd,(sizeof(hashload_t)+l));
199 D(20,Fprintf(stderr,"add_hashtab(%p,%s,..) cp=%p \n",tab,str,cp));
200 return cp;
205 #define warning(d,c,s) do { scan->errdeck=d; scan->errcard=c; parse_warn(scan,s); } while(0)
206 #define error(d,c,s) do { scan->errdeck=d; scan->errcard=c; parse_error(scan,s); } while(0)
207 #define checkvalid(d,q) scanner_checkvalid(d,q)
209 static eqn_t parseval(deck_t *d, card_t *c, uchar *val)
211 uchar *ps;
212 eqn_t eqn;
213 eqn=eqn_empty();
215 if(val==NULL)return eqn;
217 for(ps=val;ps[0]!=0;ps++)
218 if(!isspace(ps[0]))break;
220 if(ps[0]=='\'') ps++; /* hack */
222 eqn=eqn_parse(ps);
224 return eqn;
229 /************************************************************************/
230 /******* PASS 2 : create subcircuit definitions (for forward ref) ****/
231 /******* and count devices (for memory alloc) ****/
232 /******* fill in all devices and nodes (except x subckt) ****/
233 /************************************************************************/
237 static void skip_subckt(deck_t **thedeckpp)
239 int i;
240 deck_t *dp=*thedeckpp;
241 i=0;
243 while(dp!=NULL)
245 if(dp->card!=NULL)
247 if(dp->card->token==Kends)i--;
248 if(dp->card->token==Ksubckt)i++;
250 if(i==0)break;
251 dp=dp->next;
253 *thedeckpp=dp;
256 static subckt_t *new_subckt(deck_t **thedeckpp, subckt_t *parent, scanner_t *scan)
258 int i, qtynodes, qtyparams, qtycallparams, qtylparams;
259 int qtym, qtyc, qtyx, qtyr, qtyl, qtyv, qtyi;
260 int qtysubckt, qtyglobal;
261 subckt_t *scktp;
262 card_t *cp;
263 deck_t *dp,*d=*thedeckpp,*dplast=NULL;
264 int size;
265 void *p;
266 uchar *name;
267 hashload_t payload={ PAYLOAD_null, {NULL} };
269 qtycallparams=0;
270 qtynodes=0;
271 qtyparams=0;
272 qtylparams=0;
273 qtysubckt=0;
274 qtyglobal=0;
276 if(!checkvalid(d,2))error(d,d->card,"invalid subckt definition");
277 name=d->card->next->str;
279 i = 0;
280 for(cp=d->card->next->next; cp!=NULL; cp=cp->next)
282 if(cp->val==NULL) qtynodes++;
283 else qtylparams++;
284 i++;
287 qtym = 0;
288 qtyc = 0;
289 qtyr = 0;
290 qtyl = 0;
291 qtyx = 0;
292 qtyv = 0;
293 qtyi = 0;
295 for(dp=d; dp!=NULL; dp=dp->next)
297 uchar a;
298 dplast=dp;
299 if(dp->card==NULL)continue;
301 if( (dp->card->token==Ksubckt) && (dp!=d))
302 { skip_subckt(&dp); qtysubckt++; continue; } /* consume .ends token */
304 if(dp==NULL)break;
305 if(dp->card==NULL)continue;
307 if(dp->card->token==Kend)break;
308 if(dp->card->token==Kends)break;
311 if(parent!=NULL)
312 { if(dp->card->token==Kends)break; }
313 else { if(dp->card->token==Kend)break; }
316 a=dp->card->str[0];
317 if(a=='x')
319 qtyx++;
320 for(cp=dp->card->next;cp!=NULL;cp=cp->next)
321 if(cp->val!=NULL)qtycallparams++;
324 if(a=='m') qtym++;
325 if(a=='c') qtyc++;
326 if(a=='r') qtyr++;
327 if(a=='l') qtyl++;
328 if(a=='v') qtyv++;
329 if(a=='i') qtyi++;
331 if(dp->card->token==Kparam)
333 for(cp=dp->card->next;cp!=NULL;cp=cp->next)
334 qtyparams++;
336 if(dp->card->token==Kglobal)
338 for(cp=dp->card->next;cp!=NULL;cp=cp->next)
339 qtyglobal++;
343 if(dp==NULL) {
344 if(parent==NULL)
347 uchar *p,buf[64]=".END ";
348 D(50,Fprintf(stderr,"ignoring lack of .END token\n"));
349 assert(dplast!=NULL);
350 assert(dplast->next==NULL);
351 dp=dplast->next=new_deck();
352 dp->next=NULL;
353 p=buf;
354 dp->card=make_card(&p,PARSE_CASE_TOLOWER);
355 dp->card->token=Kend;
358 else
360 if(parent==NULL)error(d,NULL,"No .END found");
361 else error(d,NULL,"No .ENDS found");
365 D(10, Fprintf(stderr,"Got %i subckts, %i x's %i m's %i c's %i r's "
366 "%i l %i v %i i's\n",
367 qtysubckt, qtyx, qtym, qtyc, qtyr, qtyl, qtyv, qtyi));
369 size=
370 sizeof(subckt_t) +
371 (sizeof(node_t)*qtynodes) +
372 (sizeof(m_t)*qtym) +
373 (sizeof(x_t)*qtyx) +
374 (sizeof(c_t)*qtyc) +
375 (sizeof(r_t)*qtyr) +
376 (sizeof(l_t)*qtyl) +
377 (sizeof(v_t)*qtyv) +
378 (sizeof(i_t)*qtyi) +
379 (strlen(name) + 2);
381 scktp=p=malloc(size+1024); /* 1024 is debug pad */
383 assert(scktp!=NULL);
384 memset(scktp,0,size);
385 memset(((char *)scktp)+size,'a',1024);
386 p= ((char *)p+sizeof(subckt_t));
388 scktp->defn=p;
389 scktp->ndefn=qtynodes;
390 p= ((char *)p+(sizeof(node_t)*qtynodes));
392 scktp->m=p;
393 scktp->nm=qtym;
394 p= ((char *)p+(sizeof(m_t)*qtym));
396 scktp->c=p;
397 scktp->nc=qtyc;
398 p= ((char *)p+(sizeof(c_t)*qtyc));
400 scktp->r=p;
401 scktp->nr=qtyr;
402 p= ((char *)p+(sizeof(r_t)*qtyr));
404 scktp->l=p;
405 scktp->nl=qtyl;
406 p= ((char *)p+(sizeof(l_t)*qtyl));
408 scktp->v=p;
409 scktp->nv=qtyv;
410 p= ((char *)p+(sizeof(v_t)*qtyv));
412 scktp->i=p;
413 scktp->ni=qtyi;
414 p= ((char *)p+(sizeof(i_t)*qtyi));
416 scktp->x=p;
417 scktp->nx=qtyx;
418 p= ((char *)p+(sizeof(x_t)*qtyx));
420 scktp->name=p;
421 strcpy(scktp->name,name);
422 p= ((char *)p+strlen(name)+2);
425 scktp->scale=1.0;
426 scktp->mult=1.0;
427 scktp->subckt_magic=SUBCKT_MAGIC;
428 assert((((char *)p)-((char *)scktp))==size); /* sanity check */
430 /* estimate good size for hashtable */
431 scktp->nodes=hash_new((qtym*3)+(qtyx*4),nodeclient_hash,nodeclient_cmp);
433 scktp->flag=0;
434 scktp->params=hash_new(qtyparams,paramclient_hash,paramclient_cmp);
435 scktp->lparams=hash_new(qtylparams,paramclient_hash,paramclient_cmp);
436 scktp->parent=parent;
437 scktp->cktdir=hash_new(qtysubckt,nodeclient_hash,nodeclient_cmp);
438 scktp->global=hash_new(qtyglobal,nodeclient_hash,nodeclient_cmp);
440 /* store defn nodes, and ptrs */
441 for(i=0,cp=d->card->next->next;cp!=NULL;cp=cp->next)
443 if(cp->val==NULL) /* skip params on line */
445 if(find_hashtab(scktp->nodes,cp->str)!=NULL)
446 warning(d,cp,"duplicate node in subckt definition");
448 payload.flag=PAYLOAD_null;
449 payload.data.p=NULL;
450 scktp->defn[i]=add_hashtab(scktp->nodes,cp->str,payload);
451 i++;
455 /* do subckt params (those on the .subckt line) */
457 for(cp=d->card->next->next;cp!=NULL;cp=cp->next)
459 if(cp->val!=NULL) /* skip nodes on line */
460 add_param(scktp->lparams,cp->str,parseval(d,cp,cp->val));
463 /* do spice deck */
465 /* reinitialize device counters */
466 qtyr = 0;
467 qtyl = 0;
468 qtym = 0;
469 qtyc = 0;
470 qtyx = 0;
471 qtyv = 0;
472 qtyi = 0;
474 for (dp = d; dp != NULL; dp = dp->next)
476 uchar a;
477 if (dp->card == NULL) continue;
479 if ((dp->card->token == Ksubckt) && (dp != d))
481 subckt_t *child=NULL;
482 child=new_subckt(&dp,scktp,scan);
483 payload.data.subckt=child;
484 payload.flag=PAYLOAD_subckt;
485 add_hashtab(scktp->cktdir,child->name,payload);
486 continue;
488 if(dp==NULL)break;
489 if(dp->card==NULL)continue;
490 if(parent!=NULL)
491 { if(dp->card->token==Kends)break; }
492 else { if(dp->card->token==Kend)break; }
494 a=dp->card->str[0];
495 if(a=='x')
497 int k=0;
498 x_t *xp;
499 card_t *last;
501 assert(qtyx<scktp->nx);
502 xp=&(scktp->x[qtyx]);
503 xp->nn=0;
504 xp->nl=0;
505 xp->nodes=NULL;
506 xp->locals=NULL;
508 if(!checkvalid(dp,2))error(d,NULL,"invalid subckt call");
509 for(i=0,last=cp=dp->card->next;cp!=NULL;cp=cp->next,i++)
511 if(cp->val!=NULL)break; last=cp;
514 if(cp!=NULL)
516 for(k=0;cp!=NULL;cp=cp->next,k++);
518 else k=0;
520 xp->deck=dp;
521 xp->rest=last;
522 xp->nodes=malloc((sizeof(node_t)*i)+(sizeof(paramclient_t*)*k));
523 if(k==0)
524 xp->locals=NULL;
525 else
526 xp->locals=(void *)((char *)(xp->nodes))+(sizeof(node_t)*(i));
527 xp->nn=i-1;
528 xp->nl=k;
529 assert(xp->nodes!=NULL);
531 payload.flag=PAYLOAD_null;
532 payload.data.s=NULL;
534 for(i=0,cp=dp->card->next;(cp!=NULL)&&(cp!=last);cp=cp->next,i++)
536 xp->nodes[i]=add_hashtab(scktp->nodes,cp->str,payload);
537 if(0)Fprintf(stderr,"X:%s adding node %p cp->str=%s\n",dp->card->str,xp->nodes[i],cp->str);
539 if(cp!=NULL)
541 for(k=0,cp=cp->next;(cp!=NULL);cp=cp->next,k++)
542 if(cp->val!=NULL)
543 { xp->locals[k]=new_callparam(cp->str,parseval(dp,cp,cp->val)); }
544 else xp->locals[k]=NULL;
546 qtyx++;
548 if(a=='m') /* Mident d g s b model L=val W=val other_params... */
550 m_t *mp;
551 if(!checkvalid(dp,8))error(d,NULL,"invalid mosfet card");
552 mp=&(scktp->m[qtym]);
553 cp=dp->card->next;
555 payload.flag=PAYLOAD_null;
556 payload.data.s=NULL;
558 for(i=0;i<4;i++)
560 mp->nodes[i]=add_hashtab(scktp->nodes,cp->str,payload);
561 cp=cp->next;
563 mp->type=0;
564 /* hope this is n or p */
565 if((cp->str[0]=='n')||(cp->str[0]=='p'))
566 mp->type=cp->str[0];
567 else
569 uchar *p;
570 for(p=cp->str;p[0]!=0;p++)
571 if((p[0]=='n')||(p[0]=='p'))
572 mp->type=p[0];
574 if(mp->type==0)
576 Fprintf(stderr,"Couldn't determine fet type from model name %s\n",cp->str);
579 mp->rest=cp;
580 mp->deck=dp;
581 cp=cp->next;
583 mp->l =eqn_const(1); mp->w=eqn_const(1);
584 mp->as=eqn_const(-1); mp->ad=eqn_const(-1);
585 mp->ps=eqn_const(-1); mp->pd=eqn_const(-1);
587 for(i=0;cp!=NULL;cp=cp->next,i++)
589 if( (cp->str[0]=='l') && (cp->str[1]==0)) mp->l=parseval(dp,cp,cp->val);
590 if( (cp->str[0]=='w') && (cp->str[1]==0)) mp->w=parseval(dp,cp,cp->val);
591 if( (cp->str[0]=='a') && (cp->str[1]=='s') && (cp->str[2]==0) )
592 mp->as=parseval(dp,cp,cp->val);
593 if( (cp->str[0]=='a') && (cp->str[1]=='d') && (cp->str[2]==0) )
594 mp->ad=parseval(dp,cp,cp->val);
595 if( (cp->str[0]=='p') && (cp->str[1]=='s') && (cp->str[2]==0) )
596 mp->ps=parseval(dp,cp,cp->val);
597 if( (cp->str[0]=='p') && (cp->str[1]=='d') && (cp->str[2]==0) )
598 mp->pd=parseval(dp,cp,cp->val);
600 qtym++;
602 if(a=='c') /* Cident node0 node1 value */
604 if(!checkvalid(dp,4))error(d,NULL,"invalid capacitor card");
606 payload.flag=PAYLOAD_null;
607 payload.data.p=NULL;
608 scktp->c[qtyc].nodes[0]=add_hashtab(scktp->nodes,dp->card->next->str,payload);
609 scktp->c[qtyc].nodes[1]=add_hashtab(scktp->nodes,dp->card->next->next->str,payload);
610 cp=dp->card->next->next->next;
611 scktp->c[qtyc].deck=dp;
612 scktp->c[qtyc].c=parseval(dp,cp,cp->str);
613 scktp->c[qtyc].rest=cp;
614 qtyc++;
617 if (a == 'r') /* Rident node0 node1 value */
619 if (!checkvalid(dp,4))error(d,NULL,"invalid resistor card");
621 payload.flag=PAYLOAD_null;
622 payload.data.p=NULL;
623 scktp->r[qtyr].nodes[0] =
624 add_hashtab(scktp->nodes,dp->card->next->str,payload);
625 scktp->r[qtyr].nodes[1] =
626 add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
627 cp=dp->card->next->next->next;
628 scktp->r[qtyr].deck=dp;
629 scktp->r[qtyr].r=parseval(dp,cp,cp->str);
630 scktp->r[qtyr].rest=cp;
631 qtyr++;
634 /* To be done: AC, pulse, and PWL sources */
636 if (a == 'v') /* Vident node0 node1 value */
638 if (!checkvalid(dp,4))error(d,NULL,"invalid voltage source card");
640 payload.flag=PAYLOAD_null;
641 payload.data.p=NULL;
642 scktp->v[qtyv].nodes[0] =
643 add_hashtab(scktp->nodes,dp->card->next->str,payload);
644 scktp->v[qtyv].nodes[1] =
645 add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
646 cp=dp->card->next->next->next;
647 scktp->v[qtyv].deck=dp;
648 scktp->v[qtyv].v=parseval(dp,cp,cp->str);
649 scktp->v[qtyv].rest=cp;
650 qtyv++;
653 if (a == 'i') /* Iident node0 node1 value */
655 if (!checkvalid(dp,4))error(d,NULL,"invalid current source card");
657 payload.flag=PAYLOAD_null;
658 payload.data.p=NULL;
659 scktp->i[qtyi].nodes[0] =
660 add_hashtab(scktp->nodes,dp->card->next->str,payload);
661 scktp->i[qtyi].nodes[1] =
662 add_hashtab(scktp->nodes,dp->card->next->next->str, payload);
663 cp=dp->card->next->next->next;
664 scktp->i[qtyi].deck=dp;
665 scktp->i[qtyi].i=parseval(dp,cp,cp->str);
666 scktp->i[qtyi].rest=cp;
667 qtyi++;
670 if (a == 'l') /* Lident node0 node1 value */
672 if (!checkvalid(dp,4))error(d,NULL,"invalid inductor card");
674 payload.flag=PAYLOAD_null;
675 payload.data.p=NULL;
676 scktp->l[qtyl].nodes[0] =
677 add_hashtab(scktp->nodes,dp->card->next->str,payload);
678 scktp->l[qtyl].nodes[1] =
679 add_hashtab(scktp->nodes,dp->card->next->next->str,payload);
680 cp=dp->card->next->next->next;
681 scktp->l[qtyl].deck=dp;
682 scktp->l[qtyl].l=parseval(dp,cp,cp->str);
683 scktp->l[qtyl].rest=cp;
684 qtyl++;
687 if(dp->card->token==Kparam)
688 for(cp=dp->card->next;cp!=NULL;cp=cp->next)
690 if(cp->val==NULL)error(dp,cp,"couldn't find = in .param statement");
691 add_param(scktp->params,cp->str,parseval(dp,cp,cp->val));
692 D(10, Fprintf(stderr, "spice: adding param %s to scktp->params=%p \n",
693 cp->str, scktp->params));
696 if(dp->card->token==Kscale)
698 if(dp->card->val!=NULL)
699 scktp->scale=parse_float(dp->card->val);
700 else error(dp,dp->card,"need a value for .scale ");
703 if(dp->card->token==Kmult)
705 if(dp->card->val!=NULL)
706 scktp->mult=parse_float(dp->card->val);
707 else error(dp,dp->card,"need a value for .scale ");
710 payload.flag=PAYLOAD_null;
711 payload.data.p=NULL;
713 if(dp->card->token==Kglobal)
714 for(cp=dp->card->next;cp!=NULL;cp=cp->next)
715 add_hashtab(scktp->global,cp->str,payload);
717 if(dp->next==NULL) *thedeckpp=dp; /* ignore lack of end token */
719 if(dp!=NULL)
720 *thedeckpp=dp; /*dp->next;*/ /* skip .end token if present */
722 return scktp;
726 static void do_subckts(subckt_t *ckt, scanner_t *scan)
728 x_t *xp;
729 nodeclient_t *hcp;
730 int i;
732 if(ckt==NULL)return;
733 if(ckt->flag)return;
734 ckt->flag=1;
736 for(i=0;i<ckt->nx;i++)
738 uchar *nm=NULL;
739 xp=ckt->x+i;
740 hcp=NULL;
741 if(xp->rest!=NULL)
743 subckt_t *search;
744 nm=xp->rest->str;
745 for(search=ckt;search!=NULL;search=search->parent)
746 if( (hcp=find_hashtab(search->cktdir,nm)) != NULL) break;
748 if(hcp==NULL)
749 { Fprintf(stderr,"subcircuit named [%s] not found in ckt [%s]\n",
750 nm,ckt->name); }
751 else {
752 assert(hcp->payload.flag==PAYLOAD_subckt);
753 xp->xp=hcp->payload.data.subckt;
754 assert(xp->xp!=NULL);
755 do_subckts(xp->xp,scan); /* recursion */
762 static subckt_t *new_ckt(deck_t *d, scanner_t *scan)
764 deck_t *dp;
765 subckt_t *first=NULL;
766 deck_t topdeck;
767 card_t topcard[2];
768 topdeck.line.line=0;
769 topdeck.line.fileindex=0;
770 topdeck.next=d;
771 topdeck.card=&(topcard[0]);
772 topcard[0].next=&(topcard[1]);
773 topcard[0].str[0]=0;
774 topcard[0].token=Ksubckt;
775 strcpy(topcard[0].str,".su"); /* max 4 bytes */
776 topcard[0].val=NULL;
777 topcard[1].next=NULL;
778 topcard[1].token=Kother;
779 topcard[1].val=NULL;
780 strcpy(topcard[1].str,"TOP"); /* MAX 4 bytes */
782 dp=&topdeck;
784 first=new_subckt(&dp,NULL,scan);
785 first->subckt_magic=SUBCKT_MAGIC;
786 do_subckts(first,scan);
787 return first;
791 static void debug_subckts(void * dbg, subckt_t *ckt, int level)
793 int i;
794 uchar pad[64]=" ";
796 if(ckt==NULL)return;
798 if(ckt->flag)return;
799 ckt->flag=1;
802 pad[level*2]=0;
804 fprintf(dbg,"%s subckt %s nm=%i nc=%i nr=%i nx=%i\n",pad,ckt->name,ckt->nm,ckt->nc,ckt->nr,ckt->nx);
805 for(i=0;i<ckt->nm;i++)
807 node_t *n=ckt->m[i].nodes;
808 fprintf(dbg,"%s M %s %s %s %s\n%s +",pad,
809 n[0]->str,n[1]->str,n[2]->str,n[3]->str,pad);
810 debug_eqn(dbg,"l",&(ckt->m[i].l));
811 debug_eqn(dbg,"w",&(ckt->m[i].w));
812 debug_eqn(dbg,"as",&(ckt->m[i].as));
813 debug_eqn(dbg,"ad",&(ckt->m[i].ad));
814 debug_eqn(dbg,"ps",&(ckt->m[i].ps));
815 debug_eqn(dbg,"pd",&(ckt->m[i].ps));
816 fprintf(dbg,"\n");
819 for(i=0;i<ckt->nc;i++)
821 node_t *n=ckt->c[i].nodes;
822 fprintf(dbg,"%s C %s %s ",pad,
823 n[0]->str,n[1]->str);
824 debug_eqn(dbg,"c",&(ckt->c[i].c));
825 fprintf(dbg,"\n");
828 for(i=0;i<ckt->nr;i++)
830 node_t *n=ckt->r[i].nodes;
831 fprintf(dbg,"%s R %s %s ",pad,
832 n[0]->str,n[1]->str);
833 debug_eqn(dbg,"r",&(ckt->r[i].r));
834 fprintf(dbg,"\n");
838 for(i=0;i<ckt->nx;i++)
840 fprintf(dbg,"%s X %s : %p, %i nodes\n",pad,ckt->x[i].xp->name,ckt->x[i].nodes,ckt->x[i].nn);
841 debug_subckts(dbg,ckt->x[i].xp,level+1); /* recursion */
852 /**********************************************************************/
853 /***************** PASS 3: operations on heirarchy *******************/
854 /******************************-- flattening --- **********************/
859 /* a couple of different lookup functions for equations and parameters
860 with slightly different semantics
862 lookup_params is for TERMINAL equations that need multipliers
863 lookup_params_nomult is for equations in '.param' statements
864 lookup_parents_call_eqns is for equations in subckt calls
865 ie: Xdddd blah blah v='eqn blah' ...
867 #ifndef NO_EQUATIONS
868 static eqn_t lookup_parents_call_eqns(stack_t *s, eqn_t *ep);
869 static eqn_t lookup_params_nomult(stack_t *s, eqn_t *ep);
870 static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m);
871 #endif
874 static void spice_recurse_subckts(spice_t *spice, subckt_t *ckt, stack_t *parent, void (*process)(stack_t *s, int flag, void *data),void *data)
876 stack_t s;
877 int i;
878 s.nl=NULL;
879 s.scan=spice->scan;
880 if(ckt==NULL)return;
882 if(parent==NULL) { s.level=0; s.parent=NULL; s.ckt=ckt; s.call=NULL; s.top=&s; }
883 else { s.level=parent->level+1; s.parent=parent; s.ckt=ckt; s.call=NULL; s.top=s.parent->top; }
885 process(&s,0,data);
887 for(i=0;i<ckt->nx;i++)
888 { s.call=ckt->x+i; spice_recurse_subckts(spice,s.call->xp,&s,process,data); } /* recursion */
890 s.call=NULL;
891 process(&s,1,data);
896 static char * do_name(stack_t *s, char *str)
898 static char buf[1024*63];
899 char *bp,*c;
900 stack_t *sp;
901 int l,q=0,sizebuf=sizeof(buf);
902 int m;
904 D(10,Fprintf(stderr,"doname: [%s] ",str));
906 m=sizebuf -4;
907 buf[sizebuf-1]=0;
908 bp=buf+sizebuf-1;
910 l=strlen(str);
911 bp-=l;
912 q+=l; assert(q<m);
913 memcpy(bp,str,l);
915 for(sp=s;sp!=NULL;sp=sp->parent)
917 if(sp->call==NULL)continue;
918 assert(sp->call->deck!=NULL);
919 assert(sp->call->deck->card!=NULL);
920 c=sp->call->deck->card->str;
921 l=strlen(c);
922 q+=l+1; assert(q<m);
923 bp--;
924 bp[0]='.';
925 bp-=l;
926 memcpy(bp,c,l);
928 D(10,Fprintf(stderr,"(%s)\n",bp));
929 return bp;
936 #ifdef NO_EQUATIONS
937 static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m)
939 ep->val=ep->val*m;
940 return *ep;
942 #else
946 static paramclient_t * find_param_intable(hash_t *h, char *str)
948 int l;
949 paramclient_t *pc,*tofind;
950 /* note to self: this trickery is dependent on hash.c doing the right thing which it does */
951 tofind=(void *)(str-sizeof(paramload_t));
953 l=strlen(str)+1;
954 D(30,Fprintf(stderr,"looking for %s in table %p l=%i ",str,h,l));
955 pc=hash_find(h,tofind,sizeof(paramload_t)+l);
956 D(30,Fprintf(stderr," hash_find=%p\n",pc));
957 return pc;
961 /* local (bottom) takes precedence over top (global) */
962 static paramclient_t * find_param_bot(stack_t *s, char *str)
964 stack_t *sp;
965 paramclient_t *r=NULL,*toret=NULL;
967 subckt_t *ckt;
969 for(sp=s;sp!=NULL;sp=sp->parent)
971 if(sp->ckt!=NULL)
973 ckt=sp->ckt;
974 r=find_param_intable(ckt->lparams,str);
975 if(toret==NULL)toret=r;
976 r=find_param_intable(ckt->params,str);
977 if(toret==NULL)toret=r;
980 return toret;
983 /* global (top) takes precidence over bottom (local) */
984 static paramclient_t * find_param_top(stack_t *s, char *str)
986 paramclient_t *r=NULL,*toret=NULL;
987 subckt_t *ckt;
988 stack_t *sp;
990 for(sp=s;sp!=NULL;sp=sp->parent)
992 if(sp->ckt!=NULL)
994 ckt=sp->ckt;
995 r=find_param_intable(ckt->lparams,str);
996 if(r!=NULL)toret=r;
997 r=find_param_intable(ckt->params,str);
998 if(r!=NULL)toret=r;
1001 return toret;
1007 static eqn_litref_t lookup_function(plookup_t *user, char *str)
1009 paramlookup_t *me=user->user;
1010 paramclient_t *r;
1011 eqn_litref_t index=eqn_litref_INIT;
1012 char *hname;
1014 if(1)r=find_param_bot(me->sp,str);
1015 else r=find_param_top(me->sp,str);
1016 if(r!=NULL)
1018 /* this is not a renameable local parameter */
1019 if(r->payload.patch_call==NULL)
1021 /* we want to use this parameter, but don't have a global entry yet */
1022 if(r->payload.global_i<0)
1024 /* todo: lookup this param=equation now, in case it has dependencies */
1025 eqn_t eq;
1026 hname=do_name(me->sp,str);
1027 D(5,Fprintf(stderr,"Lookup function: Adding eqn (%s) (%s)\n",str,hname));
1028 D(5,debug_eqn(stderr,str,&(r->payload.eqn)));
1029 D(5,Fprintf(stderr,"\n"));
1030 eq=lookup_params_nomult(me->sp,&(r->payload.eqn));
1031 r->payload.global_i=eqnl_add(&(me->nl->eqnl),eq,hname);
1033 index=r->payload.global_i;
1035 else /* we renamed this parameter, follow the indirection, make heir. name */
1036 { /* also note we probably want to call lookup params now
1037 using parent's context for subckt call
1039 D(50,Fprintf(stderr,"Lookup rename: %s\n",str));
1040 D(50,debug_eqn(stderr," eqn ",&(r->payload.patch_call->eqn)));
1041 D(50,Fprintf(stderr,"\n"));
1042 if(r->payload.global_i<0)
1044 hname=do_name(me->sp,str);
1045 D(5,Fprintf(stderr,"Lookup function rename: Adding eqn (%s) (%s)\n",str,hname));
1046 D(5,debug_eqn(stderr," eqn ",&(r->payload.patch_call->eqn)));
1047 r->payload.global_i=eqnl_add(&(me->nl->eqnl),
1048 lookup_parents_call_eqns(me->sp, &(r->payload.patch_call->eqn)),
1049 hname);
1051 index=r->payload.global_i;
1054 else /* an undefined reference, may be a sweep parameter, to be loaded from tracefile */
1056 index=eqnl_find(&(me->nl->eqnl),str);
1057 if(index<0)
1059 D(3,Fprintf(stderr,"Netlist_sp: assuming %s is global sweep parameter\n",str));
1060 index= eqnl_add(&(me->nl->eqnl),eqn_undefined(),str);
1062 else D(3,Fprintf(stderr,"Netlist_sp: assume %s is a global parameter, not local\n",str));
1064 return index;
1068 static eqn_t lookup_parents_call_eqns(stack_t *s, eqn_t *ep)
1070 int r=0;
1071 eqn_t v;
1072 plookup_t plu;
1073 paramlookup_t me;
1075 if(s->parent!=NULL)
1077 me.sp=s->parent;
1078 me.nl=s->nl;
1079 plu.user=&me;
1080 plu.lookup=lookup_function;
1081 v=eqn_copy(*ep);
1082 D(10,debug_eqn(stderr,"lookup parents:", &v));
1083 D(10,Fprintf(stderr,"\n"));
1084 r=eqntok_depend(v.eqn,&plu);
1085 if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
1087 else D(1,Fprintf(stderr,"lookup parents eqn called, but we are at the top level\n"));
1088 assert(s->parent!=NULL);
1089 return v;
1092 static eqn_t lookup_params_nomult(stack_t *s, eqn_t *ep)
1094 eqn_t v;
1095 int r=0;
1096 plookup_t plu;
1097 paramlookup_t me;
1098 me.sp=s;
1099 me.nl=s->nl;
1100 plu.user=&me;
1101 plu.lookup=lookup_function;
1103 v=eqn_copy(*ep);
1105 if(v.eqn!=NULL)
1106 r=eqntok_depend(v.eqn,&plu);
1108 if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
1110 return v;
1115 static eqn_t lookup_params(stack_t *s, eqn_t *ep, float m)
1117 eqn_t v;
1118 int r=0;
1119 plookup_t plu;
1120 paramlookup_t me;
1121 me.sp=s;
1122 me.nl=s->nl;
1123 plu.user=&me;
1124 plu.lookup=lookup_function;
1126 v=eqn_copy_m(*ep,m);
1128 if(v.eqn!=NULL)
1129 r=eqntok_depend(v.eqn,&plu);
1131 if(r)D(1,Fprintf(stderr,"couldn't find a parameter in equation\n"));
1133 return v;
1135 #endif
1139 static void count_stuff(stack_t *s, int flag, void *data)
1141 netlist_t *nl=data;
1142 if(flag)return;
1143 nl->e[DEVT_FET].qcount+=s->ckt->nm;
1144 nl->e[DEVT_CAP].qcount+=s->ckt->nc;
1151 static void build_stuff(stack_t *s, int flag, void *data)
1153 netlist_t *nl=data;
1154 int i,q,j;
1155 node_t n;
1156 hashbin_t *bp;
1157 hash_t *h,*globals,*h1;
1158 x_t *call;
1159 paramclient_t *pc,*findpc;
1160 scanner_t *scan=s->scan;
1161 if(flag)return; /* preorder */
1163 h=s->ckt->nodes;
1164 globals=s->top->ckt->global;
1165 s->nl=nl;
1167 D(40,Fprintf(stderr,"processing stack %p: s->top=%p s->parent=%p s->ckt=%p\n",s,s->top,s->parent,s->ckt));
1169 /* first assign parent payloads to all the nodes in nodedir */
1170 if(s->parent!=NULL)
1172 call=s->parent->call;
1173 assert(call!=NULL);
1175 if(call->nn!=s->ckt->ndefn)
1176 error(call->deck,call->rest,"Definition does not match use");
1178 q=minimum(call->nn,s->ckt->ndefn);
1180 for(i=0;i<q;i++)
1182 assert(call->nodes[i]!=NULL);
1183 assert(call->nodes[i]->payload.flag==PAYLOAD_gnptr);
1184 s->ckt->defn[i]->payload.data=call->nodes[i]->payload.data;
1185 s->ckt->defn[i]->payload.flag=PAYLOAD_parent;
1189 /* lookup subckt call's and map to local params */
1191 h1=s->ckt->lparams;
1192 hash_forall(h1,i,bp) /* init patch ptrs to Null (so any previous invokation won't be used) */
1194 pc=hash_bin2user(bp); pc->payload.patch_call=NULL; pc->payload.global_i=-1;
1195 D(30,Fprintf(stderr,"considering hash table entry %i %s len=%i\n",i,pc->str,bp->size-sizeof(paramload_t)));
1198 /* for each param in the x call line, patch local param if found */
1199 for(i=0;i<call->nl;i++)
1201 callparam_t *callp;
1202 callp=call->locals[i];
1203 if(callp==NULL)continue;
1205 /* hackish hash_find: we pass a bogus object, who's string is at same location */
1206 findpc=hash_find(h1,callp->str-sizeof(paramload_t),strlen(callp->str)+sizeof(paramload_t)+1);
1208 if(findpc!=NULL) /* we link to this subckt eqn call */
1209 findpc->payload.patch_call=callp;
1210 else
1211 D(2,Fprintf(stderr,"subckt call, specified parameter [%s] not found\n",callp->str));
1213 D(5,Fprintf(stderr,"patching call %s",callp->str));
1214 if(findpc!=NULL)D(5,debug_eqn(stderr," orig ",&(findpc->payload.eqn)));
1215 D(5,debug_eqn(stderr," patch ",&(callp->eqn)));
1216 D(5,Fprintf(stderr,"\n"));
1220 /* if parent is NULL, then we are top level, specially create/process global nodes first */
1221 else
1223 assert(s->top->ckt==s->ckt);
1225 FORALL_HASH(globals,i,bp)
1227 char *flatname;
1228 n=hash_bin2user(bp);
1229 n->payload.flag=PAYLOAD_gnptr;
1230 /* note to self: must use terminal indices, because node table may be reallocated as it grows */
1231 flatname=do_name(s,n->str);
1232 n->payload.data.t=netlist_node(nl,flatname,(void*)n);
1237 /* then assign new node payload to all the rest, doing global checks */
1239 FORALL_HASH(h,i,bp)
1241 node_t gbn;
1242 n=hash_bin2user(bp);
1243 if((n->payload.flag==PAYLOAD_gnptr)||(n->payload.flag==PAYLOAD_parent)||(n->payload.flag==PAYLOAD_null))
1245 else assert(0);
1247 gbn=find_hashtab(globals,n->str); /* i hope this search is efficient */
1248 if(gbn!=NULL)
1250 if(n->payload.flag!=PAYLOAD_parent)
1251 n->payload.data=gbn->payload.data;
1253 else
1255 if(n->payload.flag!=PAYLOAD_parent)
1257 char *flatname;
1258 flatname=do_name(s,n->str);
1259 n->payload.data.t=netlist_node(nl,flatname,(void *)n);
1262 n->payload.flag=PAYLOAD_gnptr; /* set both types to gnptr */
1266 /* now we have ptrs to every gn_t in this subckt reference, so we can process elements */
1268 for(i=0;i<s->ckt->nc;i++) /* FOR EACH capacitor */
1270 dev_input_t devinp;
1271 devcap_t *dcp;
1272 c_t *cp;
1273 termptr_t np[2];
1274 for(j=0;j<2;j++)
1275 np[j]= s->ckt->c[i].nodes[j]->payload.data.t;
1276 devinp.spice_cap=cp=&(s->ckt->c[i]);
1277 dcp=list_data(&(nl->e[DEVT_CAP].l),netlist_newdev_fromnode(nl,DEVT_CAP,devinp,np));
1278 dcp->v[DEVCAP_c]=lookup_params(s,&(cp->c),s->ckt->mult);
1281 for(i=0;i<s->ckt->nm;i++) /* FOR EACH fet */
1283 dev_input_t devinp;
1284 termptr_t np[4];
1285 m_t *cp;
1286 devfet_t *dfp;
1287 int spiceorder[4]={INDEX_SOURCE, INDEX_DRAIN, INDEX_GATE, INDEX_BULK };
1288 int netlistorder[4]= {DEVFET_S, DEVFET_D, DEVFET_G, DEVFET_B };
1290 for(j=0;j<4;j++)
1291 np[netlistorder[j]]=s->ckt->m[i].nodes[spiceorder[j]]->payload.data.t;
1292 devinp.spice_fet=cp=&(s->ckt->m[i]);
1293 dfp=list_data(&(nl->e[DEVT_FET].l),netlist_newdev_fromnode(nl,DEVT_FET,devinp,np));
1295 for(j=0;j<DEVFET_V;j++)
1296 dfp->v[j]=eqn_const(0);
1298 dfp->type=0;
1300 if(cp->type=='p')
1301 { dfp->type=DEVFET_pmos; }
1302 else
1303 if(cp->type=='n')
1304 { dfp->type=DEVFET_nmos; }
1305 else
1306 assert(0);
1308 D(30,do
1310 static int mosfet_i=0;
1311 Fprintf(stderr,"processing mosfet %i \n",++mosfet_i);
1312 } while(0)
1315 dfp->v[DEVFET_w] =lookup_params(s,&(cp->w),s->ckt->scale);
1316 dfp->v[DEVFET_l] =lookup_params(s,&(cp->l),s->ckt->scale);
1317 dfp->v[DEVFET_as]=lookup_params(s,&(cp->as),(s->ckt->scale)*(s->ckt->scale));
1318 dfp->v[DEVFET_ad]=lookup_params(s,&(cp->ad),(s->ckt->scale)*(s->ckt->scale));
1319 dfp->v[DEVFET_ps]=lookup_params(s,&(cp->ps),s->ckt->scale);
1320 dfp->v[DEVFET_pd]=lookup_params(s,&(cp->pd),s->ckt->scale);
1323 for(i=0;i<s->ckt->nx;i++) /* FOR EACH SUBCKT CALL */
1325 x_t *xp;
1326 xp=s->ckt->x+i;
1327 for(j=0;j<xp->nl;j++)
1328 if(xp->locals[j]!=NULL)
1330 /* we copy the actual equation at use instantiation time
1331 via lookup_parent...
1341 return ; /* recurse on subckt calls */
1347 static void free_ckt(subckt_t *ckt)
1349 int i;
1350 hash_t *tab;
1351 hashbin_t *bp;
1352 node_t p;
1353 subckt_t *tofree;
1355 if(ckt==NULL)return;
1357 tab=ckt->cktdir;
1358 FORALL_HASH(tab,i,bp)
1360 p=hash_bin2user(bp);
1361 tofree=p->payload.data.subckt;
1362 p->payload.data.subckt=NULL;
1363 free_ckt(tofree);
1366 for(i=0;i<ckt->nx;i++)
1368 int j;
1370 for(j=0;j<ckt->x[i].nl;j++)
1371 if(ckt->x[i].locals[j]!=NULL)
1372 free(ckt->x[i].locals[j]);
1374 if(ckt->x[i].nodes!=NULL)
1375 free(ckt->x[i].nodes); /* this frees locals also (combined allocation) */
1377 /* note: equations have their own memory allocation system
1378 so NEVER free an eqntoken_t *
1381 hash_free(ckt->cktdir);
1382 hash_free(ckt->nodes);
1383 hash_free(ckt->params);
1384 hash_free(ckt->lparams);
1385 hash_free(ckt->global);
1387 free(ckt);
1391 void spice_count(netlist_t *nl)
1393 spice_t *sp=nl->input.spice;
1395 spice_recurse_subckts(sp,sp->ckt,NULL,&count_stuff,(void *)nl);
1400 void spice_build(netlist_t *nl)
1402 spice_t *sp=nl->input.spice;
1403 netlist_eqn_begin(nl);
1404 spice_recurse_subckts(sp,sp->ckt,NULL,&build_stuff,(void *)nl);
1405 netlist_eqn_end(nl);
1409 void spice_release(spice_t *sp)
1411 if(sp!=NULL)
1413 free_ckt(sp->ckt);
1414 eqn_mem_free(sp->eqn_mem);
1415 free(sp);
1419 spice_t *spice_new(scanner_t *scan)
1421 spice_t *p;
1422 p=malloc(sizeof(spice_t));
1423 assert(p!=NULL);
1424 memset(p,0,sizeof(spice_t));
1425 p->spice_magic=SPICE_MAGIC;
1426 p->scan=scan;
1427 p->eqn_mem=eqn_mem_new();
1428 eqn_mem_push(p->eqn_mem);
1429 scanner_sect_new(p->scan,scanner_def_spice(),spice_tokens);
1430 scanner_parse_all(p->scan);
1431 D(6,scanner_debug_all(p->scan,stderr));
1432 p->deck=p->scan->sectp->dhead;
1433 scanner_sect_release(p->scan);
1435 if(p->deck!=NULL)
1436 { p->ckt=new_ckt(p->deck,p->scan); }
1437 else { p->ckt=NULL; }
1439 if(eqn_mem_pop()!=p->eqn_mem)
1440 assert(0);
1441 return p;
1448 void spice_debug(void * dbg_fp, spice_t *sp)
1450 FILE *dbg=dbg_fp;
1451 fprintf(dbg,"debugging output for spice circuit file \n");
1453 debug_subckts(dbg,sp->ckt, 0);