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