Initial commit at Tue Apr 25 08:36:02 EDT 2017 by tim on stravinsky
[xcircuit.git] / spiceparser / netlist_funcs.c
blob4e0f2d22d8b726ba4478ffb063a5dff7f5a21b49
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 /* netlist_funcs.c: table of usefull netlistfunc_t's for standard devtypes
22 Conrad Ziesler
25 #include <stdio.h>
26 #include "debug.h"
27 #include "netlist_dev.h"
29 #define EVALfull(n,a) eqnl_eval(&((n)->nl->eqnl),(a))
30 #define EVALquick(n,a) eqn_getval_(&(a))
31 #define EVALnm(a) EVALquick(nm,a)
33 /* accumulate fet properties (areas, perimeters add per fraction of total width) */
35 static int nlfd_props[]={ DEVFET_as, DEVFET_ad, DEVFET_ps, DEVFET_pd };
36 static int nlfd_merge_same[]= { DEVFET_w, DEVFET_as, DEVFET_ad, DEVFET_ps, DEVFET_pd};
37 static int nlfd_merge_flip[]= { DEVFET_w, DEVFET_ad, DEVFET_as, DEVFET_pd, DEVFET_ps};
39 static void nlfd_fet_acc(netlistfunc_t *nm, int devi, int termi, float *nodeprops)
41 devfet_t *f;
42 int w,i;
44 f=list_data(&(nm->entity->l),devi);
45 assert(f!=NULL);
46 w= (f->type==DEVFET_nmos)?0:1;
48 if((termi==DEVFET_S)||(termi==DEVFET_D))
50 nodeprops[w]+=EVALnm(f->v[DEVFET_w]);
51 for(i=0;i<4;i++)
52 nodeprops[2+i]+=EVALnm(f->v[nlfd_props[i]]);
56 static void nlfd_fet_dist(netlistfunc_t *nm, int devi, int termi, float *nodeprops)
58 devfet_t *f;
59 int w,i;
60 float fraction;
62 f=list_data(&(nm->entity->l),devi);
63 assert(f!=NULL);
64 w= (f->type==DEVFET_nmos)?0:1;
66 if((termi==DEVFET_S)||(termi==DEVFET_D))
68 if(nodeprops[w]!=0)
69 fraction=EVALnm(f->v[DEVFET_w])/nodeprops[w];
70 else fraction=0;
72 for(i=0;i<4;i++)
73 eqn_setval(&(f->v[nlfd_props[i]]),nodeprops[i+2]*fraction);
77 /* source and drain we do separately by in nlfd_fet_sum, since they are symmetrical */
78 typedef struct nlfd_cmp_st
80 termptr_t g,b;
81 float l;
82 char type;
83 }nlfd_cmp_t;
86 static void nlfd_fet_cmp(netlistfunc_t *nm, int index, void *data)
88 devfet_t *f;
89 nlfd_cmp_t *cmp=data;
91 f=list_data(&(nm->entity->l),index);
92 assert(f!=NULL);
93 cmp->type=f->type;
94 cmp->l=EVALnm(f->v[DEVFET_l]);
95 cmp->g=f->n[DEVFET_G];
96 cmp->b=f->n[DEVFET_B];
99 static int nlfd_fet_sum(struct netlistfunc_st *nm,int ia, int ib)
101 devfet_t *fa,*fb;
102 int i;
103 fa=list_data(&(nm->entity->l),ia);
104 fb=list_data(&(nm->entity->l),ib);
107 assert(fa!=NULL);
108 assert(fb!=NULL);
111 if( /* these are checked in mergedup, and should be ok */
112 (!memcmp(&(fa->n[DEVFET_G]),&(fb->n[DEVFET_G]),sizeof(termptr_t))) &&
113 (!memcmp(&(fa->n[DEVFET_B]),&(fb->n[DEVFET_B]),sizeof(termptr_t))) &&
114 (EVALnm(fa->v[DEVFET_l]) == EVALnm(fb->v[DEVFET_l]))
117 if((!memcmp(&(fa->n[DEVFET_S]),&(fb->n[DEVFET_S]),sizeof(termptr_t))) &&
118 (!memcmp(&(fa->n[DEVFET_D]),&(fb->n[DEVFET_D]),sizeof(termptr_t))) )
120 /* merge devices, same orientation */
121 for(i=0;i<(sizeof(nlfd_merge_same)/sizeof(int));i++)
122 eqn_setval(
123 &(fa->v[nlfd_merge_same[i]]),
124 EVALnm(fa->v[nlfd_merge_same[i]])+
125 EVALnm(fb->v[nlfd_merge_same[i]])
127 return 1;
129 if((!memcmp(&(fa->n[DEVFET_S]),&(fb->n[DEVFET_D]),sizeof(termptr_t))) &&
130 (!memcmp(&(fa->n[DEVFET_D]),&(fb->n[DEVFET_S]),sizeof(termptr_t))) )
132 /* merge devices, opposite orientation */
133 for(i=0;i<(sizeof(nlfd_merge_same)/sizeof(int));i++)
134 eqn_setval(
135 &(fa->v[nlfd_merge_same[i]]),
136 EVALnm(fa->v[nlfd_merge_same[i]])+
137 EVALnm(fb->v[nlfd_merge_flip[i]])
139 return 1;
142 else
144 fprintf(stderr,"mergedup compare failure\n");
147 return 0; /* fail request */
150 netlistfunc_t * netlist_devfet_funcs(netlist_t *nl, netlistfunc_t *fp)
152 netlistfunc_t f;
153 memset(&f,0,sizeof(f));
155 f.nl=nl;
156 f.entity=nl->e+DEVT_FET;
157 f.qproperties=6; /* n/p width + as/ad/ps/pd */
158 f.accumulate=nlfd_fet_acc;
159 f.distribute=nlfd_fet_dist;
160 f.qcmp=sizeof(nlfd_cmp_t);
161 f.sum=nlfd_fet_sum;
162 f.tocompare=nlfd_fet_cmp;
163 f.fixup=NULL; /* this is not needed, only if user wants it */
165 if(fp!=NULL)
166 *fp=f;
168 return fp;