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