1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: simalsflat.c
6 * Asynchronous Logic Simulator network flattening
7 * From algorithms by: Brent Serbin and Peter J. Gallant
8 * Last maintained by: Steven M. Rubin
9 *
10 * Copyright (c) 2000 Static Free Software.
11 *
12 * Electric(tm) is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * Electric(tm) is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Electric(tm); see the file COPYING. If not, write to
24 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25 * Boston, Mass 02111-1307, USA.
26 *
27 * Static Free Software
28 * 4119 Alpine Road
29 * Portola Valley, California 94028
30 * info@staticfreesoft.com
31 */
32
33 #include "config.h"
34 #if SIMTOOL
35
36 #include "global.h"
37 #include "sim.h"
38 #include "simals.h"
39
40 static MODPTR simals_primptr2;
41 static MODEL **simals_primptr1;
42 static CHAR *simals_mainname = 0;
43
44 /* prototypes for local routines */
45 static BOOLEAN simals_flatten_model(CONPTR);
46 static BOOLEAN simals_process_connect_list(CONPTR, CONPTR);
47 static MODPTR simals_find_model(CHAR*);
48 static EXPTR simals_find_xref_entry(CONPTR, CHAR*);
49 static BOOLEAN simals_process_gate(CONPTR, MODPTR);
50 static BOOLEAN simals_process_io_entry(MODPTR, CONPTR, IOPTR, CHAR);
51 static BOOLEAN simals_create_pin_entry(MODPTR, CHAR*, NODEPTR);
52 static STATPTR simals_create_stat_entry(MODPTR, CHAR*, NODEPTR);
53 static float simals_find_load_value(MODPTR, CHAR*);
54 static BOOLEAN simals_process_set_entry(CONPTR, IOPTR);
55 static BOOLEAN simals_process_function(CONPTR, MODPTR);
56
57 /*
58 * Routine to free all memory associated with this module.
59 */
simals_freeflatmemory(void)60 void simals_freeflatmemory(void)
61 {
62 if (simals_mainname != 0) efree((CHAR *)simals_mainname);
63 }
64
65 /*
66 * Name: simals_flatten_network
67 *
68 * Description:
69 * This procedure calls a series of routines which convert the hierarchical
70 * network description into a flattened database representation. The actual
71 * simulation must take place on the flattened network. Returns true on error.
72 */
simals_flatten_network(void)73 BOOLEAN simals_flatten_network(void)
74 {
75 MODPTR modhead;
76 EXPTR exhead;
77 NODEPTR nodehead;
78 CONPTR temproot;
79
80 simals_nseq = simals_pseq = 0;
81 simals_primptr1 = &simals_primroot;
82
83 /*
84 * create a "dummy" level to use as a mixed signal destination for plotting and
85 * screen display. This level should be bypassed for structure checking and general
86 * simulation, however, so in the following code, references to "simals_cellroot"
87 * have been changed to simals_cellroot->next (pointing to simals_mainproto).
88 * Peter Gallant July 16, 1990
89 */
90 simals_cellroot = (CONPTR) simals_alloc_mem((INTBIG)sizeof(CONNECT));
91 if (simals_cellroot == 0) return(TRUE);
92 simals_cellroot->inst_name = x_("[MIXED_SIGNAL_LEVEL]");
93 simals_cellroot->model_name = simals_cellroot->inst_name;
94 simals_cellroot->exptr = 0;
95 simals_cellroot->parent = 0;
96 simals_cellroot->child = 0;
97 simals_cellroot->next = 0;
98 simals_cellroot->display_page = 0;
99 simals_cellroot->num_chn = 0;
100 temproot = simals_cellroot;
101
102 /* get upper-case version of main proto */
103 if (simals_mainname != 0) efree(simals_mainname);
104 (void)allocstring(&simals_mainname, simals_mainproto->protoname, sim_tool->cluster);
105 simals_convert_to_upper(simals_mainname);
106
107 simals_cellroot = (CONPTR) simals_alloc_mem((INTBIG)sizeof(CONNECT));
108 if (simals_cellroot == 0) return(TRUE);
109 simals_cellroot->inst_name = simals_mainname;
110 simals_cellroot->model_name = simals_cellroot->inst_name;
111 simals_cellroot->exptr = 0;
112 simals_cellroot->parent = 0;
113 simals_cellroot->child = 0;
114 simals_cellroot->next = 0;
115 simals_cellroot->display_page = 0;
116 simals_cellroot->num_chn = 0;
117
118 /* these lines link the mixed level as the head followed by simals_mainproto PJG */
119 temproot->next = simals_cellroot; /* shouldn't this be zero? ... smr */
120 temproot->child = simals_cellroot;
121 simals_cellroot = temproot;
122
123 /* this code checks to see if model simals_mainproto is present in the netlist PJG */
124 modhead = simals_find_model(simals_mainname);
125 if (modhead == 0) return(TRUE);
126 for (exhead = modhead->exptr; exhead; exhead = exhead->next)
127 {
128 if (simals_find_xref_entry(simals_cellroot->next, exhead->node_name) == 0)
129 return(TRUE);
130 }
131
132 if (simals_flatten_model(simals_cellroot->next)) return(TRUE);
133
134 for (nodehead = simals_noderoot; nodehead; nodehead = nodehead->next)
135 {
136 if (nodehead->load < 1.0) nodehead->load = 1.0;
137 nodehead->plot_node = 0;
138 }
139 return(FALSE);
140 }
141
142 /*
143 * Name: simals_flatten_model
144 *
145 * Description:
146 * This procedure flattens a single model. If other models are referenced
147 * in connection statements in the netlist, this routine is called recursively
148 * until a totally flat model is obtained. Returns true on error.
149 *
150 * Calling Arguments:
151 * cellhead = pointer to a data structure containing information about
152 * the model that is going to be flattened
153 */
simals_flatten_model(CONPTR cellhead)154 BOOLEAN simals_flatten_model(CONPTR cellhead)
155 {
156 MODPTR modhead;
157 CONPTR subcell;
158
159 modhead = simals_find_model(cellhead->model_name);
160 if (modhead == 0) return(TRUE);
161 switch (modhead->type)
162 {
163 case 'F':
164 if (simals_process_function(cellhead, modhead)) return(TRUE);
165 break;
166
167 case 'G':
168 if (simals_process_gate(cellhead, modhead)) return(TRUE);
169 break;
170
171 case 'M':
172 if (simals_process_connect_list(cellhead, (CONPTR)modhead->ptr)) return(TRUE);
173 for (subcell = cellhead->child; subcell; subcell = subcell->next)
174 {
175 if (simals_flatten_model(subcell)) return(TRUE);
176 }
177 break;
178 }
179
180 if (modhead->setptr)
181 {
182 if (simals_process_set_entry(cellhead, modhead->setptr)) return(TRUE);
183 }
184 return(FALSE);
185 }
186
187 /*
188 * Name: simals_process_connect_list
189 *
190 * Description:
191 * This procedure steps through the connection list specified by the
192 * connection list pointer (conhead). Values are entered into the cross
193 * reference table for the present level of hierarchy and new data structures
194 * are created for the lower level of hierarchy to store their cross
195 * reference tables. Returns true on error.
196 *
197 * Calling Arguments:
198 * cellhead = pointer to the cross reference data structure for the model
199 * that is going to be flattened
200 * conhead = pointer to a list of connection statements for the model
201 * that is being flattened by this procedure
202 */
simals_process_connect_list(CONPTR cellhead,CONPTR conhead)203 BOOLEAN simals_process_connect_list(CONPTR cellhead, CONPTR conhead)
204 {
205 EXPORT **xrefptr1;
206 CONNECT **cellptr1;
207 EXPTR exhead, xrefhead, xrefptr2;
208 MODPTR modhead;
209 CONPTR cellptr2;
210
211 cellptr1 = &cellhead->child;
212 while (conhead)
213 {
214 cellptr2 = (CONPTR) simals_alloc_mem((INTBIG)sizeof(CONNECT));
215 if (cellptr2 == 0) return(TRUE);
216 cellptr2->inst_name = conhead->inst_name;
217 cellptr2->model_name = conhead->model_name;
218 cellptr2->exptr = 0;
219 cellptr2->parent = cellhead;
220 cellptr2->child = 0;
221 cellptr2->next = 0;
222 cellptr2->display_page = 0;
223 *cellptr1 = cellptr2;
224 cellptr1 = &cellptr2->next;
225
226 modhead = simals_find_model(conhead->model_name);
227 if (modhead == 0) return(TRUE);
228 simals_exptr2 = modhead->exptr;
229 for (exhead = conhead->exptr; exhead; exhead = exhead->next)
230 {
231 xrefhead = simals_find_xref_entry(cellhead, exhead->node_name);
232 if (xrefhead == 0) return(TRUE);
233
234 if (! simals_exptr2)
235 {
236 ttyputerr(_("Insufficient parameters declared for model '%s' in netlist"),
237 conhead->model_name);
238 return(TRUE);
239 }
240
241 xrefptr1 = &cellptr2->exptr;
242 for(;;)
243 {
244 if (*xrefptr1 == 0)
245 {
246 xrefptr2 = (EXPTR) simals_alloc_mem((INTBIG)sizeof(EXPORT));
247 if (xrefptr2 == 0) return(TRUE);
248 xrefptr2->node_name = simals_exptr2->node_name;
249 xrefptr2->nodeptr = xrefhead->nodeptr;
250 xrefptr2->next = 0;
251 *xrefptr1 = xrefptr2;
252 break;
253 }
254 xrefptr2 = *xrefptr1;
255 if (! estrcmp(xrefptr2->node_name, simals_exptr2->node_name))
256 {
257 ttyputerr(_("Node '%s' in model '%s' connected more than once"),
258 simals_exptr2->node_name, conhead->model_name);
259 return(TRUE);
260 }
261 xrefptr1 = &xrefptr2->next;
262 }
263
264 simals_exptr2 = simals_exptr2->next;
265 }
266
267 conhead = conhead->next;
268 }
269 return(FALSE);
270 }
271
272 /*
273 * Name: simals_find_model
274 *
275 * Description:
276 * This procedure returns a pointer to the model referenced by the
277 * calling argument character string. Returns zero on error.
278 *
279 * Calling Arguments:
280 * model_name = pointer to a string which contains the name of the model
281 * to be located by the search procedure
282 */
simals_find_model(CHAR * model_name)283 MODPTR simals_find_model(CHAR *model_name)
284 {
285 MODPTR modhead;
286 CHAR propername[256], *pt;
287
288 /* convert to proper name */
289 estrcpy(propername, model_name);
290 for(pt = propername; *pt != 0; pt++)
291 if (!isalnum(*pt)) *pt = '_';
292
293 modhead = simals_modroot;
294 for(;;)
295 {
296 if (modhead == 0)
297 {
298 ttyputerr(_("ERROR: Model '%s' not found, simulation aborted"), propername);
299 break;
300 }
301 if (! estrcmp(modhead->name, propername)) return(modhead);
302 modhead = modhead->next;
303 }
304 return(0);
305 }
306
307 /*
308 * Name: simals_find_xref_entry
309 *
310 * Description:
311 * This procedure returns the flattened database node number for the
312 * specified model and node name. Returns zero on error.
313 *
314 * Calling Arguments:
315 * cellhead = pointer to the xref table for the model being processed
316 * name = pointer to a char string containing the node name
317 */
simals_find_xref_entry(CONPTR cellhead,CHAR * name)318 EXPTR simals_find_xref_entry(CONPTR cellhead, CHAR *name)
319 {
320 EXPORT **xrefptr1;
321 EXPTR xrefptr2;
322 NODEPTR nodeptr2;
323
324 xrefptr1 = &cellhead->exptr;
325 for(;;)
326 {
327 if (*xrefptr1 == 0)
328 {
329 xrefptr2 = (EXPTR)simals_alloc_mem((INTBIG)sizeof(EXPORT));
330 if (xrefptr2 == 0) return(0);
331 xrefptr2->node_name = name;
332 /* this could be a problem during model erase...smr!!! */
333 xrefptr2->next = 0;
334 *xrefptr1 = xrefptr2;
335 break;
336 }
337 xrefptr2 = *xrefptr1;
338 if (! estrcmp(xrefptr2->node_name, name)) return(xrefptr2);
339 xrefptr1 = &xrefptr2->next;
340 }
341
342 nodeptr2 = (NODEPTR)simals_alloc_mem((INTBIG)sizeof(NODE));
343 if (nodeptr2 == 0) return(0);
344 nodeptr2->cellptr = cellhead;
345 nodeptr2->num = simals_nseq;
346 ++simals_nseq;
347 nodeptr2->plot_node = 0;
348 nodeptr2->statptr = 0;
349 nodeptr2->pinptr = 0;
350 nodeptr2->load = -1.0;
351 nodeptr2->visit = 0;
352 nodeptr2->tracenode = FALSE;
353 nodeptr2->next = simals_noderoot;
354 xrefptr2->nodeptr = simals_noderoot = nodeptr2;
355 return(xrefptr2);
356 }
357
358 /*
359 * Name: simals_process_gate
360 *
361 * Description:
362 * This procedure steps through the gate truth tables and examines all
363 * node references to insure that they have been included in the cross
364 * reference table for the model. Returns true on error.
365 *
366 * Calling Arguments:
367 * cellhead = pointer to the cross reference data structure for the model
368 * that is going to be flattened
369 * modhead = pointer to the dtat structure containing the hierarchical
370 * node references
371 */
simals_process_gate(CONPTR cellhead,MODPTR modhead)372 BOOLEAN simals_process_gate(CONPTR cellhead, MODPTR modhead)
373 {
374 ROWPTR rowhead;
375
376 simals_primptr2 = (MODPTR)simals_alloc_mem((INTBIG)sizeof(MODEL));
377 if (simals_primptr2 == 0) return(TRUE);
378 simals_primptr2->num = simals_pseq;
379 ++simals_pseq;
380 simals_primptr2->name = modhead->name;
381 simals_primptr2->type = 'G';
382 simals_primptr2->ptr = 0;
383 simals_primptr2->exptr = 0;
384 simals_primptr2->setptr = 0;
385 simals_primptr2->loadptr = 0;
386 simals_primptr2->fanout = modhead->fanout;
387 simals_primptr2->priority = modhead->priority;
388 simals_primptr2->next = 0;
389 (void)allocstring(&(simals_primptr2->level), simals_compute_path_name(cellhead), sim_tool->cluster);
390 *simals_primptr1 = simals_primptr2;
391 simals_primptr1 = &simals_primptr2->next;
392
393 simals_rowptr1 = &simals_primptr2->ptr;
394 rowhead = (ROWPTR) modhead->ptr;
395 while (rowhead)
396 {
397 simals_rowptr2 = (ROWPTR) simals_alloc_mem((INTBIG)sizeof(ROW));
398 if (simals_rowptr2 == 0) return(TRUE);
399 simals_rowptr2->inptr = 0;
400 simals_rowptr2->outptr = 0;
401 simals_rowptr2->delta = rowhead->delta;
402 simals_rowptr2->linear = rowhead->linear;
403 simals_rowptr2->exp = rowhead->exp;
404 simals_rowptr2->abs = rowhead->abs;
405 simals_rowptr2->random = rowhead->random;
406 simals_rowptr2->delay = rowhead->delay;
407 if (rowhead->delay == 0) simals_rowptr2->delay = 0; else
408 (void)allocstring(&(simals_rowptr2->delay), rowhead->delay, sim_tool->cluster);
409 simals_rowptr2->next = 0;
410 *simals_rowptr1 = (CHAR*) simals_rowptr2;
411 simals_rowptr1 = (CHAR**) &(simals_rowptr2->next);
412
413 simals_ioptr1 = (CHAR**) &(simals_rowptr2->inptr);
414 if (simals_process_io_entry(modhead, cellhead, rowhead->inptr, 'I')) return(TRUE);
415
416 simals_ioptr1 = (CHAR**) &(simals_rowptr2->outptr);
417 if (simals_process_io_entry(modhead, cellhead, rowhead->outptr, 'O')) return(TRUE);
418
419 rowhead = rowhead->next;
420 }
421 return(FALSE);
422 }
423
424 /*
425 * Name: simals_process_io_entry
426 *
427 * Description:
428 * This procedure steps through the node references contained within a
429 * row of a transition table and insures that they are included in the cross
430 * reference table in the event they were not previously specified in a
431 * connection statement. Returns true on error.
432 *
433 * Calling Arguments:
434 * modhead = pointer to model that is being flattened
435 * cellhead = pointer to the cross reference data structure for the model
436 * that is going to be flattened
437 * iohead = pointer to a row of node references to be checked for
438 * entry into the cross reference table
439 * flag = character indicating if the node is an input or output
440 */
simals_process_io_entry(MODPTR modhead,CONPTR cellhead,IOPTR iohead,CHAR flag)441 BOOLEAN simals_process_io_entry(MODPTR modhead, CONPTR cellhead, IOPTR iohead, CHAR flag)
442 {
443 EXPTR xrefhead;
444
445 while (iohead)
446 {
447 xrefhead = simals_find_xref_entry(cellhead, (CHAR *)iohead->nodeptr);
448 if (xrefhead == 0) return(TRUE);
449 simals_ioptr2 = (IOPTR) simals_alloc_mem((INTBIG)sizeof(IO));
450 if (simals_ioptr2 == 0) return(TRUE);
451 simals_ioptr2->nodeptr = xrefhead->nodeptr;
452 simals_ioptr2->operatr = iohead->operatr;
453
454 if (simals_ioptr2->operatr > 127)
455 {
456 xrefhead = simals_find_xref_entry(cellhead, iohead->operand);
457 if (xrefhead == 0) return(TRUE);
458 simals_ioptr2->operand = (CHAR *) xrefhead->nodeptr;
459 } else
460 {
461 simals_ioptr2->operand = iohead->operand;
462 }
463
464 simals_ioptr2->strength = iohead->strength;
465 simals_ioptr2->next = 0;
466 *simals_ioptr1 = (CHAR*) simals_ioptr2;
467 simals_ioptr1 = (CHAR**) &(simals_ioptr2->next);
468
469 switch (flag)
470 {
471 case 'I':
472 if (simals_create_pin_entry(modhead, (CHAR *)iohead->nodeptr,
473 simals_ioptr2->nodeptr)) return(TRUE);
474 break;
475 case 'O':
476 simals_ioptr2->nodeptr = (NODE *)simals_create_stat_entry(modhead,
477 (CHAR *)iohead->nodeptr, simals_ioptr2->nodeptr);
478 if (simals_ioptr2->nodeptr == 0) return(TRUE);
479 }
480
481 if (simals_ioptr2->operatr > 127)
482 {
483 if (simals_create_pin_entry(modhead, (CHAR *)iohead->operand,
484 (NODEPTR)simals_ioptr2->operand)) return(TRUE);
485 }
486
487 iohead = iohead->next;
488 }
489 return(FALSE);
490 }
491
492 /*
493 * Name: simals_create_pin_entry
494 *
495 * Description:
496 * This procedure makes an entry into the primitive input table for the
497 * specified node. This table keeps track of the primitives which use
498 * this node as an input for event driven simulation. Returns true on error.
499 *
500 * Calling Arguments:
501 * modhead = pointer to the model structure from which the primitive
502 * is being created
503 * node_name = pointer to a char string containing the name of the node
504 * whose input list is being updated
505 * nodehead = pointer to the node data structure allocated for this node
506 */
simals_create_pin_entry(MODPTR modhead,CHAR * node_name,NODEPTR nodehead)507 BOOLEAN simals_create_pin_entry(MODPTR modhead, CHAR *node_name, NODEPTR nodehead)
508 {
509 LOAD **pinptr1;
510 LOADPTR pinptr2;
511
512 pinptr1 = &nodehead->pinptr;
513 for(;;)
514 {
515 if (*pinptr1 == 0)
516 {
517 pinptr2 = (LOADPTR)simals_alloc_mem((INTBIG)sizeof(LOAD));
518 if (pinptr2 == 0) return(TRUE);
519 pinptr2->ptr = (CHAR *) simals_primptr2;
520 pinptr2->next = 0;
521 *pinptr1 = pinptr2;
522 nodehead->load += simals_find_load_value(modhead, node_name);
523 break;
524 }
525 pinptr2 = *pinptr1;
526 if ((MODPTR)pinptr2->ptr == simals_primptr2) break;
527 pinptr1 = &pinptr2->next;
528 }
529 return(FALSE);
530 }
531
532 /*
533 * Name: simals_create_stat_entry
534 *
535 * Description:
536 * This procedure makes an entry into the database for an output which
537 * is connected to the specified node. Statistics are maintained for each output
538 * that is connected to a node. Returns zero on error.
539 *
540 * Calling Arguments:
541 * modhead = pointer to the model structure from which the primitive
542 * is being created
543 * node_name = pointer to a char string containing the name of the node
544 * whose output list is being updated
545 * nodehead = pointer to the node data structure allocated for this node
546 */
simals_create_stat_entry(MODPTR modhead,CHAR * node_name,NODEPTR nodehead)547 STATPTR simals_create_stat_entry(MODPTR modhead, CHAR *node_name, NODEPTR nodehead)
548 {
549 STAT **statptr1;
550 STATPTR statptr2;
551
552 statptr1 = &nodehead->statptr;
553 for(;;)
554 {
555 if (*statptr1 == 0)
556 {
557 statptr2 = (STATPTR)simals_alloc_mem((INTBIG)sizeof(STAT));
558 if (statptr2 == 0) break;
559 statptr2->primptr = simals_primptr2;
560 statptr2->nodeptr = nodehead;
561 statptr2->next = 0;
562 *statptr1 = statptr2;
563 nodehead->load += simals_find_load_value(modhead, node_name);
564 return(statptr2);
565 }
566 statptr2 = *statptr1;
567 if (statptr2->primptr == simals_primptr2) return(statptr2);
568 statptr1 = &statptr2->next;
569 }
570 return(0);
571 }
572
573 /*
574 * Name: simals_find_load_value
575 *
576 * Description:
577 * This procedure returns the loading factor for the specified node. If
578 * the node can't be found in the load list it is assumed it has a default value
579 * of 1.0.
580 *
581 * Calling Arguments:
582 * modhead = pointer to the model structure from which the primitive
583 * is being created
584 * node_name = pointer to a char string containing the name of the node
585 * whose load value is to be determined
586 */
simals_find_load_value(MODPTR modhead,CHAR * node_name)587 float simals_find_load_value(MODPTR modhead, CHAR *node_name)
588 {
589 LOADPTR loadhead;
590
591 for (loadhead = modhead->loadptr; loadhead != 0; loadhead = loadhead->next)
592 {
593 if (! estrcmp(loadhead->ptr, node_name)) return(loadhead->load);
594 }
595
596 if (modhead->type == 'F') return(0.0);
597 return(1.0);
598 }
599
600 /*
601 * Name: simals_process_set_entry
602 *
603 * Description:
604 * This procedure goes through the set node list for the specified cell
605 * and generates vectors for the node. These vectors are executed at t=0 by
606 * the simulator to initialize the node correctly. Returns true on error.
607 *
608 * Calling Arguments:
609 * cellhead = pointer to the cross reference table where the node locations
610 * are to be found
611 * iohead = pointer to the set list containing node names and state info
612 */
simals_process_set_entry(CONPTR cellhead,IOPTR iohead)613 BOOLEAN simals_process_set_entry(CONPTR cellhead, IOPTR iohead)
614 {
615 EXPTR xrefhead;
616 LINKPTR sethead;
617
618 for (; iohead; iohead = iohead->next)
619 {
620 xrefhead = simals_find_xref_entry(cellhead, (CHAR *)iohead->nodeptr);
621 if (xrefhead == 0) return(TRUE);
622
623 sethead = simals_alloc_link_mem();
624 if (sethead == 0) return(TRUE);
625 sethead->type = 'N';
626 sethead->ptr = (CHAR *) xrefhead->nodeptr;
627 sethead->state = (INTBIG) iohead->operand;
628 sethead->strength = iohead->strength;
629 sethead->priority = 2;
630 sethead->time = 0.0;
631 sethead->right = 0;
632 simals_insert_set_list(sethead);
633 }
634 return(FALSE);
635 }
636
637 /*
638 * Name: simals_process_function
639 *
640 * Description:
641 * This procedure steps through the event driving input list for a function
642 * and enters the function into the primitive input list for the particular node.
643 * In addition to this task the procedure sets up the calling argument node list
644 * for the function when it is called. Returns true on error.
645 *
646 * Calling Arguments:
647 * cellhead = pointer to the cross reference data structure for the model
648 * that is going to be flattened
649 * modhead = pointer to the data structure containing the hierarchical
650 * node references
651 */
simals_process_function(CONPTR cellhead,MODPTR modhead)652 BOOLEAN simals_process_function(CONPTR cellhead, MODPTR modhead)
653 {
654 EXPTR exhead, xrefhead;
655 FUNCPTR funchead, funcptr2;
656 EXPORT **exptr1;
657
658 simals_primptr2 = (MODPTR) simals_alloc_mem((INTBIG)sizeof(MODEL));
659 if (simals_primptr2 == 0) return(TRUE);
660 simals_primptr2->num = simals_pseq;
661 ++simals_pseq;
662 simals_primptr2->name = modhead->name;
663 simals_primptr2->type = 'F';
664 simals_primptr2->ptr = (CHAR*) simals_alloc_mem((INTBIG)sizeof(FUNC));
665 if (simals_primptr2->ptr == 0) return(TRUE);
666 simals_primptr2->exptr = 0;
667 simals_primptr2->setptr = 0;
668 simals_primptr2->loadptr = 0;
669 simals_primptr2->fanout = 0;
670 simals_primptr2->priority = modhead->priority;
671 simals_primptr2->next = 0;
672 (void)allocstring(&(simals_primptr2->level), simals_compute_path_name(cellhead),
673 sim_tool->cluster);
674 *simals_primptr1 = simals_primptr2;
675 simals_primptr1 = &simals_primptr2->next;
676
677 funchead = (FUNCPTR)modhead->ptr;
678 funcptr2 = (FUNCPTR)simals_primptr2->ptr;
679 funcptr2->procptr = (void(*)(MODPTR))simals_get_function_address(modhead->name);
680 if (funcptr2->procptr == 0) return(TRUE);
681 funcptr2->inptr = 0;
682 funcptr2->delta = funchead->delta;
683 funcptr2->linear = funchead->linear;
684 funcptr2->exp = funchead->exp;
685 funcptr2->abs = funchead->abs;
686 funcptr2->random = funchead->random;
687 funcptr2->userptr = 0;
688 funcptr2->userint = 0;
689 funcptr2->userfloat = 0.0;
690
691 exptr1 = &simals_primptr2->exptr;
692 for (exhead = modhead->exptr; exhead; exhead = exhead->next)
693 {
694 xrefhead = simals_find_xref_entry(cellhead, exhead->node_name);
695 if (xrefhead == 0) return(TRUE);
696 simals_exptr2 = (EXPTR) simals_alloc_mem((INTBIG)sizeof(EXPORT));
697 if (simals_exptr2 == 0) return(TRUE);
698 if (exhead->nodeptr)
699 {
700 simals_exptr2->node_name = (CHAR *) simals_create_stat_entry(modhead,
701 exhead->node_name, xrefhead->nodeptr);
702 if (simals_exptr2->node_name == 0) return(TRUE);
703 } else
704 {
705 simals_exptr2->node_name = 0;
706 }
707 simals_exptr2->nodeptr = xrefhead->nodeptr;
708 simals_exptr2->next = 0;
709 *exptr1 = simals_exptr2;
710 exptr1 = &simals_exptr2->next;
711 }
712
713 exptr1 = &funcptr2->inptr;
714 for (exhead = funchead->inptr; exhead; exhead = exhead->next)
715 {
716 xrefhead = simals_find_xref_entry(cellhead, exhead->node_name);
717 if (xrefhead == 0) return(TRUE);
718 simals_exptr2 = (EXPTR) simals_alloc_mem((INTBIG)sizeof(EXPORT));
719 if (simals_exptr2 == 0) return(TRUE);
720 simals_exptr2->nodeptr = xrefhead->nodeptr;
721 simals_exptr2->next = 0;
722 *exptr1 = simals_exptr2;
723 exptr1 = &simals_exptr2->next;
724 if (simals_create_pin_entry(modhead, exhead->node_name, xrefhead->nodeptr))
725 return(TRUE);
726 }
727 return(FALSE);
728 }
729
730 #endif /* SIMTOOL - at top */
731