1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: simals.c
6  * Asynchronous Logic Simulator main module
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 /********************************* GLOBALS *********************************/
41 
42        MODPTR      simals_modroot = 0;
43 static MODPTR      simals_modptr2;
44        MODPTR      simals_primroot = 0;
45        ROWPTR      simals_rowptr2;
46        IOPTR       simals_ioptr2;
47 static CONPTR      simals_conptr2;
48        CONPTR      simals_levelptr = 0;
49        CONPTR      simals_cellroot = 0;
50        EXPTR       simals_exptr2;
51        NODEPTR     simals_noderoot = 0;
52        NODEPTR     simals_drive_node;
53        LINKPTR     simals_linkfront = 0;
54        LINKPTR     simals_linkback = 0;
55        LINKPTR     simals_setroot = 0;
56        TRAKPTR     simals_trakroot = 0;
57        LOADPTR     simals_chekroot;
58        CHAR      **simals_rowptr1;
59        CHAR      **simals_ioptr1;
60        CHAR       *simals_instbuf = 0;
61 static INTBIG      simals_loop_count;
62        INTBIG      simals_pseq;
63        INTBIG      simals_nseq;
64        INTBIG     *simals_instptr = 0;
65 static INTBIG      simals_ibufsize;
66 static INTBIG      simals_iptrsize;
67        INTBIG      simals_trakfull;
68        INTBIG      simals_trakptr;
69        INTBIG      simals_no_update_key;		/* variable key for "SIM_als_no_update" */
70        BOOLEAN     simals_seed_flag = TRUE;
71        BOOLEAN     simals_trace_all_nodes = FALSE;
72        double      simals_time_abs;
73 static float       simals_delta_def;
74 static float       simals_linear_def;
75 static float       simals_exp_def;
76 static float       simals_random_def;
77 static float       simals_abs_def;
78        NODEPROTO  *simals_mainproto = NONODEPROTO;
79        INTBIG      simals_trace_size = 0;
80        CHAR       *simals_title = 0;
81 
82 /********************************* LOCALS *********************************/
83 
84 static INTBIG     i_ptr;
85 static CHAR       delay[16];
86 
87 /* prototypes for local routines */
88 static BOOLEAN simals_alloc_char_buffer(CHAR**, INTBIG*, INTBIG);
89 static BOOLEAN simals_get_string(CHAR*);
90 static BOOLEAN simals_get_int(INTBIG*);
91 static BOOLEAN simals_get_float(float*);
92 static BOOLEAN simals_get_name(CHAR*);
93 static BOOLEAN simals_fragment_line(CHAR*);
94 static BOOLEAN simals_parse_struct_header(CHAR);
95 static BOOLEAN simals_parse_gate(void);
96 static BOOLEAN simals_parse_node(void);
97 static BOOLEAN simals_parse_timing(void);
98 static BOOLEAN simals_parse_fanout(void);
99 static BOOLEAN simals_parse_load(void);
100 static BOOLEAN simals_parse_model(void);
101 static BOOLEAN simals_parse_function(void);
102 static BOOLEAN simals_parse_func_input(EXPORT**);
103 static BOOLEAN simals_parse_func_output(void);
104 static BOOLEAN simals_parse_delay(void);
105 static BOOLEAN simals_alloc_ptr_buffer(INTBIG**, INTBIG*, INTBIG);
106 
107 /******************************************************************************/
108 
simals_init(void)109 void simals_init(void)
110 {
111 	REGISTER VARIABLE *var;
112 
113 	/* allocate memory */
114 	if (simals_instbuf == 0)
115 	{
116 		if (simals_alloc_char_buffer(&simals_instbuf, &simals_ibufsize, 200)) return;
117 	}
118 	if (simals_instptr == 0)
119 	{
120 		if (simals_alloc_ptr_buffer(&simals_instptr, &simals_iptrsize, 100)) return;
121 	}
122 	if (simals_trace_size == 0)
123 	{
124 		var = getval((INTBIG)sim_tool, VTOOL, VINTEGER, x_("SIM_als_num_events"));
125 		if (var == NOVARIABLE) simals_trace_size = DEFAULT_TRACE_SIZE; else
126 			simals_trace_size = var->addr;
127 	}
128 	if (simals_trakroot == 0)
129 	{
130 		simals_trakroot = (TRAKPTR)simals_alloc_mem((INTBIG)(simals_trace_size * sizeof(TRAK)));
131 		if (simals_trakroot == 0) return;
132 	}
133 	simals_no_update_key = makekey(x_("SIM_als_no_update"));
134 }
135 
simals_term(void)136 void simals_term(void)
137 {
138 	simals_erase_model();
139 	if (simals_instbuf != 0) efree((CHAR *)simals_instbuf);
140 	if (simals_instptr != 0) efree((CHAR *)simals_instptr);
141 	if (simals_trakroot != 0) efree((CHAR *)simals_trakroot);
142 	simals_freeflatmemory();
143 	simals_freesimmemory();
144 }
145 
146 /*
147  * routine to create a new window with simulation of cell "simals_mainproto"
148  */
simals_init_display(void)149 void simals_init_display(void)
150 {
151 	CONPTR cellptr;
152 	CHAR *pt;
153 	REGISTER void *infstr;
154 
155 	if (simals_mainproto == NONODEPROTO)
156 	{
157 		ttyputerr(_("No cell to simulate"));
158 		return;
159 	}
160 
161 	/* set top level */
162 	simals_levelptr = simals_cellroot;
163 	infstr = initinfstr();
164 	addstringtoinfstr(infstr, simals_mainproto->protoname);
165 	pt = returninfstr(infstr);
166 	simals_convert_to_upper(pt);
167 	cellptr = simals_find_level(pt);
168 	if (cellptr != 0) simals_levelptr = cellptr;
169 	if (simals_levelptr == 0)
170 	{
171 		ttyputerr(_("No simulation to resume"));
172 		return;
173 	}
174 	if (simals_set_current_level()) return;
175 
176 	/* run simulation */
177 	(void)simals_initialize_simulator(TRUE);
178 }
179 
simals_com_comp(INTBIG count,CHAR * par[10])180 void simals_com_comp(INTBIG count, CHAR *par[10])
181 {
182 	CHAR *pp;
183 	INTBIG l;
184 
185 	l = estrlen(pp = par[0]);
186 
187 	if (namesamen(pp, x_("build-actel-models"), l) == 0 && l >= 1)
188 	{
189 		simals_build_actel_command(count-1, &par[1]);
190 		return;
191 	}
192 	if (namesamen(pp, x_("clock"), l) == 0 && l >= 1)
193 	{
194 		simals_clock_command(count-1, &par[1]);
195 		return;
196 	}
197 	if (namesamen(pp, x_("erase"), l) == 0 && l >= 1)
198 	{
199 		simals_erase_model();
200 		return;
201 	}
202 	if (namesamen(pp, x_("go"), l) == 0 && l >= 1)
203 	{
204 		simals_go_command(count-1, &par[1]);
205 		return;
206 	}
207 	if (namesamen(pp, x_("help"), l) == 0 && l >= 1)
208 	{
209 		simals_help_command();
210 		return;
211 	}
212 	if (namesamen(pp, x_("print"), l) == 0 && l >= 1)
213 	{
214 		simals_print_command(count-1, &par[1]);
215 		return;
216 	}
217 	if (namesamen(pp, x_("seed"), l) == 0 && l >= 3)
218 	{
219 		simals_seed_command(count-1, &par[1]);
220 		return;
221 	}
222 	if (namesamen(pp, x_("set"), l) == 0 && l >= 3)
223 	{
224 		simals_set_command(count-1, &par[1]);
225 		return;
226 	}
227 	if (namesamen(pp, x_("trace"), l) == 0 && l >= 1)
228 	{
229 		simals_trace_command(count-1, &par[1]);
230 		return;
231 	}
232 	if (namesamen(pp, x_("vector"), l) == 0 && l >= 1)
233 	{
234 		simals_vector_command(count-1, &par[1]);
235 		return;
236 	}
237 	if (namesamen(pp, x_("annotate"), l) == 0 && l >= 1)
238 	{
239 		simals_annotate_command(count-1, &par[1]);
240 		return;
241 	}
242 	if (namesamen(pp, x_("order"), l) == 0 && l >= 1)
243 	{
244 		simals_order_command(count-1, &par[1]);
245 		return;
246 	}
247 	ttyputbadusage(x_("telltool simulation als"));
248 }
249 
250 /*
251  * Name: simals_alloc_mem
252  *
253  * Description:
254  *	This procedure allocates a block of memory of size that is defined
255  * by the calling argument.  If there are memory allocation problems,
256  * a diagnostic message is generated and program execution is terminated.
257  * The procedure returns an integer value representing the address of the
258  * newly allocated memory.  Returns zero on error.
259  *
260  * Calling Arguments:
261  *	size = integer value representing size of data element
262  */
263 #ifdef DEBUGMEMORY
_simals_alloc_mem(INTBIG size,CHAR * filename,INTBIG lineno)264 CHAR *_simals_alloc_mem(INTBIG size, CHAR *filename, INTBIG lineno)
265 #else
266 CHAR *simals_alloc_mem(INTBIG size)
267 #endif
268 {
269 	CHAR   *ptr;
270 	INTBIG   i;
271 
272 #ifdef DEBUGMEMORY
273 	ptr = (CHAR *)_emalloc(size, sim_tool->cluster, filename, lineno);
274 #else
275 	ptr = (CHAR *)emalloc(size, sim_tool->cluster);
276 #endif
277 	if (ptr == 0)
278 	{
279 		ttyputmsg(_("ERROR: Memory Allocation Error"));
280 		return(0);
281 	}
282 	for(i=0; i<size; i++) ptr[i] = 0;
283 	return(ptr);
284 }
285 
286 /*
287  * Name: simals_alloc_char_buffer
288  *
289  * Description:
290  *	This procedure allocates a buffer to contain the specified number
291  * of data elements for the text buffer.  If the buffer was already allocated
292  * the contents of the old one are copied into the new buffer after the memory
293  * has been allocated.  Returns true on error.
294  *
295  * Calling Arguments:
296  *	root    = address of pointer to the beginning of character space
297  *	old     = address of int value indicating the old size of the buffer
298  *	newsize = integer value indicating the new size to be created
299  */
simals_alloc_char_buffer(CHAR ** root,INTBIG * old,INTBIG newsize)300 BOOLEAN simals_alloc_char_buffer(CHAR **root, INTBIG *old, INTBIG newsize)
301 {
302 	INTBIG   i;
303 	CHAR  *head;
304 
305 	head = (CHAR *) simals_alloc_mem((INTBIG)(newsize * sizeof(CHAR)));
306 	if (head == 0) return(TRUE);
307 	if (*root)
308 	{
309 		for (i = 0; i < (*old); ++i) head[i] = (*root)[i];
310 		efree((CHAR *)*root);
311 	}
312 
313 	*root = head;
314 	*old = newsize;
315 	return(FALSE);
316 }
317 
318 /*
319  * Name: simals_alloc_ptr_buffer
320  *
321  * Description:
322  *	This procedure allocates a buffer to contain the specified number
323  * of data elements for the pointers to char strings in the char buffer.  If
324  * the buffer was already allocated the contents of the old one are copied into
325  * the new buffer after the memory has been allocated.  Returns true on error.
326  *
327  * Calling Arguments:
328  *	root    = address of pointer to the beginning of pointer space
329  *	old     = address of int value indicating the old size of the buffer
330  *	newsize = integer value indicating the new size to be created
331  */
simals_alloc_ptr_buffer(INTBIG ** root,INTBIG * old,INTBIG newsize)332 BOOLEAN simals_alloc_ptr_buffer(INTBIG **root, INTBIG *old, INTBIG newsize)
333 {
334 	INTBIG   i, **head;
335 
336 	head = (INTBIG **) simals_alloc_mem((INTBIG)(newsize * sizeof(INTBIG *)));
337 	if (head == 0) return(TRUE);
338 
339 	if (*root)
340 	{
341 		for (i = 0; i < (*old); ++i) head[i] = (INTBIG*) (*root)[i];
342 		efree((CHAR *)*root);
343 	}
344 
345 	*root = (INTBIG*) head;
346 	*old = newsize;
347 	return(FALSE);
348 }
349 
350 /*
351  * Name: simals_get_string
352  *
353  * Description:
354  *	This procedure gets one string from the instruction buffer.  The
355  * procedure returns a Null value if the string was successfully obtained.
356  * A true value is returned when End Of File (EOF) is encountered.
357  *
358  * Calling Arguments:
359  *	sp = pointer to char string where results are to be saved
360  */
simals_get_string(CHAR * sp)361 BOOLEAN simals_get_string(CHAR *sp)
362 {
363 	INTBIG   i;
364 	CHAR  line[260];
365 	extern TOOL *vhdl_tool;
366 
367 	if (((simals_instptr[i_ptr] < 0) || (simals_instbuf[simals_instptr[i_ptr]] == '#')) && simals_loop_count)
368 	{
369 		++i_ptr;
370 		return(TRUE);
371 	}
372 
373 	while ((simals_instptr[i_ptr] < 0) || (simals_instbuf[simals_instptr[i_ptr]] == '#'))
374 	{
375 		i = asktool(vhdl_tool, x_("get-line"), (INTBIG)line);
376 
377 		if (i == 0)
378 		{
379 			++i_ptr;
380 			return(TRUE);
381 		}
382 
383 		if (estrlen(line) > 255)
384 		{
385 			ttyputerr(_("ERROR: Input record too large.  Make them smaller"));
386 			return(TRUE);
387 		}
388 		if (simals_fragment_line(line)) return(TRUE);
389 		i_ptr = 0;
390 	}
391 
392 	(void)estrcpy(sp, &(simals_instbuf[simals_instptr[i_ptr]]));
393 	++i_ptr;
394 	return(FALSE);
395 }
396 
397 /*
398  * Name: simals_get_int
399  *
400  * Description:
401  *	This procedure reads in the required number of strings to compose an
402  * integer value.  It is possible to have a leading +/- sign before the actual
403  * integer value.
404  *
405  * Calling Arguments:
406  *	value = pointer to an integer value where results are to be saved
407  */
simals_get_int(INTBIG * value)408 BOOLEAN simals_get_int(INTBIG *value)
409 {
410 	BOOLEAN   i;
411 	CHAR  s1[256], s2[256];
412 
413 	i = simals_get_string(s1);
414 	if (i) return(TRUE);
415 
416 	if ((s1[0] == '+') || (s1[0] == '-'))
417 	{
418 		i = simals_get_string(s2);
419 		if (i) return(TRUE);
420 		(void)estrcat(s1, s2);
421 	}
422 
423 	*value = simals_atoi(s1);
424 	return(FALSE);
425 }
426 
427 /*
428  * Name: simals_atoi
429  *
430  * Description:
431  *	This procedure examines the input string, determines which base the
432  * integer is written in, and then returns the integer value to the calling
433  * routine.  Hex numbers = 0xDDDD, Octal = 0DDDD, Binary = 0bDDDD,
434  * and base10 = DDDDD.
435  *
436  * Calling Arguments:
437  *	s1 = pointer to a string containing the integer value to be interpreted
438  */
simals_atoi(CHAR * s1)439 INTBIG simals_atoi(CHAR *s1)
440 {
441 	INTBIG  i, sum;
442 
443 	sum = 0;
444 	switch (s1[0])
445 	{
446 		case '0':
447 			switch (s1[1])
448 			{
449 				case 'B':
450 					for (i = 2; ; ++i)
451 					{
452 						if ((s1[i] >= '0') && (s1[i] <= '1'))
453 						{
454 							 sum = (sum << 1) + s1[i] - 48;
455 							 continue;
456 						}
457 						break;
458 					}
459 					break;
460 				case 'X':
461 					for (i = 2; ; ++i)
462 					{
463 						if ((s1[i] >= '0') && (s1[i] <= '9'))
464 						{
465 							 sum = (sum << 4) + s1[i] - 48;
466 							 continue;
467 						}
468 						if ((s1[i] >= 'A') && (s1[i] <= 'F'))
469 						{
470 							 sum = (sum << 4) + s1[i] - 55;
471 							 continue;
472 						}
473 						break;
474 					}
475 					break;
476 				default:
477 					for (i = 1; ; ++i)
478 					{
479 						if ((s1[i] >= '0') && (s1[i] <= '7'))
480 						{
481 							 sum = (sum << 3) + s1[i] - 48;
482 							 continue;
483 						}
484 						break;
485 					}
486 			}
487 			break;
488 
489 		default:
490 			sum = eatol(s1);
491 	}
492 
493 	return(sum);
494 }
495 
496 /*
497  * Name: simals_convert_to_upper
498  *
499  * Description:
500  *	This procedure converts any lower case characters that are in the
501  * character string to upper case.
502  *
503  * Calling Arguments:
504  *	s1 = pointer to char string that is to be converted to upper case
505  */
simals_convert_to_upper(CHAR * s1)506 void simals_convert_to_upper(CHAR *s1)
507 {
508 	for (; *s1; ++s1)
509 	{
510 		if (('a' <= (*s1)) && ((*s1) <= 'z')) *s1 += 'A' - 'a';
511 	}
512 }
513 
514 /*
515  * Name: simals_get_float
516  *
517  * Description:
518  *	This procedure reads in the required number of strings to compose a
519  * float value.  It is possible to have a leading +/- sign before the actual
520  * float value combined with the chance that the number is entered in scientific
521  * notation.
522  *
523  * Calling Arguments:
524  *	value = pointer to a float value where results are to be saved
525  */
simals_get_float(float * value)526 BOOLEAN simals_get_float(float *value)
527 {
528 	BOOLEAN   eof;
529 	INTBIG    i;
530 	CHAR  s1[256], s2[256];
531 
532 	eof = simals_get_string(s1);
533 	if (eof) return(TRUE);
534 
535 	if ((s1[0] == '+') || (s1[0] == '-'))
536 	{
537 		eof = simals_get_string(s2);
538 		if (eof) return(TRUE);
539 		(void)estrcat(s1, s2);
540 	}
541 
542 	i = estrlen(s1);
543 	if (s1[i-1] != 'E')
544 	{
545 		*value = (float)eatof(s1);
546 		return(FALSE);
547 	}
548 
549 	eof = simals_get_string(s2);
550 	if (eof) return(TRUE);
551 	(void)estrcat(s1, s2);
552 
553 	if ((s2[0] == '+') || (s2[0] == '-'))
554 	{
555 		eof = simals_get_string(s2);
556 		if (eof) return(TRUE);
557 		(void)estrcat(s1, s2);
558 	}
559 
560 	*value = (float)eatof(s1);
561 	return(FALSE);
562 }
563 
564 /*
565  * Name: simals_get_name
566  *
567  * Description:
568  *	This procedure reads in the required number of strings to compose a
569  * model/node name for the element. If array subscripting is used, the
570  * brackets and argument string is spliced to the node name.
571  *
572  * Calling Arguments:
573  *	sp = pointer to a character string where results are to be saved
574  */
simals_get_name(CHAR * sp)575 BOOLEAN simals_get_name(CHAR *sp)
576 {
577 	BOOLEAN   eof;
578 	CHAR  s1[256], s2[256];
579 
580 	eof = simals_get_string(s1);
581 	if (eof) return(TRUE);
582 
583 	eof = simals_get_string(s2);
584 	if (eof || (s2[0] != '['))
585 	{
586 		(void)estrcpy(sp, s1);
587 		--i_ptr;
588 		return(FALSE);
589 	}
590 
591 	(void)estrcat(s1, s2);
592 	for(;;)
593 	{
594 		eof = simals_get_string(s2);
595 		if (eof) return(TRUE);
596 		(void)estrcat(s1, s2);
597 		if (s2[0] == ']') break;
598 	}
599 
600 	(void)estrcpy(sp, s1);
601 	return(FALSE);
602 }
603 
604 /*
605  * Name: simals_fragment_line
606  *
607  * Description:
608  *	This procedure processes the string specified by the calling argument
609  * and fragments it into a series of smaller character strings, each of which
610  * is terminated by a null character.  Returns true on error.
611  *
612  * Calling Arguments:
613  *	line = pointer to the character string to be fragmented
614  */
simals_fragment_line(CHAR * line)615 BOOLEAN simals_fragment_line(CHAR *line)
616 {
617 	INTBIG   i, j, k, count;
618 
619 	j = count = simals_instptr[0] = 0;
620 	k = 1;
621 
622 	for (i = 0; ; ++i)
623 	{
624 		if (j > (simals_ibufsize - 3))
625 		{
626 			if (simals_alloc_char_buffer(&simals_instbuf, &simals_ibufsize,
627 				(simals_ibufsize * 5))) return(TRUE);
628 		}
629 		if (k > (simals_iptrsize - 2))
630 		{
631 			if (simals_alloc_ptr_buffer(&simals_instptr, &simals_iptrsize,
632 				(simals_iptrsize * 5))) return(TRUE);
633 		}
634 
635 		if (line[i] == 0 || line[i] == '\n')
636 		{
637 			if (count)
638 			{
639 				simals_instbuf[j] = 0;
640 				simals_instptr[k] = -1;
641 			} else
642 			{
643 				simals_instptr[k-1] = -1;
644 			}
645 			break;
646 		}
647 
648 		switch (line[i])
649 		{
650 			case ' ':
651 			case ',':
652 			case '\t':
653 			case ':':
654 				if (count)
655 				{
656 					simals_instbuf[j] = 0;
657 					simals_instptr[k] = j+1;
658 					++j;
659 					++k;
660 					count = 0;
661 				}
662 				break;
663 
664 			case '(':
665 			case ')':
666 			case '{':
667 			case '}':
668 			case '[':
669 			case ']':
670 			case '=':
671 			case '!':
672 			case '>':
673 			case '<':
674 			case '+':
675 			case '-':
676 			case '*':
677 			case '/':
678 			case '%':
679 			case '@':
680 			case ';':
681 			case '#':
682 				if (count)
683 				{
684 					simals_instbuf[j] = 0;
685 					simals_instbuf[j+1] = line[i];
686 					simals_instbuf[j+2] = 0;
687 					simals_instptr[k] = j+1;
688 					simals_instptr[k+1] = j+3;
689 					j += 3;
690 					k += 2;
691 					count = 0;
692 				} else
693 				{
694 					simals_instbuf[j] = line[i];
695 					simals_instbuf[j+1] = 0;
696 					simals_instptr[k] = j+2;
697 					j += 2;
698 					++k;
699 				}
700 				break;
701 
702 			default:
703 				if (('a' <= line[i]) && (line[i] <= 'z'))
704 				{
705 					line[i] += 'A' - 'a';
706 				}
707 				simals_instbuf[j] = line[i];
708 				++j;
709 				++count;
710 		}
711 	}
712 	return(FALSE);
713 }
714 
715 /*
716  * Name: simals_read_net_desc
717  *
718  * Description:
719  *	This procedure reads a netlist description of the logic network
720  * to be analysed in other procedures.  Returns true on error.
721  */
simals_read_net_desc(NODEPROTO * np)722 BOOLEAN simals_read_net_desc(NODEPROTO *np)
723 {
724 	CHAR    s1[256], *intended;
725 	BOOLEAN    eof;
726 	extern TOOL *vhdl_tool;
727 
728 	simals_mainproto = np;
729 	if (asktool(vhdl_tool, x_("begin-netlist-input"), (INTBIG)np, sim_filetypeals, (INTBIG)&intended) != 0)
730 	{
731 		ttyputerr(_("Cannot read %s"), intended);
732 		return(TRUE);
733 	}
734 	ttyputmsg(_("Simulating netlist in %s"), intended);
735 
736 	simals_instptr[0] = -1;
737 	i_ptr = 0;
738 	simals_loop_count = 0;
739 
740 	for(;;)
741 	{
742 		eof = simals_get_string(s1);
743 		if (eof) break;
744 
745 		if (! (estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION")) && estrcmp(s1, x_("MODEL"))))
746 		{
747 			if (simals_parse_struct_header(s1[0]))
748 			{
749 				(void)asktool(vhdl_tool, x_("end-input"));
750 				return(TRUE);
751 			}
752 			continue;
753 		}
754 
755 		ttyputerr(_("ERROR: String '%s' invalid (expecting gate, function, or model)"), s1);
756 		(void)asktool(vhdl_tool, x_("end-input"));
757 		return(TRUE);
758 	}
759 	(void)asktool(vhdl_tool, x_("end-input"));
760 	return(FALSE);
761 }
762 
763 /*
764  * Name: simals_parse_struct_header
765  *
766  * Description:
767  *	This procedure parses the input text used to describe the header for
768  * a top level structure (gate, function, model).  The structure name and
769  * argument list (exported node names) are entered into the database.  Returns
770  * nonzero on error.
771  *
772  * Calling Arguments:
773  *	flag = char representing the type of structure to be parsed
774  */
simals_parse_struct_header(CHAR flag)775 BOOLEAN simals_parse_struct_header(CHAR flag)
776 {
777 	BOOLEAN   eof;
778 	CHAR  s1[256];
779 	MODEL **modptr1;
780 	EXPORT **exptr1;
781 
782 	eof = simals_get_name(s1);
783 	if (eof)
784 	{
785 		ttyputerr(_("Structure declaration: EOF unexpectedly found"));
786 		return(TRUE);
787 	}
788 
789 	modptr1 = &simals_modroot;
790 	for(;;)
791 	{
792 		if (*modptr1 == 0)
793 		{
794 			simals_modptr2 = (MODPTR) simals_alloc_mem((INTBIG)sizeof(MODEL));
795 			if (simals_modptr2 == 0) return(TRUE);
796 			simals_modptr2->name = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
797 			if (simals_modptr2->name == 0) return(TRUE);
798 			(void)estrcpy(simals_modptr2->name, s1);
799 			simals_modptr2->type = flag;
800 			simals_modptr2->ptr = 0;
801 			simals_modptr2->exptr  = 0;
802 			simals_modptr2->setptr = 0;
803 			simals_modptr2->loadptr = 0;
804 			simals_modptr2->fanout = 1;
805 			simals_modptr2->priority = 1;
806 			simals_modptr2->next   = 0;
807 			*modptr1 = simals_modptr2;
808 			break;
809 		}
810 		simals_modptr2 = *modptr1;
811 		if (! estrcmp(simals_modptr2->name, s1))
812 		{
813 			ttyputerr(_("ERROR: Structure %s already defined"), s1);
814 			return(TRUE);
815 		}
816 		modptr1 = &simals_modptr2->next;
817 	}
818 
819 	eof = simals_get_string(s1);
820 	if (eof)
821 	{
822 		ttyputerr(_("Structure declaration: EOF unexpectedly found"));
823 		return(TRUE);
824 	}
825 	if (s1[0] != '(')
826 	{
827 		ttyputerr(_("Structure declaration: Expecting to find '(' in place of string '%s'"), s1);
828 		return(TRUE);
829 	}
830 
831 	for(;;)
832 	{
833 		eof = simals_get_name(s1);
834 		if (eof)
835 		{
836 			ttyputerr(_("Structure declaration: EOF unexpectedly found"));
837 			return(TRUE);
838 		}
839 		if (s1[0] == ')') break;
840 
841 		exptr1 = &simals_modptr2->exptr;
842 		for(;;)
843 		{
844 			if (*exptr1 == 0)
845 			{
846 				simals_exptr2 = (EXPTR) simals_alloc_mem((INTBIG)sizeof(EXPORT));
847 				if (simals_exptr2 == 0) return(TRUE);
848 				simals_exptr2->node_name = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
849 				if (simals_exptr2->node_name == 0) return(TRUE);
850 				(void)estrcpy(simals_exptr2->node_name, s1);
851 				simals_exptr2->nodeptr = 0;
852 				simals_exptr2->next = 0;
853 				*exptr1 = simals_exptr2;
854 				break;
855 			}
856 			simals_exptr2 = *exptr1;
857 			if (! estrcmp(simals_exptr2->node_name, s1))
858 			{
859 				ttyputerr(_("Node %s specified more than once in argument list"), s1);
860 				return(TRUE);
861 			}
862 			exptr1 = &simals_exptr2->next;
863 		}
864 	}
865 
866 	switch (flag)
867 	{
868 		case 'G':
869 			if (simals_parse_gate()) return(TRUE);
870 			return(FALSE);
871 		case 'F':
872 			if (simals_parse_function()) return(TRUE);
873 			return(FALSE);
874 		case 'M':
875 			if (simals_parse_model()) return(TRUE);
876 			return(FALSE);
877 	}
878 	ttyputerr(_("Error in parser: invalid structure type"));
879 	return(TRUE);
880 }
881 
882 /*
883  * Name: simals_parse_gate
884  *
885  * Description:
886  *	This procedure parses the text used to describe a gate entity.
887  * The user specifies truth table entries, loading factors, and timing parameters
888  * in this region of the netlist.  Returns true on error.
889  */
simals_parse_gate(void)890 BOOLEAN simals_parse_gate(void)
891 {
892 	INTBIG   j;
893 	BOOLEAN eof;
894 	CHAR  s1[256];
895 
896 	/* init delay transition name */
897 	(void)esnprintf(delay, 16, x_("XX"));
898 
899 	simals_delta_def = simals_linear_def = simals_exp_def = simals_random_def = simals_abs_def = 0;
900 	simals_rowptr1 = &(simals_modptr2->ptr);
901 	for(;;)
902 	{
903 		eof = simals_get_string(s1);
904 		if (eof || (! (estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION")) && estrcmp(s1, x_("MODEL")))))
905 		{
906 			--i_ptr;
907 			break;
908 		}
909 
910 		if (! estrcmp(s1, x_("I")))
911 		{
912 			simals_rowptr2 = (ROWPTR) simals_alloc_mem((INTBIG)sizeof(ROW));
913 			if (simals_rowptr2 == 0) return(TRUE);
914 			simals_rowptr2->inptr = 0;
915 			simals_rowptr2->outptr = 0;
916 			simals_rowptr2->delta = simals_delta_def;
917 			simals_rowptr2->linear = simals_linear_def;
918 			simals_rowptr2->exp = simals_exp_def;
919 			simals_rowptr2->random = simals_random_def;
920 			simals_rowptr2->abs = simals_abs_def;
921 			(void)allocstring(&(simals_rowptr2->delay), delay, sim_tool->cluster);
922 			(void)esnprintf(delay, 16, x_("XX"));  /* reset name */
923 			simals_rowptr2->next = 0;
924 			*simals_rowptr1 = (CHAR*) simals_rowptr2;
925 			simals_rowptr1 = (CHAR**) &(simals_rowptr2->next);
926 			simals_ioptr1 = (CHAR**) &(simals_rowptr2->inptr);
927 			if (simals_parse_node()) return(TRUE);
928 			continue;
929 		}
930 
931 		if (! estrcmp(s1, x_("O")))
932 		{
933 			simals_ioptr1 = (CHAR**) &(simals_rowptr2->outptr);
934 			if (simals_parse_node()) return(TRUE);
935 			continue;
936 		}
937 
938 		if (! estrcmp(s1, x_("T")))
939 		{
940 			if (simals_parse_timing()) return(TRUE);
941 			continue;
942 		}
943 
944 		if (! estrcmp(s1, x_("D")))
945 		{
946 			if (simals_parse_delay()) return(TRUE);
947 			continue;
948 		}
949 
950 		if (! estrcmp(s1, x_("FANOUT")))
951 		{
952 			if (simals_parse_fanout()) return(TRUE);
953 			continue;
954 		}
955 
956 		if (! estrcmp(s1, x_("LOAD")))
957 		{
958 			if (simals_parse_load()) return(TRUE);
959 			continue;
960 		}
961 
962 		if (! estrcmp(s1, x_("PRIORITY")))
963 		{
964 			eof = simals_get_int(&j);
965 			if (eof)
966 			{
967 				ttyputerr(_("Priority declaration: EOF unexpectedly found"));
968 				return(TRUE);
969 			}
970 			simals_modptr2->priority = (INTSML)j;
971 			continue;
972 		}
973 
974 		if (! estrcmp(s1, x_("SET")))
975 		{
976 			simals_ioptr1 = (CHAR**) &(simals_modptr2->setptr);
977 			for (simals_ioptr2 = simals_modptr2->setptr; simals_ioptr2;
978 				simals_ioptr2 = simals_ioptr2->next)
979 			{
980 				simals_ioptr1 = (CHAR**) &(simals_ioptr2->next);
981 			}
982 			if (simals_parse_node()) return(TRUE);
983 			continue;
984 		}
985 
986 		ttyputerr(_("ERROR: String '%s' invalid syntax"), s1);
987 		return(TRUE);
988 	}
989 	return(FALSE);
990 }
991 
992 /*
993  * Name: simals_parse_node
994  *
995  * Description:
996  *	This procedure creates an entry in the database for one of the nodes
997  * that belong to a row entry or set state entry.  Returns true on error.
998  */
simals_parse_node(void)999 BOOLEAN simals_parse_node(void)
1000 {
1001 	INTBIG   j;
1002 	BOOLEAN  eof;
1003 	CHAR  s1[256];
1004 
1005 	for(;;)
1006 	{
1007 		eof = simals_get_name(s1);
1008 		if (eof || (! (estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION"))
1009 			&& estrcmp(s1, x_("MODEL")) && estrcmp(s1, x_("I")) && estrcmp(s1, x_("O"))
1010 			&& estrcmp(s1, x_("T")) && estrcmp(s1, x_("FANOUT")) && estrcmp(s1, x_("LOAD"))
1011 			&& estrcmp(s1, x_("PRIORITY")) && estrcmp(s1, x_("SET")))))
1012 		{
1013 			--i_ptr;
1014 			break;
1015 		}
1016 
1017 		simals_ioptr2 = (IOPTR) simals_alloc_mem((INTBIG)sizeof(IO));
1018 		if (simals_ioptr2 == 0) return(TRUE);
1019 		simals_ioptr2->nodeptr = (NODE *)simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1020 		if (simals_ioptr2->nodeptr == 0) return(TRUE);
1021 		(void)estrcpy((CHAR *)simals_ioptr2->nodeptr, s1);
1022 		simals_ioptr2->strength = GATE_STRENGTH;
1023 		simals_ioptr2->next = 0;
1024 		*simals_ioptr1 = (CHAR*) simals_ioptr2;
1025 		simals_ioptr1 = (CHAR**) &(simals_ioptr2->next);
1026 
1027 		eof = simals_get_string(s1);
1028 		if (eof)
1029 		{
1030 			ttyputerr(_("Node declaration: EOF unexpectedly found"));
1031 			return(TRUE);
1032 		}
1033 		switch (s1[0])
1034 		{
1035 			case '=':
1036 			case '!':
1037 			case '>':
1038 			case '<':
1039 			case '+':
1040 			case '-':
1041 			case '*':
1042 			case '/':
1043 			case '%':
1044 				break;
1045 			default:
1046 				ttyputerr(_("Gate declaration: Invalid Operator '%s'"), s1);
1047 				return(TRUE);
1048 		}
1049 		simals_ioptr2->operatr = s1[0];
1050 
1051 		eof = simals_get_string(s1);
1052 		if (eof)
1053 		{
1054 			ttyputerr(_("Node declaration: EOF unexpectedly found"));
1055 			return(TRUE);
1056 		}
1057 		if (! (estrcmp(s1, x_("L")) && estrcmp(s1, x_("X")) && estrcmp(s1, x_("H"))))
1058 		{
1059 			simals_ioptr2->operand = (CHAR*) simals_trans_state_to_number(s1);
1060 		} else
1061 		{
1062 			--i_ptr;
1063 			if ((s1[0] == '+') || (s1[0] == '-') || ((s1[0] >= '0') && (s1[0] <= '9')))
1064 			{
1065 				eof = simals_get_int((INTBIG *)&simals_ioptr2->operand);
1066 				if (eof)
1067 				{
1068 					ttyputerr(_("Node declaration: EOF unexpectedly found"));
1069 					return(TRUE);
1070 				}
1071 			} else
1072 			{
1073 				eof = simals_get_name(s1);
1074 				if (eof)
1075 				{
1076 					ttyputerr(_("Node declaration: EOF unexpectedly found"));
1077 					return(TRUE);
1078 				}
1079 				simals_ioptr2->operand = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1080 				if (simals_ioptr2->operand == 0) return(TRUE);
1081 				(void)estrcpy(simals_ioptr2->operand, s1);
1082 				simals_ioptr2->operatr += 128;
1083 			}
1084 		}
1085 
1086 		eof = simals_get_string(s1);
1087 		if (eof || (s1[0] != '@'))
1088 		{
1089 			--i_ptr;
1090 			continue;
1091 		}
1092 		eof = simals_get_int(&(j));
1093 		if (eof)
1094 		{
1095 			ttyputerr(_("Node declaration: EOF unexpectedly found"));
1096 			return(TRUE);
1097 		}
1098 		simals_ioptr2->strength = (INTSML)j*2;
1099 	}
1100 	return(FALSE);
1101 }
1102 
1103 /*
1104  * Name: simals_trans_state_to_number
1105  *
1106  * Description:
1107  *	This procedure translates a state representation (L, H, X) that is
1108  * stored in a char to an integer value.
1109  *
1110  * Calling Arguments:
1111  *	s1 = pointer to character string that contains state value
1112  */
simals_trans_state_to_number(CHAR * s1)1113 INTBIG simals_trans_state_to_number(CHAR *s1)
1114 {
1115 	switch (s1[0])
1116 	{
1117 		case 'L': case 'l':
1118 			return(LOGIC_LOW);
1119 		case 'X': case 'x':
1120 			return(LOGIC_X);
1121 		case 'H': case 'h':
1122 			return(LOGIC_HIGH);
1123 		default:
1124 			return(simals_atoi(s1));
1125 	}
1126 }
1127 
1128 /*
1129  * Name: simals_parse_timing
1130  *
1131  * Description:
1132  *	This procedure inserts timing values into the appropriate places in
1133  * the database.  Returns true on error.
1134  */
simals_parse_timing(void)1135 BOOLEAN simals_parse_timing(void)
1136 {
1137 	BOOLEAN    eof;
1138 	CHAR   s1[256], s2[256];
1139 	float  value;
1140 
1141 	simals_delta_def = simals_linear_def = simals_exp_def = simals_random_def = simals_abs_def = 0;
1142 
1143 	for(;;)
1144 	{
1145 		eof = simals_get_string(s1);
1146 		if (eof)
1147 		{
1148 			ttyputerr(_("Timing declaration: EOF unexpectedly found"));
1149 			return(TRUE);
1150 		}
1151 
1152 		eof = simals_get_string(s2);
1153 		if (eof)
1154 		{
1155 			ttyputerr(_("Timing declaration: EOF unexpectedly found"));
1156 			return(TRUE);
1157 		}
1158 		if (s2[0] != '=')
1159 		{
1160 			ttyputerr(_("Timing declaration: Invalid Operator '%s' (expecting '=')"), s2);
1161 			return(TRUE);
1162 		}
1163 
1164 		eof = simals_get_float(&value);
1165 		if (eof)
1166 		{
1167 			ttyputerr(_("Timing declaration: EOF unexpectedly found"));
1168 			return(TRUE);
1169 		}
1170 
1171 		switch (s1[0])
1172 		{
1173 			case 'A':
1174 				simals_abs_def = value;
1175 				break;
1176 			case 'D':
1177 				simals_delta_def = value;
1178 				break;
1179 			case 'E':
1180 				simals_exp_def = value;
1181 				break;
1182 			case 'L':
1183 				simals_linear_def = value;
1184 				break;
1185 			case 'R':
1186 				simals_random_def = value;
1187 				if (value > 0.0) simals_modptr2->priority = 2;
1188 				break;
1189 			default:
1190 				ttyputerr(_("Invalid timing mode '%s'"), s1);
1191 				return(TRUE);
1192 		}
1193 
1194 		eof = simals_get_string(s1);
1195 		if (eof || (s1[0] != '+'))
1196 		{
1197 			--i_ptr;
1198 			break;
1199 		}
1200 	}
1201 	return(FALSE);
1202 }
1203 
1204 /*
1205  * Name: simals_parse_delay
1206  *
1207  * This procedure sets the delay transition type for the current input state.
1208  */
simals_parse_delay(void)1209 BOOLEAN simals_parse_delay(void)
1210 {
1211 	BOOLEAN   eof;
1212 	CHAR  s1[256];
1213 
1214 	eof = simals_get_string(s1);
1215 	if (eof)
1216 	{
1217 		ttyputerr(_("Timing declaration: EOF unexpectedly found"));
1218 		return(TRUE);
1219 	}
1220 
1221 	if (estrcmp(s1, x_("01")) && estrcmp(s1, x_("10")) && estrcmp(s1, x_("OZ")) && estrcmp(s1, x_("Z1"))
1222 		&& estrcmp(s1, x_("1Z")) && estrcmp(s1, x_("Z0")) && estrcmp(s1, x_("0X")) && estrcmp(s1, x_("X1"))
1223 		&& estrcmp(s1, x_("1X")) && estrcmp(s1, x_("X0")) && estrcmp(s1, x_("XZ")) && estrcmp(s1, x_("ZX")))
1224 	{
1225 		ttyputerr(_("Invalid delay transition name '%s'"), s1);
1226 		return(TRUE);
1227 	}
1228 	else
1229 		(void)esnprintf(delay, 16, x_("%s"), s1);
1230 
1231 	return(FALSE);
1232 }
1233 
1234 /*
1235  * Name: simals_parse_fanout
1236  *
1237  * Description:
1238  *	This procedure sets a flag in the model data structure regarding
1239  * if fanout calculations are to be performed for this models output.
1240  * If fanout calculations are required the model should have a single output.
1241  * Returns true on error.
1242  */
simals_parse_fanout(void)1243 BOOLEAN simals_parse_fanout(void)
1244 {
1245 	BOOLEAN   eof;
1246 	CHAR  s1[256];
1247 
1248 	eof = simals_get_string(s1);
1249 	if (eof)
1250 	{
1251 		ttyputerr(_("Fanout declaration: EOF unexpectedly found"));
1252 		return(TRUE);
1253 	}
1254 	if (s1[0] != '=')
1255 	{
1256 		ttyputerr(_("Fanout declaration: Invalid Operator '%s' (expecting '=')"), s1);
1257 		return(TRUE);
1258 	}
1259 
1260 	eof = simals_get_string(s1);
1261 	if (eof)
1262 	{
1263 		ttyputerr(_("Fanout declaration: EOF unexpectedly found"));
1264 		return(TRUE);
1265 	}
1266 
1267 	if (estrcmp(s1, x_("ON")) == 0)
1268 	{
1269 		simals_modptr2->fanout = 1;
1270 		return(FALSE);
1271 	}
1272 
1273 	if (estrcmp(s1, x_("OFF")) == 0)
1274 	{
1275 		simals_modptr2->fanout = 0;
1276 		return(FALSE);
1277 	}
1278 
1279 	ttyputerr(_("Fanout declaration: Invalid option '%s'"), s1);
1280 	return(TRUE);
1281 }
1282 
1283 /*
1284  * Name: simals_parse_load
1285  *
1286  * Description:
1287  *	This procedure enters the capacitive load rating (on per unit basis)
1288  * into the database for the specified node.  Returns true on error.
1289  */
simals_parse_load(void)1290 BOOLEAN simals_parse_load(void)
1291 {
1292 	BOOLEAN	eof;
1293 	CHAR    s1[256], s2[256];
1294 	float    load;
1295 	LOADPTR  loadptr2;
1296 	LOAD   **loadptr1;
1297 
1298 	loadptr1 = &simals_modptr2->loadptr;
1299 	for (loadptr2 = simals_modptr2->loadptr; loadptr2 != 0; loadptr2 = loadptr2->next)
1300 		loadptr1 = &loadptr2->next;
1301 
1302 	for(;;)
1303 	{
1304 		eof = simals_get_name(s1);
1305 		if (eof || (! (estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION"))
1306 			&& estrcmp(s1, x_("MODEL")) && estrcmp(s1, x_("I")) && estrcmp(s1, x_("O"))
1307 			&& estrcmp(s1, x_("T")) && estrcmp(s1, x_("FANOUT")) && estrcmp(s1, x_("LOAD"))
1308 			&& estrcmp(s1, x_("PRIORITY")) && estrcmp(s1, x_("SET")))))
1309 		{
1310 			--i_ptr;
1311 			break;
1312 		}
1313 
1314 		eof = simals_get_string(s2);
1315 		if (eof)
1316 		{
1317 			ttyputerr(_("Load declaration: EOF unexpectedly found"));
1318 			return(TRUE);
1319 		}
1320 		if (s2[0] != '=')
1321 		{
1322 			ttyputerr(_("Load declaration: Invalid Operator '%s' (expecting '=')"), s2);
1323 			return(TRUE);
1324 		}
1325 
1326 		eof = simals_get_float(&load);
1327 		if (eof)
1328 		{
1329 			ttyputerr(_("Load declaration: EOF unexpectedly found"));
1330 			return(TRUE);
1331 		}
1332 
1333 		loadptr2 = (LOADPTR) simals_alloc_mem((INTBIG)sizeof(LOAD));
1334 		if (loadptr2 == 0) return(TRUE);
1335 		loadptr2->ptr = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1336 		if (loadptr2->ptr == 0) return(TRUE);
1337 		(void)estrcpy(loadptr2->ptr, s1);
1338 		loadptr2->load = load;
1339 		loadptr2->next = 0;
1340 		*loadptr1 = loadptr2;
1341 		loadptr1 = &loadptr2->next;
1342 	}
1343 	return(FALSE);
1344 }
1345 
1346 /*
1347  * Name: simals_parse_model
1348  *
1349  * Description:
1350  *	This procedure parses the text used to describe a model entity.
1351  * The user specifies the interconnection of lower level primitives (gates and
1352  * functions) in this region of the netlist.  Returns true on error.
1353  */
simals_parse_model(void)1354 BOOLEAN simals_parse_model(void)
1355 {
1356 	BOOLEAN    eof;
1357 	CHAR    s1[256];
1358 	EXPORT **exptr1;
1359 	CONNECT **conptr1;
1360 
1361 	for(;;)
1362 	{
1363 		eof = simals_get_name(s1);
1364 		if (eof || (! (estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION")) && estrcmp(s1, x_("MODEL")))))
1365 		{
1366 			--i_ptr;
1367 			break;
1368 		}
1369 
1370 		if (s1[0] == '}') continue;
1371 
1372 		if (! estrcmp(s1, x_("SET")))
1373 		{
1374 			simals_ioptr1 = (CHAR**) &(simals_modptr2->setptr);
1375 			for (simals_ioptr2 = simals_modptr2->setptr; simals_ioptr2;
1376 				simals_ioptr2 = simals_ioptr2->next)
1377 			{
1378 				simals_ioptr1 = (CHAR**) &(simals_ioptr2->next);
1379 			}
1380 			if (simals_parse_node()) return(TRUE);
1381 			continue;
1382 		}
1383 
1384 		conptr1 = (CONNECT **)&simals_modptr2->ptr;
1385 		for(;;)
1386 		{
1387 			if (*conptr1 == 0)
1388 			{
1389 				simals_conptr2 = (CONPTR) simals_alloc_mem((INTBIG)sizeof(CONNECT));
1390 				if (simals_conptr2 == 0) return(TRUE);
1391 				simals_conptr2->inst_name = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1392 				if (simals_conptr2->inst_name == 0) return(TRUE);
1393 				(void)estrcpy(simals_conptr2->inst_name, s1);
1394 				simals_conptr2->model_name = 0;
1395 				simals_conptr2->exptr = 0;
1396 				simals_conptr2->next = 0;
1397 				simals_conptr2->display_page = 0;
1398 				*conptr1 = simals_conptr2;
1399 				break;
1400 			}
1401 			simals_conptr2 = *conptr1;
1402 			if (! estrcmp(simals_conptr2->inst_name, s1))
1403 			{
1404 				ttyputerr(_("ERROR: Instance name '%s' defined more than once"), s1);
1405 				return(TRUE);
1406 			}
1407 			conptr1 = &simals_conptr2->next;
1408 		}
1409 
1410 		eof = simals_get_name(s1);
1411 		if (eof)
1412 		{
1413 			ttyputerr(_("Model declaration: EOF unexpectedly found"));
1414 			return(TRUE);
1415 		}
1416 		simals_conptr2->model_name = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1417 		if (simals_conptr2->model_name == 0) return(TRUE);
1418 		(void)estrcpy(simals_conptr2->model_name, s1);
1419 
1420 
1421 		eof = simals_get_string(s1);
1422 		if (eof)
1423 		{
1424 			ttyputerr(_("Model declaration: EOF unexpectedly found"));
1425 			return(TRUE);
1426 		}
1427 		if (s1[0] != '(')
1428 		{
1429 			ttyputerr(_("Model declaration: Expecting to find '(' in place of string '%s'"), s1);
1430 			return(TRUE);
1431 		}
1432 
1433 		exptr1 = &simals_conptr2->exptr;
1434 		for(;;)
1435 		{
1436 			eof = simals_get_name(s1);
1437 			if (eof)
1438 			{
1439 				ttyputerr(_("Model declaration: EOF unexpectedly found"));
1440 				return(TRUE);
1441 			}
1442 			if (s1[0] == ')') break;
1443 			simals_exptr2 = (EXPTR) simals_alloc_mem((INTBIG)sizeof(EXPORT));
1444 			if (simals_exptr2 == 0) return(TRUE);
1445 			simals_exptr2->nodeptr = 0;
1446 			simals_exptr2->node_name = simals_alloc_mem((INTBIG)(estrlen(s1) + 1));
1447 			if (simals_exptr2->node_name == 0) return(TRUE);
1448 			(void)estrcpy(simals_exptr2->node_name, s1);
1449 			simals_exptr2->next = 0;
1450 			*exptr1 = simals_exptr2;
1451 			exptr1 = &simals_exptr2->next;
1452 		}
1453 	}
1454 	return(FALSE);
1455 }
1456 
1457 /*
1458  * Name: simals_parse_function
1459  *
1460  * Description:
1461  *      This procedure parses the text used to describe a function entity.
1462  * The user specifies input entries, loading factors, and timing parameters
1463  * in this region of the netlist.
1464  */
simals_parse_function(void)1465 BOOLEAN simals_parse_function(void)
1466 {
1467 	BOOLEAN    eof;
1468 	CHAR     s1[256];
1469 	INTBIG    j;
1470 	FUNCPTR  funchead;
1471 	EXPORT **exptr1;
1472 
1473 	simals_modptr2->fanout = 0;
1474 	simals_modptr2->ptr = simals_alloc_mem(sizeof(FUNC));
1475 	if (simals_modptr2->ptr == 0) return(TRUE);
1476 	funchead = (FUNCPTR)simals_modptr2->ptr;
1477 	funchead->procptr = 0;
1478 	funchead->inptr = 0;
1479 	funchead->delta = 0.0;
1480 	funchead->linear = 0.0;
1481 	funchead->exp = 0.0;
1482 	funchead->abs = 0.0;
1483 	funchead->random = 0.0;
1484 	funchead->userptr = 0;
1485 	funchead->userint = 0;
1486 	funchead->userfloat = 0.0;
1487 
1488 	for(;;)
1489 	{
1490 		eof = simals_get_string(s1);
1491 		if (eof || (!(estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION")) && estrcmp(s1, x_("MODEL")))))
1492 		{
1493 			--i_ptr;
1494 			break;
1495 		}
1496 
1497 		if (!estrcmp(s1, x_("I")))
1498 		{
1499 			exptr1 = &funchead->inptr;
1500 			for (simals_exptr2 = funchead->inptr; simals_exptr2;
1501 				simals_exptr2 = simals_exptr2->next)
1502 			{
1503 				exptr1 = &simals_exptr2->next;
1504 			}
1505 			if (simals_parse_func_input(exptr1)) return(TRUE);
1506 			continue;
1507 		}
1508 
1509 		if (!estrcmp(s1, x_("O")))
1510 		{
1511 			if (simals_parse_func_output()) return(TRUE);
1512 			continue;
1513 		}
1514 
1515 		if (!estrcmp(s1, x_("T")))
1516 		{
1517 			if (simals_parse_timing()) return(TRUE);
1518 			funchead->delta = simals_delta_def;
1519 			funchead->linear = simals_linear_def;
1520 			funchead->exp = simals_exp_def;
1521 			funchead->abs = simals_abs_def;
1522 			funchead->random = simals_random_def;
1523 			continue;
1524 		}
1525 
1526 		if (!estrcmp(s1, x_("LOAD")))
1527 		{
1528 			if (simals_parse_load()) return(TRUE);
1529 			continue;
1530 		}
1531 
1532 		if (!estrcmp(s1, x_("PRIORITY")))
1533 		{
1534 			eof = simals_get_int(&j);
1535 			if (eof)
1536 			{
1537 				ttyputerr(_("Priority declaration: EOF unexpectedly found"));
1538 				return(TRUE);
1539 			}
1540 			simals_modptr2->priority = (INTSML)j;
1541 			continue;
1542 		}
1543 
1544 		if (!estrcmp(s1, x_("SET")))
1545 		{
1546 			simals_ioptr1 = (CHAR**) &(simals_modptr2->setptr);
1547 			for (simals_ioptr2 = simals_modptr2->setptr; simals_ioptr2;
1548 				simals_ioptr2 = simals_ioptr2->next)
1549 			{
1550 				simals_ioptr1 = (CHAR**) &(simals_ioptr2->next);
1551 			}
1552 			(void)simals_parse_node();
1553 			continue;
1554 		}
1555 
1556 		ttyputerr(_("ERROR: String '%s' invalid syntax"), s1);
1557 		return(TRUE);
1558 	}
1559 	return(FALSE);
1560 }
1561 
1562 /*
1563  * Name: simals_parse_func_input
1564  *
1565  * Description:
1566  *      This procedure creates a list of input nodes which are used for event
1567  * driving the function.
1568  */
simals_parse_func_input(EXPORT ** exptr1)1569 BOOLEAN simals_parse_func_input(EXPORT **exptr1)
1570 {
1571 	BOOLEAN   eof;
1572 	CHAR    s1[256];
1573 
1574 	for(;;)
1575 	{
1576 		eof = simals_get_name(s1);
1577 		if (eof || (!(estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION"))
1578 			&& estrcmp(s1, x_("MODEL")) && estrcmp(s1, x_("I")) && estrcmp(s1, x_("O"))
1579 			&& estrcmp(s1, x_("T")) && estrcmp(s1, x_("FANOUT")) && estrcmp(s1, x_("LOAD"))
1580 			&& estrcmp(s1, x_("PRIORITY")) && estrcmp(s1, x_("SET")))))
1581 		{
1582 			--i_ptr;
1583 			break;
1584 		}
1585 
1586 		simals_exptr2 = (EXPTR)simals_alloc_mem(sizeof(EXPORT));
1587 		if (simals_exptr2 == 0) return(TRUE);
1588 		simals_exptr2->nodeptr = 0;
1589 		simals_exptr2->node_name = simals_alloc_mem(estrlen(s1) + 1);
1590 		if (simals_exptr2->node_name == 0) return(TRUE);
1591 		(void)estrcpy(simals_exptr2->node_name, s1);
1592 		simals_exptr2->next = 0;
1593 		*exptr1 = simals_exptr2;
1594 		exptr1 = &simals_exptr2->next;
1595 	}
1596 	return(FALSE);
1597 }
1598 
1599 /*
1600  * Name: simals_parse_func_output
1601  *
1602  * Description:
1603  *      This procedure creates a list of output nodes for the function.
1604  */
simals_parse_func_output(void)1605 BOOLEAN simals_parse_func_output(void)
1606 {
1607 	BOOLEAN   eof;
1608 	CHAR    s1[256];
1609 
1610 	for(;;)
1611 	{
1612 		eof = simals_get_name(s1);
1613 		if (eof || (!(estrcmp(s1, x_("GATE")) && estrcmp(s1, x_("FUNCTION"))
1614 			&& estrcmp(s1, x_("MODEL")) && estrcmp(s1, x_("I")) && estrcmp(s1, x_("O"))
1615 			&& estrcmp(s1, x_("T")) && estrcmp(s1, x_("FANOUT")) && estrcmp(s1, x_("LOAD"))
1616 			&& estrcmp(s1, x_("PRIORITY")) && estrcmp(s1, x_("SET")))))
1617 		{
1618 			--i_ptr;
1619 			break;
1620 		}
1621 
1622 		for (simals_exptr2 = simals_modptr2->exptr; ; simals_exptr2 = simals_exptr2->next)
1623 		{
1624 			if (!simals_exptr2)
1625 			{
1626 				ttyputerr(_("ERROR: Unable to find node %s in port list"), s1);
1627 				return(TRUE);
1628 			}
1629 			if (!estrcmp(s1, simals_exptr2->node_name))
1630 			{
1631 				simals_exptr2->nodeptr = (NODEPTR)1;
1632 				break;
1633 			}
1634 		}
1635 	}
1636 	return(FALSE);
1637 }
1638 
1639 /*
1640  * Name: simals_fragment_command
1641  *
1642  * Description:
1643  *	This procedure processes the string specified by the calling argument
1644  * and fragments it into a series of smaller character strings, each of which
1645  * is terminated by a null character.  Returns true on error.
1646  *
1647  * Calling Arguments:
1648  *	line = pointer to the character string to be fragmented
1649  */
simals_fragment_command(CHAR * line)1650 BOOLEAN simals_fragment_command(CHAR *line)
1651 {
1652 	INTBIG   i, j, k, count;
1653 
1654 	j = count = simals_instptr[0] = simals_instbuf[0] = 0;
1655 	k = 1;
1656 
1657 	for (i = 0; ; ++i)
1658 	{
1659 		if (j > (simals_ibufsize - 3))
1660 		{
1661 			if (simals_alloc_char_buffer(&simals_instbuf, &simals_ibufsize,
1662 				(simals_ibufsize * 5))) return(TRUE);
1663 		}
1664 		if (k > (simals_iptrsize - 2))
1665 		{
1666 			if (simals_alloc_ptr_buffer(&simals_instptr, &simals_iptrsize,
1667 				(simals_iptrsize * 5))) return(TRUE);
1668 		}
1669 
1670 		if (line[i] == 0 || line[i] == '\n')
1671 		{
1672 			if (count)
1673 			{
1674 				simals_instbuf[j] = 0;
1675 				simals_instptr[k] = -1;
1676 			} else
1677 			{
1678 				simals_instptr[k-1] = -1;
1679 			}
1680 			break;
1681 		}
1682 		switch (line[i])
1683 		{
1684 			case ' ':
1685 			case ',':
1686 			case '\t':
1687 			case '=':
1688 			case '@':
1689 				if (count)
1690 				{
1691 					simals_instbuf[j] = 0;
1692 					simals_instptr[k] = j+1;
1693 					++j;
1694 					++k;
1695 					count = 0;
1696 				}
1697 				break;
1698 
1699 			default:
1700 				simals_instbuf[j] = line[i];
1701 				++j;
1702 				++count;
1703 		}
1704 	}
1705 	return(FALSE);
1706 }
1707 
1708 /*
1709  * Name: simals_compute_node_name
1710  *
1711  * Description:
1712  *	This procedure composes a character string which indicates the node name
1713  * for the nodeptr specified in the calling argument.
1714  *
1715  * Calling Arguments:
1716  *	nodehead = pointer to desired node in database
1717  *	sp	= pointer to char string where complete name is to be saved
1718  */
simals_compute_node_name(NODEPTR nodehead,CHAR * sp)1719 void simals_compute_node_name(NODEPTR nodehead, CHAR *sp)
1720 {
1721 	CONPTR  cellhead;
1722 	EXPTR   exhead;
1723 
1724 	cellhead = nodehead->cellptr;
1725 	estrcpy(sp, simals_compute_path_name(cellhead));
1726 
1727 	for (exhead = cellhead->exptr; ; exhead = exhead->next)
1728 	{
1729 		if (nodehead == exhead->nodeptr)
1730 		{
1731 			(void)estrcat(sp, x_("."));
1732 			(void)estrcat(sp, exhead->node_name);
1733 			return;
1734 		}
1735 	}
1736 }
1737 
1738 /*
1739  * Name: simals_compute_path_name
1740  *
1741  * Description:
1742  *	This procedure composes a character string which indicates the path name
1743  * to the level of hierarchy specified in the calling argument.
1744  *
1745  * Calling Arguments:
1746  *	cellhead = pointer to desired level of hierarchy
1747  *	sp	= pointer to char string where path name is to be saved
1748  */
simals_compute_path_name(CONPTR cellhead)1749 CHAR *simals_compute_path_name(CONPTR cellhead)
1750 {
1751 	REGISTER void *infstr;
1752 
1753 	infstr = initinfstr();
1754 	for ( ; cellhead; cellhead = cellhead->parent)
1755 		formatinfstr(infstr, x_(".%s"), cellhead->inst_name);
1756 	return(returninfstr(infstr));
1757 }
1758 
1759 /*
1760  * Name: simals_find_node
1761  *
1762  * Description:
1763  *	This procedure returns a pointer to the calling routine which indicates
1764  * the address of the node entry in the database.  The calling argument string
1765  * contains information detailing the path name to the desired node.
1766  *
1767  * Calling Argument:
1768  *	sp = pointer to char string containing path name to node
1769  */
simals_find_node(CHAR * sp)1770 NODEPTR simals_find_node(CHAR *sp)
1771 {
1772 	INTBIG	i;
1773 	CHAR    s1[80], *s2;
1774 	CONPTR   cellptr;
1775 	EXPTR    exhead;
1776 	NODEPTR  nodehead;
1777 
1778 	if ((sp[0] == '$') && (sp[1] == 'N'))
1779 	{
1780 		i = eatoi(&(sp[2]));
1781 		for (nodehead = simals_noderoot; nodehead; nodehead = nodehead->next)
1782 		{
1783 			if (nodehead->num == i) return(nodehead);
1784 		}
1785 		return(0);
1786 	}
1787 
1788 	(void)estrcpy(s1, sp);
1789 	s2 = s1;
1790 	for (i = 0; s1[i]; ++i)
1791 	{
1792 		if (s1[i] == '.') s2 = &(s1[i+1]);
1793 	}
1794 
1795 	if (s2 > s1)
1796 	{
1797 		*(s2 - 1) = 0;
1798 		cellptr = simals_find_level(s1);
1799 	} else
1800 	{
1801 		cellptr = simals_levelptr;
1802 	}
1803 	if (cellptr == 0) return(0);
1804 
1805 	for (exhead = cellptr->exptr; exhead; exhead = exhead->next)
1806 	{
1807 		if (! estrcmp(exhead->node_name, s2)) return(exhead->nodeptr);
1808 	}
1809 
1810 	return(0);
1811 }
1812 
1813 /*
1814  * command parsing routines for instance names
1815  */
1816 static CONPTR  sim_als_cellptr;
1817 
simals_topofinstances(CHAR ** c)1818 BOOLEAN simals_topofinstances(CHAR **c)
1819 {
1820 	Q_UNUSED( c );
1821 	if (simals_levelptr == 0) return(FALSE);
1822 	sim_als_cellptr = simals_levelptr->child;
1823 	return(TRUE);
1824 }
1825 
simals_nextinstance(void)1826 CHAR *simals_nextinstance(void)
1827 {
1828 	REGISTER void *infstr;
1829 
1830 	if (sim_als_cellptr == 0) return(0);
1831 	infstr = initinfstr();
1832 	formatinfstr(infstr, x_("%s (%s)"), sim_als_cellptr->inst_name, sim_als_cellptr->model_name);
1833 	sim_als_cellptr = sim_als_cellptr->next;
1834 	return(returninfstr(infstr));
1835 }
1836 
1837 /*
1838  * Name: simals_find_level
1839  *
1840  * Description:
1841  *	This procedure returns a pointer to a structure in the cross reference
1842  * table. The calling argument string contains information detailing the path
1843  * name to the desired level in the cross reference table.
1844  *
1845  * Calling Argument:
1846  *	sp = pointer to char string containing path name to level in xref table
1847  */
simals_find_level(CHAR * sp)1848 CONPTR simals_find_level(CHAR *sp)
1849 {
1850 	INTBIG    i, j;
1851 	CHAR    s1[80];
1852 	CONPTR  cellptr;
1853 
1854 	if (sp[0] == '.')
1855 	{
1856 		cellptr = simals_cellroot;
1857 		if (cellptr == 0) return(0);
1858 		i = 1;
1859 	} else
1860 	{
1861 		if (simals_levelptr == 0) return(0);
1862 		cellptr = simals_levelptr->child;
1863 		i = 0;
1864 	}
1865 
1866 	for(j = 0; ; ++i)
1867 	{
1868 		if ((sp[i] == '.') || ! (sp[i]))
1869 		{
1870 			for(s1[j] = 0; ; cellptr = cellptr->next)
1871 			{
1872 				if (! cellptr) return(0);
1873 				if (! estrcmp(s1, cellptr->inst_name))
1874 				{
1875 					if (! (sp[i])) return(cellptr);
1876 					cellptr = cellptr->child;
1877 					j = 0;
1878 					break;
1879 				}
1880 			}
1881 			continue;
1882 		}
1883 		s1[j] = sp[i];
1884 		++j;
1885 	}
1886 }
1887 
1888 /*
1889  * Name: simals_trans_number_to_state
1890  *
1891  * Description:
1892  *	This procedure translates an integer value that represents a state
1893  * and returns a single character corresponding to the state.
1894  *
1895  * Calling Arguments:
1896  *	state_num = integer value that is to be converted to a character
1897  */
simals_trans_number_to_state(INTBIG state_num)1898 CHAR *simals_trans_number_to_state(INTBIG state_num)
1899 {
1900 	static CHAR s1[20];
1901 
1902 	switch (state_num)
1903 	{
1904 		case LOGIC_LOW:
1905 			(void)estrcpy(s1, x_("L"));
1906 			break;
1907 		case LOGIC_X:
1908 			(void)estrcpy(s1, x_("X"));
1909 			break;
1910 		case LOGIC_HIGH:
1911 			(void)estrcpy(s1, x_("H"));
1912 			break;
1913 		default:
1914 			(void)esnprintf(s1, 20, x_("0x%lX"), state_num);
1915 			break;
1916 	}
1917 	return(s1);
1918 }
1919 
1920 #endif  /* SIMTOOL - at top */
1921