Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / sim / sim_util.c
1 /*****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI AVERTEC */
4 /* */
5 /* Produit : SIM Version 2.00 */
6 /* Fichier : sim_obj.c */
7 /* */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
10 /* */
11 /* Auteur(s) : Gilles Augustins */
12 /* */
13 /*****************************************************************************/
14 #include <semaphore.h>
15
16 #include SIM_H
17 #include "sim.h"
18 #include "sim_util.h"
19
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;
24 double SIM_VTH = 0.5;
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;
42
43
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);
52
53 int sim_SetPowerSupply (lofig_list *lofig)
54 {
55 float supply;
56
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;
61 return 1;
62 }
63 return 0;
64 }
65
66 static int donesimInFork=0;
67 mbk_sem_t simInFork;
68
69 /*static void sim_destroy_sem()
70 {
71 mbk_sem_destroy(simInFork, &simInForkStatic, "simvfork");
72 }*/
73 void simenv ()
74 {
75 char *env;
76 int stoprequest=0;
77
78 if (!donesimInFork) {
79 mbk_sem_init(&simInFork, 1);
80 donesimInFork++;
81 }
82
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;
87 }
88 else SIM_OUTLOAD = SIM_TRANSISTOR_OUTLOAD;
89
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;
97 }
98 }
99 if (V_INT_TAB[__SIM_TOOL].SET && !V_INT_TAB[__SIM_TOOLMODEL].SET) {
100 switch (V_INT_TAB[__SIM_TOOL].VALUE) {
101 case SIM_TOOL_SPICE:
102 case SIM_TOOL_LTSPICE:
103 case SIM_TOOL_NGSPICE:
104 V_INT_TAB[__SIM_TOOLMODEL].VALUE = SIM_TOOLMODEL_SPICE;
105 break;
106 case SIM_TOOL_HSPICE:
107 case SIM_TOOL_MSPICE:
108 V_INT_TAB[__SIM_TOOLMODEL].VALUE = SIM_TOOLMODEL_HSPICE;
109 break;
110 case SIM_TOOL_ELDO:
111 V_INT_TAB[__SIM_TOOLMODEL].VALUE = SIM_TOOLMODEL_ELDO;
112 break;
113 case SIM_TOOL_TITAN:
114 V_INT_TAB[__SIM_TOOLMODEL].VALUE = SIM_TOOLMODEL_TITAN;
115 break;
116 }
117 }
118
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;
121 }
122
123 switch (V_INT_TAB[__SIM_TOOL].VALUE) {
124 case SIM_TOOL_ELDO:
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;
136 break;
137 case SIM_TOOL_TITAN:
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;
151 break;
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;
164 break;
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;
176 break;
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;
189 break;
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;
202 break;
203 default:
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;
210 }
211
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;
215 }
216 else V_BOOL_TAB[__SIM_USE_PRINT].VALUE = 0;
217 }
218
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 ;
228 }
229
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;
233
234 if ((env = V_STR_TAB[__SIM_MEAS_CMD].VALUE))
235 {
236 sim_decodeMeasCmdFree();
237 sim_decodeMeasCmd(env);
238 }
239 if ((env = V_STR_TAB[__SIM_EXTRACT_RULE].VALUE))
240 {
241 mfe_freerules(&SIM_EXTRACT_RULE);
242 mfe_addrule(&SIM_EXTRACT_RULE,env);
243 }
244
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;
252
253 SIM_DEFAULT_REMOVE_FILES = V_BOOL_TAB[__SIM_REMOVE_FILES].VALUE?SIM_YES:SIM_NO;
254
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; }
262
263 if (stoprequest) EXIT(1);
264
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; }
269
270 if (stoprequest) EXIT(1);
271 // ---------------------
272 spi_env();
273 }
274
275 void sim_error( char *msg, ... )
276 {
277 va_list arg;
278
279 va_start( arg, msg );
280
281 fflush( stdout );
282 fprintf( stderr, "\n\n *** Fatal error in sim library ***\n" );
283 vfprintf( stderr, msg, arg );
284
285 EXIT(1);
286 }
287
288 void sim_warning( char *msg, ... )
289 {
290 va_list arg;
291 char buf[2048];
292
293 va_start( arg, msg );
294
295 // fflush( stdout );
296 // fprintf( stderr, "\n\n *** Warning in sim library ***\n" );
297 vsprintf( buf, msg, arg );
298 avt_error("sim", -1, AVT_WAR, buf);
299 }
300
301 /*{{{ */
302 /* */
303 /* */
304 /****************************************************************************/
305 locon_list *sim_find_locon(char *name, lofig_list *topfig,
306 locon_list **loconfound, chain_list **listins )
307 {
308 locon_list *locon;
309
310 if (loconfound)
311 {
312 sim_find_by_name(name,topfig,loconfound,NULL,listins);
313 locon = *loconfound;
314 }
315 else
316 sim_find_by_name(name,topfig,&locon,NULL,listins);
317
318 return locon;
319 }
320
321 /*}}}************************************************************************/
322 /*{{{ sim_get_hier_list() */
323 /* */
324 /* */
325 /****************************************************************************/
326 chain_list* sim_get_hier_list(char *hiername)
327 {
328 chain_list *decomp = NULL;
329 char word[1024];
330 int pos, destpos;
331
332 pos = 0;
333 destpos = 0;
334
335 while (hiername[pos] != '\0')
336 {
337 if( hiername[pos] != SEPAR )
338 word[destpos++] = hiername[pos];
339 else
340 {
341 word[destpos] = '\0';
342 destpos = 0;
343 decomp = addchain(decomp,namealloc(word));
344 }
345 pos ++;
346 }
347
348 if (destpos)
349 {
350 word[destpos] = '\0';
351 decomp = addchain(decomp,namealloc(word));
352 }
353
354 return reverse(decomp);
355 }
356
357 /*}}}************************************************************************/
358 /*{{{ */
359 /* */
360 /* */
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.
363
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.
371 OU
372 i1.i2.tr.Z -> la netlist est à plat, le trs s'appelle i1.i2.tr
373 ...
374 */
375 /****************************************************************************/
376 void sim_find_by_name( char *name,
377 lofig_list *topfig,
378 locon_list **loconfound,
379 losig_list **losigfound,
380 chain_list **listins
381 )
382 {
383 chain_list *hiername;
384 locon_list *locon;
385 losig_list *losig;
386
387 hiername = sim_get_hier_list(name);
388
389 if (loconfound)
390 *loconfound = NULL;
391 if (losigfound)
392 *losigfound = NULL;
393 if (listins)
394 *listins = NULL;
395
396 // recherche d'abord sur l interface
397 locon = findLoconInFig(topfig,name);
398 // puis les signaux
399 losig = findLosigInFig(topfig,name);
400
401 if (!locon && !losig)
402 {
403 sim_find_by_nameInt(name,topfig,loconfound,losigfound,listins,hiername);
404 }
405 else
406 {
407 if (loconfound)
408 *loconfound = locon;
409 if (losigfound)
410 *losigfound = losig;
411 }
412
413 freechain(hiername);
414
415 }
416
417 /*}}}************************************************************************/
418 /*{{{ */
419 /* */
420 /* */
421 /****************************************************************************/
422 static inline locon_list *findLoconInFig(lofig_list *fig, char *loconName)
423 {
424 locon_list *locon = fig->LOCON;
425
426 while (locon && locon->NAME != loconName)
427 locon = locon->NEXT;
428
429 return locon;
430 }
431
432 /*}}}************************************************************************/
433 /*{{{ */
434 /* */
435 /* */
436 /****************************************************************************/
437 static inline locon_list *findLoconInLoins(loins_list *ins, char *loconName,
438 char *loconName2)
439 {
440 locon_list *locon = ins->LOCON;
441
442 if (loconName2)
443 while (locon && locon->NAME != loconName && locon->NAME != loconName2)
444 locon = locon->NEXT;
445 else
446 while (locon && locon->NAME != loconName)
447 locon = locon->NEXT;
448
449 return locon;
450 }
451
452 /*}}}************************************************************************/
453 /*{{{ */
454 /* */
455 /* */
456 /****************************************************************************/
457 static inline losig_list *findLosigInFig(lofig_list *fig, char *losigName)
458 {
459 losig_list *losig = fig->LOSIG;
460
461 while (losig && getsigname(losig) != losigName)
462 losig = losig->NEXT;
463
464 return losig;
465 }
466
467 /*}}}************************************************************************/
468 /*{{{ */
469 /* */
470 /* */
471 /****************************************************************************/
472 static inline loins_list *findLoinsInFig(lofig_list *fig, char *loinsName)
473 {
474 loins_list *loins = fig->LOINS;
475
476 while (loins && loins->INSNAME != loinsName)
477 loins = loins->NEXT;
478
479 return loins;
480 }
481
482 /*}}}************************************************************************/
483 /*{{{ */
484 /* */
485 /* */
486 /****************************************************************************/
487 static inline lotrs_list *findLotrsInFig(lofig_list *fig, char *lotrsName)
488 {
489 lotrs_list *lotrs = fig->LOTRS;
490
491 while (lotrs && (!lotrs->TRNAME || lotrs->TRNAME != lotrsName))
492 lotrs = lotrs->NEXT;
493
494 return lotrs;
495 }
496
497 /*}}}************************************************************************/
498 /*{{{ */
499 /* */
500 /* */
501 /****************************************************************************/
502 static inline locon_list *findLoconInTrs(lotrs_list *trs, char *loconName,
503 char *loconName2)
504 {
505 locon_list *locon;
506
507 if (!trs)
508 locon = NULL;
509 else if (trs->GRID->NAME == loconName || trs->GRID->NAME == loconName2)
510 locon = trs->GRID;
511 else if (trs->SOURCE->NAME == loconName || trs->SOURCE->NAME == loconName2)
512 locon = trs->SOURCE;
513 else if (trs->DRAIN->NAME == loconName || trs->DRAIN->NAME == loconName2)
514 locon = trs->DRAIN;
515 else if (trs->BULK &&
516 (trs->BULK->NAME == loconName || trs->BULK->NAME == loconName2))
517 locon = trs->BULK;
518 else
519 locon = NULL;
520
521 return locon;
522 }
523
524
525
526 /*}}}************************************************************************/
527 /*{{{ */
528 /* */
529 /* */
530 /****************************************************************************/
531 locon_list* sim_find_by_nameInt(char *name,
532 lofig_list *topfig,
533 locon_list **loconfound,
534 losig_list **losigfound,
535 chain_list **listins,
536 chain_list *hiername)
537 {
538 loins_list *loins;
539 locon_list *locon = NULL;
540 losig_list *losig = NULL;
541 lotrs_list *lotrs;
542 char tmpbuf[BUFSIZ], nomtrs[BUFSIZ], *tmp, *insname, *signame;
543 chain_list *chainx, *ins = NULL, *headTrs;
544 lofig_list *figx;
545
546 // descend la hiérarchie. Les noms sont de la forme
547 // A.B.locon
548 // A.tr.locon
549 // A.losig
550 for (figx = topfig, chainx = hiername; chainx; chainx = chainx->NEXT)
551 {
552 insname = (char*)chainx->DATA;
553 if ((loins = findLoinsInFig(figx,insname)))
554 {
555 ins = addchain(ins,loins);
556 figx = getlofig(loins->FIGNAME,'A');
557 }
558 else
559 break;
560 }
561
562 headTrs = chainx;
563 signame = insname; // the last visited is a signal name
564
565 /* C'est sur une instance */
566 if (ins)
567 {
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 */
571 chainx = ins ;
572 ins = ins->NEXT ;
573 chainx->NEXT = NULL ;
574 freechain( chainx );
575
576 }
577
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)
581 {
582 // creation of transistor name
583 strcpy(nomtrs,(char*)headTrs->DATA);
584 for (chainx = headTrs->NEXT; chainx->NEXT; chainx = chainx->NEXT)
585 {
586 sprintf(tmpbuf,"%s%c%s",nomtrs,SEPAR,(char*)chainx->DATA);
587 strcpy(nomtrs,tmpbuf);
588 }
589
590 if ((tmp = namefind(nomtrs)))
591 lotrs = findLotrsInFig(figx,tmp);
592 else
593 lotrs = NULL;
594 locon = findLoconInTrs(lotrs,chainx->DATA,name);
595 }
596
597 // C'est peut etre un signal
598 if (!locon)
599 losig = findLosigInFig(figx,signame);
600
601 if (locon)
602 {
603 if (loconfound)
604 *loconfound = locon;
605 if (listins)
606 *listins = reverse(ins);
607 else
608 freechain(ins);
609 }
610 else if (listins)
611 {
612 freechain(ins);
613 *listins = NULL;
614 }
615
616 if (losigfound)
617 *losigfound = losig;
618
619
620 return locon;
621 }
622
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
626 plus hautes. */
627
628 chain_list *sim_getfiglist( lofig_list *lofig )
629 {
630 chain_list *last;
631 chain_list *head;
632 chain_list *done;
633 chain_list *new;
634 loins_list *loins;
635 lofig_list *figins;
636
637 head = addchain( NULL, lofig );
638 last = head;
639 done = head;
640
641 while( done ) {
642
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 );
650 last->NEXT = new;
651 last = new;
652 }
653 }
654 done = done->NEXT;
655 }
656
657 for( done = head->NEXT ; done ; done = done->NEXT ) {
658 lofig = (lofig_list*)(done->DATA);
659 lofig->USER = delptype( lofig->USER, SIM_MARKED );
660 }
661
662 return reverse( head );
663 }
664
665 static chain_list *_sim_getallfiglist(ht *fight, chain_list *head, lofig_list *lofig )
666 {
667 loins_list *loins;
668 lofig_list *figins;
669
670 for( loins = lofig->LOINS ; loins!=NULL ; loins = loins->NEXT )
671 {
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);
676 }
677
678 return head;
679 }
680
681 chain_list *sim_getallfiglist(lofig_list *lofig )
682 {
683 chain_list *head;
684 ht *fight;
685 fight=addht(10);
686
687 head=_sim_getallfiglist(fight, NULL, lofig);
688
689 delht(fight);
690 return head;
691 }
692
693
694 /*---------------------------------------------------------------------------*/
695
696 char *sim_vect (char *v) /* a 0 -> a[0] */
697 {
698 char sv[1024];
699 int i = 0, isvector = 0;
700
701 while (v[i] != '\0')
702 if (v[i] != ' ') {
703 sv[i] = v[i];
704 i++;
705 }
706 else {
707 isvector = 1;
708 sv[i++] = '[';
709 }
710
711 if (isvector)
712 sv[i++] = ']';
713
714 sv[i] = '\0';
715 return namealloc (sv);
716 }
717
718
719 /*---------------------------------------------------------------------------*/
720
721 char *sim_devect (char *v) /* a[0] -> a 0 */
722 {
723 char sv[1024];
724 int i = 0;
725
726 return spi_devect (v);
727 while (v[i] != '\0')
728 switch (v[i]) {
729 case '[':
730 case '(':
731 sv[i++] = ' ';
732 break;
733 case ']':
734 case ')':
735 sv[i++] = '\0';
736 break;
737 default:
738 sv[i] = v[i];
739 i++;
740 }
741
742 sv[i] = '\0';
743 return namealloc (sv);
744 }
745
746 /*---------------------------------------------------------------------------*/
747
748 char *sim_spivect (char *v) /* a 0 -> a_0 */
749 {
750 char sv[1024];
751 int i = 0;
752
753 while (v[i] != '\0')
754 if (v[i] != ' ') {
755 sv[i] = v[i];
756 i++;
757 }
758 else
759 sv[i++] = '_';
760
761 sv[i] = '\0';
762 return namealloc (sv);
763 }
764
765 /*---------------------------------------------------------------------------*/
766
767 char *sim_spidevect (char *v) /* a_0 -> a 0 */
768 {
769 char sv[1024];
770 int i = 0;
771
772 while (v[i] != '\0') {
773 sv[i] = v[i];
774 i++;
775 }
776 sv[i--] = '\0';
777
778 while (isdigit ((int)v[i])) i--;
779
780 if (v[i] == '_')
781 sv[i] = ' ';
782
783 return namealloc (sv);
784 }
785
786 /*--------------------------------------------------------------*/
787 /*--------- useful functions -----------------------------------*/
788 /*--------------------------------------------------------------*/
789 #if 0
790 /*--------- log2 -----------------------------------------------*/
791
792 unsigned long log2 (unsigned long n)
793 {
794 unsigned long log = 0;
795 while (n /= 2)
796 log++;
797 return log;
798 }
799
800 /*--------- exp2 -----------------------------------------------*/
801
802 unsigned long exp2 (unsigned long n)
803 {
804 long exp = 1;
805 while (n--)
806 exp *= 2;
807 return exp;
808 }
809 #endif
810 /*--------- dec_to_bin -----------------------------------------*/
811
812 void reverse_endianess (char *bin)
813 {
814 int i, l;
815 char *buf;
816
817 l = strlen (bin);
818 buf = (char*)mbkalloc (l * sizeof (char));
819
820 for (i = 0; i < l; i++)
821 buf[l - i - 1] = bin[i];
822 for (i = 0; i < l; i++)
823 bin[i] = buf[i];
824
825 mbkfree(buf);
826 }
827
828 /*--------- dec_to_bin -----------------------------------------*/
829
830
831 void sim_hex2bin (char *bin, char *hex)
832 {
833 int i;
834 int l = strlen (hex);
835
836 for (i = 0; i < l; i++)
837 switch (hex[i]) {
838 case '0':
839 strcpy (&bin[4 * i], "0000");
840 break;
841 case '1':
842 strcpy (&bin[4 * i], "0001");
843 break;
844 case '2':
845 strcpy (&bin[4 * i], "0010");
846 break;
847 case '3':
848 strcpy (&bin[4 * i], "0011");
849 break;
850 case '4':
851 strcpy (&bin[4 * i], "0100");
852 break;
853 case '5':
854 strcpy (&bin[4 * i], "0101");
855 break;
856 case '6':
857 strcpy (&bin[4 * i], "0110");
858 break;
859 case '7':
860 strcpy (&bin[4 * i], "0111");
861 break;
862 case '8':
863 strcpy (&bin[4 * i], "1000");
864 break;
865 case '9':
866 strcpy (&bin[4 * i], "1001");
867 break;
868 case 'a': case 'A':
869 strcpy (&bin[4 * i], "1010");
870 break;
871 case 'b': case 'B':
872 strcpy (&bin[4 * i], "1011");
873 break;
874 case 'c': case 'C':
875 strcpy (&bin[4 * i], "1100");
876 break;
877 case 'd': case 'D':
878 strcpy (&bin[4 * i], "1101");
879 break;
880 case 'e': case 'E':
881 strcpy (&bin[4 * i], "1110");
882 break;
883 case 'f': case 'F':
884 strcpy (&bin[4 * i], "1111");
885 break;
886 default:
887 fprintf (stderr, "malformed hex value `%s'\n", hex);
888 strcpy (&bin[4 * i], "0000");
889 }
890 }
891
892 char *sim_vectorize (char *radix, int index)
893 {
894 char buf[2048];
895
896 sprintf (buf, "%s %d", radix, index);
897 return namealloc (buf);
898 }
899
900 /* sim_node_clean permet d'effacer les ic, pwl, addmeaure du node */
901 void sim_node_clean(sim_model *model, char *name)
902 {
903 locon_list *locon ;
904 losig_list *losig ;
905
906 sim_find_by_name( name,
907 sim_model_get_lofig( model ),
908 &locon,
909 &losig,
910 NULL
911 );
912 if( locon )
913 sim_ic_clear( model, name, SIM_IC_LOCON );
914 if( losig )
915 sim_ic_clear( model, name, SIM_IC_SIGNAL );
916
917 sim_input_clear( model, name);
918 }
919
920
921 static mbkContext *mc=NULL;
922
923 lofig_list *sim_GetNetlist(char *name)
924 {
925 lofig_list *lf;
926 if (mc==NULL)
927 {
928 mc=mbkCreateContext();
929 }
930 mbkSwitchContext(mc);
931 lf=getloadedlofig(name);
932 mbkSwitchContext(mc);
933 return lf;
934 }
935
936 sim_model *simDuplicate(sim_model *src)
937 {
938 sim_model *sm;
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;
943 sim_translate *smt;
944
945 // base
946 sm=(sim_model *)mbkalloc(sizeof(sim_model));
947 memcpy(sm, src, sizeof(sim_model));
948
949 sm->FIG=sim_GetNetlist(src->FIG->NAME);
950 if (sm->FIG==NULL)
951 {
952 sm->FIG=rduplofig(src->FIG);
953 lofigchain(sm->FIG);
954 // renommage ?
955 mbkSwitchContext(mc);
956 addhtitem(HT_LOFIG, sm->FIG->NAME, (long)sm->FIG);
957 sm->FIG->NEXT=HEAD_LOFIG;
958 HEAD_LOFIG=sm->FIG;
959 mbkSwitchContext(mc);
960 }
961 sm->PARAMETER.TECHNOFILELIST=dupchainlst(sm->PARAMETER.TECHNOFILELIST);
962
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);
969 // sim_ic
970 for (ic=src->LIC, icprev=NULL; ic!=NULL; icprev=ic0, ic=ic->NEXT)
971 {
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);
976 }
977
978 // sim_input
979 sm->HTINPUT=addht(10);
980 for (si=src->LINPUT, siprev=NULL; si!=NULL; siprev=si0, si=si->NEXT)
981 {
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);
986 }
987
988 // sim_measure
989 for (sme=src->LMEASURE, smeprev=NULL; sme!=NULL; smeprev=sme0, sme=sme->NEXT)
990 {
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);
995
996 for (smd=sme->DETAIL, smdprev=NULL; smd!=NULL; smdprev=smd0, smd=smd->NEXT)
997 {
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;
1001 }
1002 }
1003
1004 // sim_translate
1005 for (smt=src->TRANSLATION; smt!=NULL; smt=smt->NEXT)
1006 {
1007 sim_input_add_alias(sm, smt->signal, smt->equiv);
1008 }
1009
1010 // sim extraction
1011 mfe_duprules(&(sm->LRULES),src->LRULES);
1012 mfe_duplabels(&(sm->LLABELS),src->LLABELS);
1013
1014 return sm;
1015 }
1016
1017 #if 0
1018 static int count=1;
1019
1020 sim_model *sim_SaveContext(sim_model *src, char *label)
1021 {
1022 sim_model *sm;
1023 sm=simDuplicate(src);
1024 sm->NUMBER=count++;
1025 if (label!=NULL)
1026 {
1027 if (src->CONTEXT_HT==NULL) src->CONTEXT_HT=addht(15);
1028 addhtitem(src->CONTEXT_HT, namealloc(label), (long)sm);
1029 }
1030 return sm;
1031 }
1032
1033 sim_model *sim_GetSavedContext(sim_model *src, char *label)
1034 {
1035 long l;
1036 if (label!=NULL && src->CONTEXT_HT!=NULL)
1037 {
1038 if ((l=gethtitem(src->CONTEXT_HT, namealloc(label)))!=EMPTYHT) return (sim_model *)l;
1039 }
1040 return NULL;
1041 }
1042
1043 static void _simDriveIC(sim_ic *si, FILE *f)
1044 {
1045 char *name, *func, val[100];
1046 switch(si->TYPE)
1047 {
1048 case SIM_IC_VOLTAGE:
1049 func="sim_AddInitVoltage";
1050 sprintf(val, "%e", si->UIC.VOLTAGE.VOLTAGE);
1051 break;
1052 case SIM_IC_LEVEL:
1053 func="sim_AddInitLevel";
1054 sprintf(val, "%d", si->UIC.LEVEL.LEVEL==SIM_ZERO?0:1);
1055 break;
1056 default: EXIT(2);
1057 }
1058 switch(si->LOCATE)
1059 {
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;
1063 default: EXIT(3);
1064 }
1065 fprintf(f," %s ( SC, \"%s\", %s);\n", func, name, val);
1066 }
1067
1068 static void _simDriveDC(sim_input *si, FILE *f)
1069 {
1070 char *func, val[100];
1071
1072 switch(si->TYPE)
1073 {
1074 case SIM_STUCK:
1075 switch(si->UINPUT.INPUT_STUCK.TYPE)
1076 {
1077 case SIM_STUCK_VALUE:
1078 func="sim_AddStuckVoltage";
1079 sprintf(val, "%e", si->UINPUT.INPUT_STUCK.MODEL.STUCK_VOLTAGE.VALUE);
1080 break;
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);
1084 break;
1085 default: EXIT(2);
1086 }
1087 fprintf(f," %s ( SC, \"%s\", %s);\n", func, si->LOCON_NAME, val);
1088 break;
1089
1090 case SIM_SLOPE:
1091 switch(si->UINPUT.INPUT_SLOPE.TYPE)
1092 {
1093 case SIM_SLOPE_SINGLE:
1094 fprintf(f," sim_AddSlope ( SC, \"%s\", %e, %e, '%c');\n",
1095 si->LOCON_NAME,
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'
1099 );
1100 break;
1101 case SIM_SLOPE_PATTERN:
1102 fprintf(f," sim_AddWaveForm ( SC, \"%s\", %e, %e, %e, \"%s\");\n",
1103 si->LOCON_NAME,
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
1108 );
1109 break;
1110 default: EXIT(4);
1111 }
1112 break;
1113 case SIM_FUNC:
1114 fprintf(stderr,"can't drive pointed functions used in ...\n");
1115 break;
1116 default: EXIT(5);
1117 }
1118 }
1119
1120 static void _simDriveMEAS(sim_measure *sm, FILE *f)
1121 {
1122 char *name, *func;
1123 switch(sm->WHAT)
1124 {
1125 case SIM_MEASURE_CURRENT:
1126 func="sim_AddMeasureCurrent";
1127 break;
1128 case SIM_MEASURE_VOLTAGE:
1129 func="sim_AddMeasure";
1130 break;
1131 default: EXIT(2);
1132 }
1133 switch(sm->TYPE)
1134 {
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;
1138 default: EXIT(3);
1139 }
1140 fprintf(f," %s ( SC, \"%s\");\n", func, name);
1141 }
1142
1143 void _simDrivePARAMS(sim_model *sm, FILE *f)
1144 {
1145 char *tool;
1146 chain_list *cl;
1147
1148 switch(sm->PARAMETER.TOOL)
1149 {
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;
1158 default: EXIT(4);
1159 }
1160
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);
1166
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');
1173
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);
1177
1178 fprintf(f,"\n");
1179 }
1180
1181 void _simDriveALIASES(sim_model *sm, FILE *f)
1182 {
1183 sim_translate *st;
1184
1185 if (sm->TRANSLATION!=NULL) fprintf(f,"\n");
1186 for (st=sm->TRANSLATION; st!=NULL; st=st->NEXT)
1187 {
1188 fprintf(f," sim_AddAlias ( SC, \"%s\", \"%s\");\n",st->signal, st->equiv);
1189 }
1190 }
1191 void sim_DriveContext(sim_model *sm, FILE *f)
1192 {
1193 sim_ic *si;
1194 sim_input *sin;
1195 sim_measure *sme;
1196
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);
1204 fprintf(f,"}\n\n");
1205 }
1206 #endif
1207
1208 static sim_model *__SIM_CTX__;
1209
1210 void sim_set_ctx(sim_model *ctx)
1211 {
1212 __SIM_CTX__=ctx;
1213 }
1214
1215 sim_model *sim_get_ctx()
1216 {
1217 return __SIM_CTX__;
1218 }
1219
1220 // Renvoie le nom hierarchique du signal en fonction du simulateur utilise
1221 char *sim_get_hier_signame (sim_model *model, char *signal)
1222 {
1223 char buf[BUFSIZ];
1224
1225 if (!model || !signal) return NULL;
1226 switch( sim_parameter_get_tool( model ) ) {
1227 case SIM_TOOL_ELDO:
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,
1234 signal);
1235 break;
1236 case SIM_TOOL_LTSPICE:
1237 case SIM_TOOL_SPICE:
1238 sprintf( buf, "%s:%s", sim_model_get_lofig( model )->NAME,
1239 signal);
1240 break;
1241 }
1242 return namealloc (buf);
1243 }
1244
1245 void sim_get_THR(sim_model *model, SIM_FLOAT *th_in, SIM_FLOAT *th_out, SIM_FLOAT *slopelow, SIM_FLOAT *slopehigh)
1246 {
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;
1251 }
1252
1253
1254 void sim_get_multivoltage_values (cone_list *cone, losig_list *ls, double *vssl, double *vssh, double *vddl, double *vddh)
1255 {
1256 alim_list *power;
1257 if (cone!=NULL)
1258 power=cns_get_multivoltage(cone);
1259 else
1260 power=cns_get_signal_multivoltage(ls);
1261
1262 if(power){
1263 *vssl=power->VSSMIN;
1264 *vssh=power->VSSMAX;
1265 *vddl=power->VDDMIN;
1266 *vddh=power->VDDMAX;
1267 }else{
1268 *vssl=*vssl=0;
1269 *vddl=*vddh=V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1270 }
1271 }
1272
1273 void sim_set_result_file_extension(char mode, int dc, char **var)
1274 {
1275 switch (V_INT_TAB[__SIM_TOOL].VALUE) {
1276 case SIM_TOOL_ELDO:
1277 *var = SIM_SPICEOUT;
1278 break;
1279 case SIM_TOOL_TITAN:
1280 case SIM_TOOL_TITAN7:
1281 if (!dc)
1282 {
1283 if (mode=='m')
1284 *var = sensitive_namealloc ("$.tr.t1.measure");
1285 else if (mode=='p')
1286 *var = sensitive_namealloc ("$.tr.t1.ppr");
1287 }
1288 else
1289 {
1290 if (mode=='m')
1291 *var = sensitive_namealloc ("$.dc.t1.measure");
1292 else if (mode=='p')
1293 *var = sensitive_namealloc ("$.dc.t1.ppr");
1294 }
1295 break;
1296 case SIM_TOOL_MSPICE:
1297 case SIM_TOOL_HSPICE:
1298 *var=SIM_SPICEOUT;
1299 break;
1300 case SIM_TOOL_LTSPICE:
1301 *var = sensitive_namealloc ("$.log");
1302 break;
1303 case SIM_TOOL_NGSPICE:
1304 default:
1305 *var = SIM_SPICEOUT;
1306 }
1307 }