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
21 /* netlist_funcs.c: table of usefull netlistfunc_t's for standard devtypes
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
)
44 f
=list_data(&(nm
->entity
->l
),devi
);
46 w
= (f
->type
==DEVFET_nmos
)?0:1;
48 if((termi
==DEVFET_S
)||(termi
==DEVFET_D
))
50 nodeprops
[w
]+=EVALnm(f
->v
[DEVFET_w
]);
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
)
62 f
=list_data(&(nm
->entity
->l
),devi
);
64 w
= (f
->type
==DEVFET_nmos
)?0:1;
66 if((termi
==DEVFET_S
)||(termi
==DEVFET_D
))
69 fraction
=EVALnm(f
->v
[DEVFET_w
])/nodeprops
[w
];
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
86 static void nlfd_fet_cmp(netlistfunc_t
*nm
, int index
, void *data
)
91 f
=list_data(&(nm
->entity
->l
),index
);
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
)
103 fa
=list_data(&(nm
->entity
->l
),ia
);
104 fb
=list_data(&(nm
->entity
->l
),ib
);
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
++)
123 &(fa
->v
[nlfd_merge_same
[i
]]),
124 EVALnm(fa
->v
[nlfd_merge_same
[i
]])+
125 EVALnm(fb
->v
[nlfd_merge_same
[i
]])
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
++)
135 &(fa
->v
[nlfd_merge_same
[i
]]),
136 EVALnm(fa
->v
[nlfd_merge_same
[i
]])+
137 EVALnm(fb
->v
[nlfd_merge_flip
[i
]])
144 fprintf(stderr
,"mergedup compare failure\n");
147 return 0; /* fail request */
150 netlistfunc_t
* netlist_devfet_funcs(netlist_t
*nl
, netlistfunc_t
*fp
)
153 memset(&f
,0,sizeof(f
));
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
);
162 f
.tocompare
=nlfd_fet_cmp
;
163 f
.fixup
=NULL
; /* this is not needed, only if user wants it */