1 /*****************************************************************************/
3 /* Chaine de CAO & VLSI AVERTEC */
5 /* Produit : SIM Version 2.00 */
6 /* Fichier : sim_obj.c */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
11 /* Auteur(s) : Gilles Augustins */
13 /*****************************************************************************/
14 #include <semaphore.h>
20 int SIM_OUTLOAD
= SIM_TRANSISTOR_OUTLOAD
;
21 double SIM_INPUT_START
= 0.0;
22 double SIM_OUT_CAPA_VAL
= -1.0;
23 double SIM_TECSIZE
= 1.0;
25 double SIM_VTH_HIGH
= 0.8;
26 double SIM_VTH_LOW
= 0.2;
27 double SIM_SLOP
= 200.0;
28 double SIM_SIMU_STEP
= SIM_UNDEF
;
29 double SIM_DC_STEP
= 0.001;
30 char *SIM_SPICE_OPTIONS
= NULL
;
31 char *SIM_SPICESTRING
= "spice $";
32 char *SIM_SPICENAME
= "spice";
33 char *SIM_SPICEOUT
= "$.out";
34 char *SIM_SPICESTDOUT
= "$.out";
35 char *SIM_TECHFILE
= "avtdefault.tec";
36 char SIM_TR_AS_INS
= SIM_NO
;
37 void *SIM_EXTRACT_RULE
= NULL
;
38 char SIM_DEFAULT_DRIVE_NETLIST
= SIM_NO
;
39 char SIM_DEFAULT_OVR_FILES
= SIM_YES
;
40 char SIM_DEFAULT_REMOVE_FILES
= SIM_NO
;
41 float SIM_VT_SLOPEIN
= -1.0;
44 extern char *spi_devect (char *name
);
45 static inline locon_list
*findLoconInFig(lofig_list
*fig
, char *loconName
);
46 static inline losig_list
*findLosigInFig(lofig_list
*fig
, char *losigName
);
47 static inline loins_list
*findLoinsInFig(lofig_list
*fig
, char *loinsName
);
48 static inline lotrs_list
*findLotrsInFig(lofig_list
*fig
, char *lotrsName
);
49 static inline locon_list
*findLoconInLoins(loins_list
*ins
, char *loconName
,char *loconName2
);
50 static inline locon_list
*findLoconInTrs(lotrs_list
*trs
, char *loconName
,char *loconName2
);
51 static inline locon_list
* sim_find_by_nameInt(char *name
, lofig_list
*topfig
, locon_list
**loconfound
, losig_list
**losigfound
, chain_list
**listins
, chain_list
*hiername
);
53 int sim_SetPowerSupply (lofig_list
*lofig
)
57 if (V_FLOAT_TAB
[__SIM_POWER_SUPPLY
].SET
==0)
58 if (mbk_GetPowerSupply (lofig
, &supply
)) {
59 V_FLOAT_TAB
[__SIM_POWER_SUPPLY
].VALUE
= supply
;
60 elpGeneral
[elpGVDDMAX
] = supply
;
66 static int donesimInFork
=0;
69 /*static void sim_destroy_sem()
71 mbk_sem_destroy(simInFork, &simInForkStatic, "simvfork");
79 mbk_sem_init(&simInFork
, 1);
83 if ((env
= V_STR_TAB
[__SIM_OUTLOAD
].VALUE
)) {
84 if (!strcasecmp (env
,"dynamic")) SIM_OUTLOAD
= SIM_DYNAMIC_OUTLOAD
;
85 else if (!strcasecmp (env
,"transistor")) SIM_OUTLOAD
= SIM_TRANSISTOR_OUTLOAD
;
86 else if (!strcasecmp (env
,"none")) SIM_OUTLOAD
= SIM_NO_OUTLOAD
;
88 else SIM_OUTLOAD
= SIM_TRANSISTOR_OUTLOAD
;
90 //Simulator related options
91 if (V_INT_TAB
[__SIM_TOOLMODEL
].SET
&& !V_INT_TAB
[__SIM_TOOL
].SET
) {
92 switch (V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
) {
93 case SIM_TOOLMODEL_SPICE
: V_INT_TAB
[__SIM_TOOL
].VALUE
= SIM_TOOL_SPICE
; break;
94 case SIM_TOOLMODEL_HSPICE
: V_INT_TAB
[__SIM_TOOL
].VALUE
= SIM_TOOL_HSPICE
; break;
95 case SIM_TOOLMODEL_ELDO
: V_INT_TAB
[__SIM_TOOL
].VALUE
= SIM_TOOL_ELDO
; break;
96 case SIM_TOOLMODEL_TITAN
: V_INT_TAB
[__SIM_TOOL
].VALUE
= SIM_TOOL_TITAN
; break;
99 if (V_INT_TAB
[__SIM_TOOL
].SET
&& !V_INT_TAB
[__SIM_TOOLMODEL
].SET
) {
100 switch (V_INT_TAB
[__SIM_TOOL
].VALUE
) {
102 case SIM_TOOL_LTSPICE
:
103 case SIM_TOOL_NGSPICE
:
104 V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
= SIM_TOOLMODEL_SPICE
;
106 case SIM_TOOL_HSPICE
:
107 case SIM_TOOL_MSPICE
:
108 V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
= SIM_TOOLMODEL_HSPICE
;
111 V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
= SIM_TOOLMODEL_ELDO
;
114 V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
= SIM_TOOLMODEL_TITAN
;
119 if (V_INT_TAB
[__SIM_TOOLMODEL
].VALUE
== SIM_TOOLMODEL_HSPICE
) {
120 if (!V_FLOAT_TAB
[__SIM_TNOM
].SET
) V_FLOAT_TAB
[__SIM_TNOM
].VALUE
=25;
123 switch (V_INT_TAB
[__SIM_TOOL
].VALUE
) {
125 sim_decodeMeasCmdFree();
126 sim_decodeMeasCmd (".meas tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
127 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
128 mfe_freerules(&SIM_EXTRACT_RULE
);
129 mfe_addrule (&SIM_EXTRACT_RULE
, "line:/EXTRACT INFORMATION/1****/:* %l = %v targ= %0 trig= %0");
130 SIM_SPICE_OPTIONS
= sensitive_namealloc ("hmax=1e-12 eps=10u");
131 SIM_SPICEOUT
= sensitive_namealloc ("$.chi");
132 SIM_SPICESTDOUT
= sensitive_namealloc ("$.out");
133 SIM_SPICESTRING
= sensitive_namealloc ("eldo $");
134 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
135 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
138 case SIM_TOOL_TITAN7
:
139 sim_decodeMeasCmdFree();
140 sim_decodeMeasCmd (".measure tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
141 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
142 mfe_freerules(&SIM_EXTRACT_RULE
);
143 mfe_addrule (&SIM_EXTRACT_RULE
, "line:/--- Nominal//: %l | %v | %0 | %0");
144 SIM_SPICE_OPTIONS
= sensitive_namealloc ("reltol=1e-4 tritol=5");
145 if (V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
== 1) SIM_SPICEOUT
= sensitive_namealloc ("$.tr.t1.ppr");
146 else SIM_SPICEOUT
= sensitive_namealloc ("$.tr.measure");
147 SIM_SPICESTDOUT
= sensitive_namealloc ("$.out");
148 SIM_SPICESTRING
= sensitive_namealloc ("titan $");
149 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
150 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
152 case SIM_TOOL_MSPICE
:
153 V_BOOL_TAB
[__SPI_DRIVE_USE_UNITS
].VALUE
=0;
154 SIM_SPICE_OPTIONS
= sensitive_namealloc ("COMPATIBILITY=hspice");
155 mfe_freerules(&SIM_EXTRACT_RULE
);
156 mfe_addrule (&SIM_EXTRACT_RULE
, "table:/.TITLE//:%l %v");
157 sim_decodeMeasCmdFree();
158 sim_decodeMeasCmd (".measure tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
159 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
160 SIM_SPICEOUT
= sensitive_namealloc ("$.mt0");
161 SIM_SPICESTRING
= sensitive_namealloc ("mspice $");
162 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
163 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
165 case SIM_TOOL_HSPICE
:
166 SIM_SPICE_OPTIONS
= NULL
;
167 mfe_freerules(&SIM_EXTRACT_RULE
);
168 mfe_addrule (&SIM_EXTRACT_RULE
, "table:/.TITLE//:%l %v");
169 sim_decodeMeasCmdFree();
170 sim_decodeMeasCmd (".measure tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
171 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
172 SIM_SPICEOUT
= sensitive_namealloc ("$.mt0");
173 SIM_SPICESTRING
= sensitive_namealloc ("hspice $");
174 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
175 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
177 case SIM_TOOL_LTSPICE
:
178 sim_decodeMeasCmdFree();
179 sim_decodeMeasCmd (".measure tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
180 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
181 mfe_freerules(&SIM_EXTRACT_RULE
);
182 mfe_addrule (&SIM_EXTRACT_RULE
, "line:/Direct Newton/Date:/:%l = %v FROM %0 TO %0");
183 SIM_SPICE_OPTIONS
= NULL
;
184 SIM_SPICEOUT
= sensitive_namealloc ("$.log");
185 SIM_SPICESTDOUT
= sensitive_namealloc ("$.out");
186 SIM_SPICESTRING
= sensitive_namealloc ("ltspice $");
187 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
188 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
190 case SIM_TOOL_NGSPICE
:
191 SIM_SPICE_OPTIONS
= NULL
;
192 mfe_freerules(&SIM_EXTRACT_RULE
);
193 mfe_addrule (&SIM_EXTRACT_RULE
, "line:/Transient Analysis//:%l = %v targ= %0 trig= %0");
194 sim_decodeMeasCmdFree();
195 sim_decodeMeasCmd (".measure tran %l TRIG v(%s1) val=%v1 %t1{rise,fall}=%n1{LAST}"
196 " TARG v(%s2) val=%v2 %t2{rise,fall}=%n2{LAST}");
197 SIM_SPICEOUT
= sensitive_namealloc ("$.out");
198 SIM_SPICESTDOUT
= sensitive_namealloc ("$.out");
199 SIM_SPICESTRING
= sensitive_namealloc ("ngspice -b $");
200 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=1;
201 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=0;
204 SIM_SPICE_OPTIONS
= NULL
;
205 SIM_SPICESTRING
= sensitive_namealloc ("spice -b $");
206 SIM_SPICEOUT
= sensitive_namealloc ("$.out");
207 SIM_SPICESTDOUT
= sensitive_namealloc ("$.out");
208 if (!V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
=0;
209 if (!V_BOOL_TAB
[__SIM_USE_PRINT
].SET
) V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
=1;
212 if (V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
== 1 && V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
== 1) {
213 if (V_BOOL_TAB
[__SIM_USE_PRINT
].SET
&& !V_BOOL_TAB
[__SIM_USE_MEAS
].SET
) {
214 V_BOOL_TAB
[__SIM_USE_MEAS
].VALUE
= 0;
216 else V_BOOL_TAB
[__SIM_USE_PRINT
].VALUE
= 0;
219 SIM_OUT_CAPA_VAL
= V_FLOAT_TAB
[__SIM_OUT_CAPA_VAL
].VALUE
;
220 SIM_INPUT_START
= V_FLOAT_TAB
[__SIM_INPUT_START
].VALUE
;
221 SIM_TECSIZE
= V_FLOAT_TAB
[__SIM_TECHNO_SIZE
].VALUE
;
222 SIM_VTH
= V_FLOAT_TAB
[__SIM_VTH
].VALUE
;
223 SIM_VTH_HIGH
= V_FLOAT_TAB
[__SIM_VTH_HIGH
].VALUE
;
224 SIM_VTH_LOW
= V_FLOAT_TAB
[__SIM_VTH_LOW
].VALUE
;
225 if ((env
= getenv ("SIM_SLOPE_INTERNAL_THRESHOLDS")) && (!strcasecmp (env
, "yes"))) {
226 SIM_VTH_HIGH
= ELPINITTHR
;
227 SIM_VTH_LOW
= ELPINITTHR
;
230 SIM_SLOP
= V_FLOAT_TAB
[__SIM_INPUT_SLOPE
].VALUE
* 1.0E12
;
231 SIM_SIMU_STEP
= V_FLOAT_TAB
[__SIM_SIMU_STEP
].VALUE
* 1.0E9
;
232 SIM_DC_STEP
= V_FLOAT_TAB
[__SIM_DC_STEP
].VALUE
;
234 if ((env
= V_STR_TAB
[__SIM_MEAS_CMD
].VALUE
))
236 sim_decodeMeasCmdFree();
237 sim_decodeMeasCmd(env
);
239 if ((env
= V_STR_TAB
[__SIM_EXTRACT_RULE
].VALUE
))
241 mfe_freerules(&SIM_EXTRACT_RULE
);
242 mfe_addrule(&SIM_EXTRACT_RULE
,env
);
245 if (V_STR_TAB
[__SIM_SPICE_OPTIONS
].SET
) SIM_SPICE_OPTIONS
= sensitive_namealloc (V_STR_TAB
[__SIM_SPICE_OPTIONS
].VALUE
);
246 if (V_STR_TAB
[__SIM_SPICE_STRING
].SET
) SIM_SPICESTRING
= sensitive_namealloc (V_STR_TAB
[__SIM_SPICE_STRING
].VALUE
);
247 if (V_STR_TAB
[__SIM_SPICE_OUT
].SET
) SIM_SPICEOUT
= sensitive_namealloc (V_STR_TAB
[__SIM_SPICE_OUT
].VALUE
);
248 if (V_STR_TAB
[__SIM_SPICE_STDOUT
].SET
) SIM_SPICESTDOUT
= sensitive_namealloc (V_STR_TAB
[__SIM_SPICE_STDOUT
].VALUE
);
249 if (V_STR_TAB
[__SIM_TECH_FILE
].SET
) SIM_TECHFILE
= sensitive_namealloc (V_STR_TAB
[__SIM_TECH_FILE
].VALUE
);
250 SIM_TR_AS_INS
= V_INT_TAB
[__SIM_TRANSISTOR_AS_INSTANCE
].VALUE
?SIM_YES
:SIM_NO
;
251 SIM_DEFAULT_OVR_FILES
= V_BOOL_TAB
[__SIM_OVR_FILES
].VALUE
?SIM_YES
:SIM_NO
;
253 SIM_DEFAULT_REMOVE_FILES
= V_BOOL_TAB
[__SIM_REMOVE_FILES
].VALUE
?SIM_YES
:SIM_NO
;
255 // zinaps le 12/10/2004
256 if ((SIM_VTH
<0 || SIM_VTH
>1) && SIM_VTH
!=-1)
257 { avt_error("sim", 1, AVT_ERR
, "invalid value for variable 'simVth', it should range from 0 to 1\n"); stoprequest
=1; }
258 if ((SIM_VTH_HIGH
<0 || SIM_VTH_HIGH
>1) && SIM_VTH_HIGH
!=-1)
259 { avt_error("sim", 2, AVT_ERR
, "invalid value for variable 'simVthHigh', it should range from 0 to 1\n"); stoprequest
=1; }
260 if ((SIM_VTH_LOW
<0 || SIM_VTH_LOW
>1) && SIM_VTH_LOW
!=-1)
261 { avt_error("sim", 3, AVT_ERR
, "invalid value for variable 'simVthLow', it should range from 0 to 1\n"); stoprequest
=1; }
263 if (stoprequest
) EXIT(1);
265 if (SIM_VTH_HIGH
<SIM_VTH
&& SIM_VTH
!=-1 && SIM_VTH_HIGH
!=-1)
266 { avt_error("sim", 4, AVT_ERR
, "'simVthHigh' value must be higher than 'simVth'\n"); stoprequest
=1; }
267 if (SIM_VTH_LOW
>SIM_VTH
&& SIM_VTH
!=-1 && SIM_VTH_LOW
!=-1)
268 { avt_error("sim", 5, AVT_ERR
, "'simVthLow' value must be lower than 'simVth'\n"); stoprequest
=1; }
270 if (stoprequest
) EXIT(1);
271 // ---------------------
275 void sim_error( char *msg
, ... )
279 va_start( arg
, msg
);
282 fprintf( stderr
, "\n\n *** Fatal error in sim library ***\n" );
283 vfprintf( stderr
, msg
, arg
);
288 void sim_warning( char *msg
, ... )
293 va_start( arg
, msg
);
296 // fprintf( stderr, "\n\n *** Warning in sim library ***\n" );
297 vsprintf( buf
, msg
, arg
);
298 avt_error("sim", -1, AVT_WAR
, buf
);
304 /****************************************************************************/
305 locon_list
*sim_find_locon(char *name
, lofig_list
*topfig
,
306 locon_list
**loconfound
, chain_list
**listins
)
312 sim_find_by_name(name
,topfig
,loconfound
,NULL
,listins
);
316 sim_find_by_name(name
,topfig
,&locon
,NULL
,listins
);
321 /*}}}************************************************************************/
322 /*{{{ sim_get_hier_list() */
325 /****************************************************************************/
326 chain_list
* sim_get_hier_list(char *hiername
)
328 chain_list
*decomp
= NULL
;
335 while (hiername
[pos
] != '\0')
337 if( hiername
[pos
] != SEPAR
)
338 word
[destpos
++] = hiername
[pos
];
341 word
[destpos
] = '\0';
343 decomp
= addchain(decomp
,namealloc(word
));
350 word
[destpos
] = '\0';
351 decomp
= addchain(decomp
,namealloc(word
));
354 return reverse(decomp
);
357 /*}}}************************************************************************/
361 /* Recherche un locon ou un losig d'après son nom hiérarchique. Renvoie la liste
362 chaînée des instances où il se trouve depuis topfig.
364 Les noms doivent être sous la forme :
365 Z -> Locon sur l'interface de lofig.
366 tr.Z -> Locon sur un transistor de la lofig.
367 i1.Z -> Locon sur une instance de la lofig.
368 i1.tr.Z -> Locon sur un transistor de l'instance i1
369 i1.i2.Z -> Locon sur une instance i2 de l'instance i1
370 i1.i2.tr.Z -> et ainsi de suite.
372 i1.i2.tr.Z -> la netlist est à plat, le trs s'appelle i1.i2.tr
375 /****************************************************************************/
376 void sim_find_by_name( char *name
,
378 locon_list
**loconfound
,
379 losig_list
**losigfound
,
383 chain_list
*hiername
;
387 hiername
= sim_get_hier_list(name
);
396 // recherche d'abord sur l interface
397 locon
= findLoconInFig(topfig
,name
);
399 losig
= findLosigInFig(topfig
,name
);
401 if (!locon
&& !losig
)
403 sim_find_by_nameInt(name
,topfig
,loconfound
,losigfound
,listins
,hiername
);
417 /*}}}************************************************************************/
421 /****************************************************************************/
422 static inline locon_list
*findLoconInFig(lofig_list
*fig
, char *loconName
)
424 locon_list
*locon
= fig
->LOCON
;
426 while (locon
&& locon
->NAME
!= loconName
)
432 /*}}}************************************************************************/
436 /****************************************************************************/
437 static inline locon_list
*findLoconInLoins(loins_list
*ins
, char *loconName
,
440 locon_list
*locon
= ins
->LOCON
;
443 while (locon
&& locon
->NAME
!= loconName
&& locon
->NAME
!= loconName2
)
446 while (locon
&& locon
->NAME
!= loconName
)
452 /*}}}************************************************************************/
456 /****************************************************************************/
457 static inline losig_list
*findLosigInFig(lofig_list
*fig
, char *losigName
)
459 losig_list
*losig
= fig
->LOSIG
;
461 while (losig
&& getsigname(losig
) != losigName
)
467 /*}}}************************************************************************/
471 /****************************************************************************/
472 static inline loins_list
*findLoinsInFig(lofig_list
*fig
, char *loinsName
)
474 loins_list
*loins
= fig
->LOINS
;
476 while (loins
&& loins
->INSNAME
!= loinsName
)
482 /*}}}************************************************************************/
486 /****************************************************************************/
487 static inline lotrs_list
*findLotrsInFig(lofig_list
*fig
, char *lotrsName
)
489 lotrs_list
*lotrs
= fig
->LOTRS
;
491 while (lotrs
&& (!lotrs
->TRNAME
|| lotrs
->TRNAME
!= lotrsName
))
497 /*}}}************************************************************************/
501 /****************************************************************************/
502 static inline locon_list
*findLoconInTrs(lotrs_list
*trs
, char *loconName
,
509 else if (trs
->GRID
->NAME
== loconName
|| trs
->GRID
->NAME
== loconName2
)
511 else if (trs
->SOURCE
->NAME
== loconName
|| trs
->SOURCE
->NAME
== loconName2
)
513 else if (trs
->DRAIN
->NAME
== loconName
|| trs
->DRAIN
->NAME
== loconName2
)
515 else if (trs
->BULK
&&
516 (trs
->BULK
->NAME
== loconName
|| trs
->BULK
->NAME
== loconName2
))
526 /*}}}************************************************************************/
530 /****************************************************************************/
531 locon_list
* sim_find_by_nameInt(char *name
,
533 locon_list
**loconfound
,
534 losig_list
**losigfound
,
535 chain_list
**listins
,
536 chain_list
*hiername
)
539 locon_list
*locon
= NULL
;
540 losig_list
*losig
= NULL
;
542 char tmpbuf
[BUFSIZ
], nomtrs
[BUFSIZ
], *tmp
, *insname
, *signame
;
543 chain_list
*chainx
, *ins
= NULL
, *headTrs
;
546 // descend la hiérarchie. Les noms sont de la forme
550 for (figx
= topfig
, chainx
= hiername
; chainx
; chainx
= chainx
->NEXT
)
552 insname
= (char*)chainx
->DATA
;
553 if ((loins
= findLoinsInFig(figx
,insname
)))
555 ins
= addchain(ins
,loins
);
556 figx
= getlofig(loins
->FIGNAME
,'A');
563 signame
= insname
; // the last visited is a signal name
565 /* C'est sur une instance */
568 locon
= findLoconInLoins(ins
->DATA
,insname
,name
);
569 /* Greg, le 13/10/03 : il faut retirer la dernière instance de la liste
570 puisque le locon ne se situe pas DANS l'instance */
573 chainx
->NEXT
= NULL
;
578 /* C'est sur un transistor : on gère le cas où le nom du transistor
579 correspond à un nom hiérarchique. */
580 if (!locon
&& headTrs
->NEXT
)
582 // creation of transistor name
583 strcpy(nomtrs
,(char*)headTrs
->DATA
);
584 for (chainx
= headTrs
->NEXT
; chainx
->NEXT
; chainx
= chainx
->NEXT
)
586 sprintf(tmpbuf
,"%s%c%s",nomtrs
,SEPAR
,(char*)chainx
->DATA
);
587 strcpy(nomtrs
,tmpbuf
);
590 if ((tmp
= namefind(nomtrs
)))
591 lotrs
= findLotrsInFig(figx
,tmp
);
594 locon
= findLoconInTrs(lotrs
,chainx
->DATA
,name
);
597 // C'est peut etre un signal
599 losig
= findLosigInFig(figx
,signame
);
606 *listins
= reverse(ins
);
623 /*}}}************************************************************************/
624 /* Renvoie la liste chainée des figures nécessaires pour lancer une simulation.
625 Cette liste est ordonnée des instances les plus basses vers les instances les
628 chain_list
*sim_getfiglist( lofig_list
*lofig
)
637 head
= addchain( NULL
, lofig
);
643 lofig
= (lofig_list
*)(done
->DATA
);
644 for( loins
= lofig
->LOINS
; loins
; loins
= loins
->NEXT
) {
645 if (incatalog (loins
->FIGNAME
)) continue;
646 figins
= getlofig( loins
->FIGNAME
, 'A' );
647 if( !getptype( figins
->USER
, SIM_MARKED
) ) {
648 figins
->USER
= addptype( figins
->USER
, SIM_MARKED
, NULL
);
649 new = addchain( NULL
, figins
);
657 for( done
= head
->NEXT
; done
; done
= done
->NEXT
) {
658 lofig
= (lofig_list
*)(done
->DATA
);
659 lofig
->USER
= delptype( lofig
->USER
, SIM_MARKED
);
662 return reverse( head
);
665 static chain_list
*_sim_getallfiglist(ht
*fight
, chain_list
*head
, lofig_list
*lofig
)
670 for( loins
= lofig
->LOINS
; loins
!=NULL
; loins
= loins
->NEXT
)
672 if (gethtitem(fight
, loins
->FIGNAME
)!=EMPTYHT
|| incatalog (loins
->FIGNAME
)) continue;
673 figins
= getlofig( loins
->FIGNAME
, 'A' );
674 head
=addchain(head
, figins
);
675 head
=_sim_getallfiglist(fight
, head
, figins
);
681 chain_list
*sim_getallfiglist(lofig_list
*lofig
)
687 head
=_sim_getallfiglist(fight
, NULL
, lofig
);
694 /*---------------------------------------------------------------------------*/
696 char *sim_vect (char *v
) /* a 0 -> a[0] */
699 int i
= 0, isvector
= 0;
715 return namealloc (sv
);
719 /*---------------------------------------------------------------------------*/
721 char *sim_devect (char *v
) /* a[0] -> a 0 */
726 return spi_devect (v
);
743 return namealloc (sv
);
746 /*---------------------------------------------------------------------------*/
748 char *sim_spivect (char *v
) /* a 0 -> a_0 */
762 return namealloc (sv
);
765 /*---------------------------------------------------------------------------*/
767 char *sim_spidevect (char *v
) /* a_0 -> a 0 */
772 while (v
[i
] != '\0') {
778 while (isdigit ((int)v
[i
])) i
--;
783 return namealloc (sv
);
786 /*--------------------------------------------------------------*/
787 /*--------- useful functions -----------------------------------*/
788 /*--------------------------------------------------------------*/
790 /*--------- log2 -----------------------------------------------*/
792 unsigned long log2 (unsigned long n
)
794 unsigned long log
= 0;
800 /*--------- exp2 -----------------------------------------------*/
802 unsigned long exp2 (unsigned long n
)
810 /*--------- dec_to_bin -----------------------------------------*/
812 void reverse_endianess (char *bin
)
818 buf
= (char*)mbkalloc (l
* sizeof (char));
820 for (i
= 0; i
< l
; i
++)
821 buf
[l
- i
- 1] = bin
[i
];
822 for (i
= 0; i
< l
; i
++)
828 /*--------- dec_to_bin -----------------------------------------*/
831 void sim_hex2bin (char *bin
, char *hex
)
834 int l
= strlen (hex
);
836 for (i
= 0; i
< l
; i
++)
839 strcpy (&bin
[4 * i
], "0000");
842 strcpy (&bin
[4 * i
], "0001");
845 strcpy (&bin
[4 * i
], "0010");
848 strcpy (&bin
[4 * i
], "0011");
851 strcpy (&bin
[4 * i
], "0100");
854 strcpy (&bin
[4 * i
], "0101");
857 strcpy (&bin
[4 * i
], "0110");
860 strcpy (&bin
[4 * i
], "0111");
863 strcpy (&bin
[4 * i
], "1000");
866 strcpy (&bin
[4 * i
], "1001");
869 strcpy (&bin
[4 * i
], "1010");
872 strcpy (&bin
[4 * i
], "1011");
875 strcpy (&bin
[4 * i
], "1100");
878 strcpy (&bin
[4 * i
], "1101");
881 strcpy (&bin
[4 * i
], "1110");
884 strcpy (&bin
[4 * i
], "1111");
887 fprintf (stderr
, "malformed hex value `%s'\n", hex
);
888 strcpy (&bin
[4 * i
], "0000");
892 char *sim_vectorize (char *radix
, int index
)
896 sprintf (buf
, "%s %d", radix
, index
);
897 return namealloc (buf
);
900 /* sim_node_clean permet d'effacer les ic, pwl, addmeaure du node */
901 void sim_node_clean(sim_model
*model
, char *name
)
906 sim_find_by_name( name
,
907 sim_model_get_lofig( model
),
913 sim_ic_clear( model
, name
, SIM_IC_LOCON
);
915 sim_ic_clear( model
, name
, SIM_IC_SIGNAL
);
917 sim_input_clear( model
, name
);
921 static mbkContext
*mc
=NULL
;
923 lofig_list
*sim_GetNetlist(char *name
)
928 mc
=mbkCreateContext();
930 mbkSwitchContext(mc
);
931 lf
=getloadedlofig(name
);
932 mbkSwitchContext(mc
);
936 sim_model
*simDuplicate(sim_model
*src
)
939 sim_ic
*ic
, *ic0
, *icprev
;
940 sim_input
*si
, *si0
, *siprev
;
941 sim_measure
*sme
, *sme0
, *smeprev
;
942 sim_measure_detail
*smd
, *smd0
, *smdprev
;
946 sm
=(sim_model
*)mbkalloc(sizeof(sim_model
));
947 memcpy(sm
, src
, sizeof(sim_model
));
949 sm
->FIG
=sim_GetNetlist(src
->FIG
->NAME
);
952 sm
->FIG
=rduplofig(src
->FIG
);
955 mbkSwitchContext(mc
);
956 addhtitem(HT_LOFIG
, sm
->FIG
->NAME
, (long)sm
->FIG
);
957 sm
->FIG
->NEXT
=HEAD_LOFIG
;
959 mbkSwitchContext(mc
);
961 sm
->PARAMETER
.TECHNOFILELIST
=dupchainlst(sm
->PARAMETER
.TECHNOFILELIST
);
963 if (sm
->PARAMETER
.TOOL_CMD
!=NULL
)
964 sm
->PARAMETER
.TOOL_CMD
=mbkstrdup(sm
->PARAMETER
.TOOL_CMD
);
965 if (sm
->PARAMETER
.TOOL_OUTFILE
!=NULL
)
966 sm
->PARAMETER
.TOOL_OUTFILE
=mbkstrdup(sm
->PARAMETER
.TOOL_OUTFILE
);
967 if (sm
->OUTPUT_FILE
!=NULL
)
968 sm
->OUTPUT_FILE
=mbkstrdup(sm
->OUTPUT_FILE
);
970 for (ic
=src
->LIC
, icprev
=NULL
; ic
!=NULL
; icprev
=ic0
, ic
=ic
->NEXT
)
972 ic0
=(sim_ic
*)mbkalloc(sizeof(sim_ic
));
973 memcpy(ic0
, ic
, sizeof(sim_ic
));
974 if (icprev
!=NULL
) icprev
->NEXT
=ic0
; else sm
->LIC
=ic0
;
975 ic0
->NODENAME
=dupchainlst(ic
->NODENAME
);
979 sm
->HTINPUT
=addht(10);
980 for (si
=src
->LINPUT
, siprev
=NULL
; si
!=NULL
; siprev
=si0
, si
=si
->NEXT
)
982 si0
=(sim_input
*)mbkalloc(sizeof(sim_input
));
983 memcpy(si0
, si
, sizeof(sim_input
));
984 if (siprev
!=NULL
) siprev
->NEXT
=si0
; else sm
->LINPUT
=si0
;
985 addhtitem(sm
->HTINPUT
, si0
->LOCON_NAME
, (long)si0
);
989 for (sme
=src
->LMEASURE
, smeprev
=NULL
; sme
!=NULL
; smeprev
=sme0
, sme
=sme
->NEXT
)
991 sme0
=(sim_measure
*)mbkalloc(sizeof(sim_measure
));
992 memcpy(sme0
, sme
, sizeof(sim_measure
));
993 if (smeprev
!=NULL
) smeprev
->NEXT
=sme0
; else sm
->LMEASURE
=sme0
;
994 sme0
->NODENAME
=dupchainlst(sme
->NODENAME
);
996 for (smd
=sme
->DETAIL
, smdprev
=NULL
; smd
!=NULL
; smdprev
=smd0
, smd
=smd
->NEXT
)
998 smd0
=(sim_measure_detail
*)mbkalloc(sizeof(sim_measure_detail
));
999 memcpy(smd0
, smd
, sizeof(sim_measure_detail
));
1000 if (smdprev
!=NULL
) smdprev
->NEXT
=smd0
; else sme0
->DETAIL
=smd0
;
1005 for (smt
=src
->TRANSLATION
; smt
!=NULL
; smt
=smt
->NEXT
)
1007 sim_input_add_alias(sm
, smt
->signal
, smt
->equiv
);
1011 mfe_duprules(&(sm
->LRULES
),src
->LRULES
);
1012 mfe_duplabels(&(sm
->LLABELS
),src
->LLABELS
);
1020 sim_model
*sim_SaveContext(sim_model
*src
, char *label
)
1023 sm
=simDuplicate(src
);
1027 if (src
->CONTEXT_HT
==NULL
) src
->CONTEXT_HT
=addht(15);
1028 addhtitem(src
->CONTEXT_HT
, namealloc(label
), (long)sm
);
1033 sim_model
*sim_GetSavedContext(sim_model
*src
, char *label
)
1036 if (label
!=NULL
&& src
->CONTEXT_HT
!=NULL
)
1038 if ((l
=gethtitem(src
->CONTEXT_HT
, namealloc(label
)))!=EMPTYHT
) return (sim_model
*)l
;
1043 static void _simDriveIC(sim_ic
*si
, FILE *f
)
1045 char *name
, *func
, val
[100];
1048 case SIM_IC_VOLTAGE
:
1049 func
="sim_AddInitVoltage";
1050 sprintf(val
, "%e", si
->UIC
.VOLTAGE
.VOLTAGE
);
1053 func
="sim_AddInitLevel";
1054 sprintf(val
, "%d", si
->UIC
.LEVEL
.LEVEL
==SIM_ZERO
?0:1);
1060 case SIM_IC_LOCON
: name
=si
->WHERE
.LOCON_NAME
; break;
1061 case SIM_IC_SIGNAL
: name
=si
->WHERE
.SIGNAL_NAME
; break;
1062 case SIM_IC_SIGNAL_NODE
: name
=si
->WHERE
.SIGNAL_NODE_NAME
; break;
1065 fprintf(f
," %s ( SC, \"%s\", %s);\n", func
, name
, val
);
1068 static void _simDriveDC(sim_input
*si
, FILE *f
)
1070 char *func
, val
[100];
1075 switch(si
->UINPUT
.INPUT_STUCK
.TYPE
)
1077 case SIM_STUCK_VALUE
:
1078 func
="sim_AddStuckVoltage";
1079 sprintf(val
, "%e", si
->UINPUT
.INPUT_STUCK
.MODEL
.STUCK_VOLTAGE
.VALUE
);
1081 case SIM_STUCK_LEVEL
:
1082 func
="sim_AddStuckLevel";
1083 sprintf(val
, "%d", si
->UINPUT
.INPUT_STUCK
.MODEL
.STUCK_LEVEL
.VALUE
==SIM_ZERO
?0:1);
1087 fprintf(f
," %s ( SC, \"%s\", %s);\n", func
, si
->LOCON_NAME
, val
);
1091 switch(si
->UINPUT
.INPUT_SLOPE
.TYPE
)
1093 case SIM_SLOPE_SINGLE
:
1094 fprintf(f
," sim_AddSlope ( SC, \"%s\", %e, %e, '%c');\n",
1096 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_SINGLE
.TSTART
,
1097 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_SINGLE
.TRISE
,
1098 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_SINGLE
.TRANSITION
==SIM_RISE
?'u':'d'
1101 case SIM_SLOPE_PATTERN
:
1102 fprintf(f
," sim_AddWaveForm ( SC, \"%s\", %e, %e, %e, \"%s\");\n",
1104 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_PATTERN
.TRISE
,
1105 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_PATTERN
.TFALL
,
1106 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_PATTERN
.PERIOD
,
1107 si
->UINPUT
.INPUT_SLOPE
.MODEL
.SLOPE_PATTERN
.PATTERN
1114 fprintf(stderr
,"can't drive pointed functions used in ...\n");
1120 static void _simDriveMEAS(sim_measure
*sm
, FILE *f
)
1125 case SIM_MEASURE_CURRENT
:
1126 func
="sim_AddMeasureCurrent";
1128 case SIM_MEASURE_VOLTAGE
:
1129 func
="sim_AddMeasure";
1135 case SIM_MEASURE_LOCON
: name
=sm
->WHERE
.LOCON_NAME
; break;
1136 case SIM_MEASURE_SIGNAL
: name
=sm
->WHERE
.SIGNAL_NAME
; break;
1137 case SIM_MEASURE_SIGNAL_NODE
: name
=sm
->WHERE
.SIGNAL_NODE_NAME
; break;
1140 fprintf(f
," %s ( SC, \"%s\");\n", func
, name
);
1143 void _simDrivePARAMS(sim_model
*sm
, FILE *f
)
1148 switch(sm
->PARAMETER
.TOOL
)
1150 case SIM_TOOL_NGSPICE
: tool
="NGSPICE"; break;
1151 case SIM_TOOL_LTSPICE
: tool
="LTSPICE"; break;
1152 case SIM_TOOL_HSPICE
: tool
="HSPICE"; break;
1153 case SIM_TOOL_MSPICE
: tool
="MSPICE"; break;
1154 case SIM_TOOL_TITAN
: tool
="TITAN"; break;
1155 case SIM_TOOL_TITAN7
: tool
="TITANv7"; break;
1156 case SIM_TOOL_ELDO
: tool
="ELDO"; break;
1157 case SIM_TOOL_DEFAULT
: tool
="DEFAULT"; break;
1161 fprintf(f
," sim_SetSimulatorType ( SC, \"%s\");\n",tool
);
1162 fprintf(f
," sim_SetSimulationOutputFile ( SC, \"%s\");\n", sm
->PARAMETER
.TOOL_OUTFILE
);
1163 fprintf(f
," sim_SetSimulationCall ( SC, \"%s\");\n", sm
->PARAMETER
.TOOL_CMD
);
1164 fprintf(f
," sim_SetSimulationStep ( SC, %e);\n", sm
->PARAMETER
.TRANSIANT_STEP
);
1165 fprintf(f
," sim_SetSimulationTime ( SC, %e);\n", sm
->PARAMETER
.TRANSIANT_TMAX
);
1167 fprintf(f
," sim_SetSimulationTemp ( SC, %e);\n", sm
->PARAMETER
.TEMP
);
1168 fprintf(f
," sim_SetSimulationSupply ( SC, %e);\n", sm
->PARAMETER
.ALIM_VOLTAGE
);
1169 fprintf(f
," sim_SetSimulationSlope ( SC, %e);\n", sm
->PARAMETER
.SLOPE
);
1170 fprintf(f
," sim_SetSlopeVTH ( SC, %e, %e);\n", sm
->PARAMETER
.VTH_LOW
, sm
->PARAMETER
.VTH_HIGH
);
1171 fprintf(f
," sim_SetDelayVTH ( SC, %e);\n", sm
->PARAMETER
.VTH
);
1172 fprintf(f
," sim_DriveTransistorAsInstance ( SC, '%c');\n", sm
->PARAMETER
.TRANSISTOR_AS_INSTANCE
?'y':'n');
1174 if (sm
->PARAMETER
.TECHNOFILELIST
!=NULL
) fprintf(f
,"\n");
1175 for (cl
=sm
->PARAMETER
.TECHNOFILELIST
; cl
!=NULL
; cl
=cl
->NEXT
)
1176 fprintf(f
," sim_AddSimulationTechnoFile ( SC, \"%s\");\n", (char *)cl
->DATA
);
1181 void _simDriveALIASES(sim_model
*sm
, FILE *f
)
1185 if (sm
->TRANSLATION
!=NULL
) fprintf(f
,"\n");
1186 for (st
=sm
->TRANSLATION
; st
!=NULL
; st
=st
->NEXT
)
1188 fprintf(f
," sim_AddAlias ( SC, \"%s\", \"%s\");\n",st
->signal
, st
->equiv
);
1191 void sim_DriveContext(sim_model
*sm
, FILE *f
)
1197 fprintf(f
,"void SimModel_%ld()\n{\n",sm
->NUMBER
);
1198 fprintf(f
," SC = sim_CreateContext(sim_GetNetlist(\"%s\"));\n\n",sm
->FIG
->NAME
);
1199 _simDrivePARAMS(sm
, f
);
1200 for (si
=sm
->LIC
; si
!=NULL
; si
=si
->NEXT
) _simDriveIC(si
, f
);
1201 for (sin
=sm
->LINPUT
; sin
!=NULL
; sin
=sin
->NEXT
) _simDriveDC(sin
, f
);
1202 for (sme
=sm
->LMEASURE
; sme
!=NULL
; sme
=sme
->NEXT
) _simDriveMEAS(sme
, f
);
1203 _simDriveALIASES(sm
, f
);
1208 static sim_model
*__SIM_CTX__
;
1210 void sim_set_ctx(sim_model
*ctx
)
1215 sim_model
*sim_get_ctx()
1220 // Renvoie le nom hierarchique du signal en fonction du simulateur utilise
1221 char *sim_get_hier_signame (sim_model
*model
, char *signal
)
1225 if (!model
|| !signal
) return NULL
;
1226 switch( sim_parameter_get_tool( model
) ) {
1228 case SIM_TOOL_TITAN
:
1229 case SIM_TOOL_TITAN7
:
1230 case SIM_TOOL_HSPICE
:
1231 case SIM_TOOL_MSPICE
:
1232 case SIM_TOOL_NGSPICE
:
1233 sprintf( buf
, "x%s.%s", sim_model_get_lofig( model
)->NAME
,
1236 case SIM_TOOL_LTSPICE
:
1237 case SIM_TOOL_SPICE
:
1238 sprintf( buf
, "%s:%s", sim_model_get_lofig( model
)->NAME
,
1242 return namealloc (buf
);
1245 void sim_get_THR(sim_model
*model
, SIM_FLOAT
*th_in
, SIM_FLOAT
*th_out
, SIM_FLOAT
*slopelow
, SIM_FLOAT
*slopehigh
)
1247 if (th_in
!=NULL
) *th_in
=sim_parameter_get_vss(model
, 'i')+(sim_parameter_get_alim(model
, 'i')-sim_parameter_get_vss(model
, 'i'))*model
->PARAMETER
.VTHSTART
;
1248 if (th_out
!=NULL
) *th_out
=sim_parameter_get_vss(model
, 'o')+(sim_parameter_get_alim(model
, 'o')-sim_parameter_get_vss(model
, 'o'))*model
->PARAMETER
.VTHEND
;
1249 if (slopelow
!=NULL
) *slopelow
= sim_parameter_get_vss(model
, 'o')+(sim_parameter_get_alim(model
, 'o')-sim_parameter_get_vss(model
, 'o'))*model
->PARAMETER
.VTH_LOW
;
1250 if (slopehigh
!=NULL
) *slopehigh
= sim_parameter_get_vss(model
, 'o')+(sim_parameter_get_alim(model
, 'o')-sim_parameter_get_vss(model
, 'o'))*model
->PARAMETER
.VTH_HIGH
;
1254 void sim_get_multivoltage_values (cone_list
*cone
, losig_list
*ls
, double *vssl
, double *vssh
, double *vddl
, double *vddh
)
1258 power
=cns_get_multivoltage(cone
);
1260 power
=cns_get_signal_multivoltage(ls
);
1263 *vssl
=power
->VSSMIN
;
1264 *vssh
=power
->VSSMAX
;
1265 *vddl
=power
->VDDMIN
;
1266 *vddh
=power
->VDDMAX
;
1269 *vddl
=*vddh
=V_FLOAT_TAB
[__SIM_POWER_SUPPLY
].VALUE
;
1273 void sim_set_result_file_extension(char mode
, int dc
, char **var
)
1275 switch (V_INT_TAB
[__SIM_TOOL
].VALUE
) {
1277 *var
= SIM_SPICEOUT
;
1279 case SIM_TOOL_TITAN
:
1280 case SIM_TOOL_TITAN7
:
1284 *var
= sensitive_namealloc ("$.tr.t1.measure");
1286 *var
= sensitive_namealloc ("$.tr.t1.ppr");
1291 *var
= sensitive_namealloc ("$.dc.t1.measure");
1293 *var
= sensitive_namealloc ("$.dc.t1.ppr");
1296 case SIM_TOOL_MSPICE
:
1297 case SIM_TOOL_HSPICE
:
1300 case SIM_TOOL_LTSPICE
:
1301 *var
= sensitive_namealloc ("$.log");
1303 case SIM_TOOL_NGSPICE
:
1305 *var
= SIM_SPICEOUT
;