source: vis_dev/vis-2.3/src/synth/synth.c @ 45

Last change on this file since 45 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 21.8 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [synth.c]
4
5  PackageName [synth]
6
7  Synopsis    [Commands for synthesize_network.]
8
9  Description [External procedures included in this module:
10                <ul>
11                <li> Synth_Init()
12                <li> Synth_End()
13                </ul>
14        Static procedures included in this module:
15                <ul>
16                <li> CommandSynthesizeNetwork()
17                <li> TimeOutHandle()
18                </ul> ]
19
20  Author      [Balakrishna Kumthekar, In-Ho Moon]
21
22  Copyright   [This file was created at the University of Colorado at
23  Boulder.  The University of Colorado at Boulder makes no warranty
24  about the suitability of this software for any purpose.  It is
25  presented on an AS IS basis.]
26
27******************************************************************************/
28
29#include "synthInt.h"
30
31static char rcsid[] UNUSED = "$Id: synth.c,v 1.60 2005/05/16 06:22:00 fabio Exp $";
32
33/*---------------------------------------------------------------------------*/
34/* Constant declarations                                                     */
35/*---------------------------------------------------------------------------*/
36
37
38/*---------------------------------------------------------------------------*/
39/* Stucture declarations                                                     */
40/*---------------------------------------------------------------------------*/
41
42
43/*---------------------------------------------------------------------------*/
44/* Type declarations                                                         */
45/*---------------------------------------------------------------------------*/
46
47
48/*---------------------------------------------------------------------------*/
49/* Variable declarations                                                     */
50/*---------------------------------------------------------------------------*/
51
52extern  int             VerifyTreeMode;
53
54static  jmp_buf         timeOutEnv;
55
56/*---------------------------------------------------------------------------*/
57/* Macro declarations                                                        */
58/*---------------------------------------------------------------------------*/
59
60
61/**AutomaticStart*************************************************************/
62
63/*---------------------------------------------------------------------------*/
64/* Static function prototypes                                                */
65/*---------------------------------------------------------------------------*/
66
67static int CommandSynthesizeNetwork(Hrc_Manager_t **hmgr, int argc, char **argv);
68static void TimeOutHandle(void);
69static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
70
71/**AutomaticEnd***************************************************************/
72
73
74/*---------------------------------------------------------------------------*/
75/* Definition of exported functions                                          */
76/*---------------------------------------------------------------------------*/
77
78/**Function********************************************************************
79
80  Synopsis    [This function initializes the synth package.]
81
82  Description [This function initializes the synth package.]
83
84  SideEffects [Installs the synthesize_network command.]
85
86  SeeAlso     [Synth_End()]
87
88******************************************************************************/
89void
90Synth_Init(void)
91{
92  Cmd_CommandAdd("synthesize_network", CommandSynthesizeNetwork, 0);
93}
94
95/**Function********************************************************************
96
97  Synopsis    [This function ends the synth package.]
98
99  Description [This function ends the synth package.]
100
101  SideEffects [none]
102
103  SeeAlso     [Synth_Init()]
104
105******************************************************************************/
106void
107Synth_End(void)
108{
109}
110
111/*---------------------------------------------------------------------------*/
112/* Definition of internal functions                                          */
113/*---------------------------------------------------------------------------*/
114
115/*---------------------------------------------------------------------------*/
116/* Definition of static functions                                            */
117/*---------------------------------------------------------------------------*/
118
119/**Function********************************************************************
120
121  Synopsis [Implements the synthesize_network command.]
122
123  Description [This function synthesizes a network to have as few
124  literals as possible and outputs a blif file and an equation file.
125  Those files are the results of the synthesis. By default, the names
126  of the files are model_name.ml.blif and model_name.eq unless users
127  specify the model_name explicitly using -o option. But, when the
128  output blif file is read in sis, it may have slightly different
129  number of literals. This problem will be fixed in the later version.
130  Currently, this command can be used only with CUDD package.
131
132  Designs described in BLIF or BLIF-MV format can be synthesized by
133  this command. However, multiple valued variables are not
134  supported. Hence, signals in the designs described in BLIF-MV need
135  to be restricted to binary values.]
136
137  SideEffects [None]
138
139  SeeAlso []
140
141  CommandName [synthesize_network]
142
143  CommandSynopsis [Synthesizes a network using ZDD factorization method.]
144
145  CommandArguments [\[-d &lt;divisor&gt;\] \[-e\] \[-f &lt;factoringMethod&gt;\]
146  \[-h\] \[-i &lt;prefix&gt;\] \[-o &lt;fileHead&gt;\]
147  \[-r &lt;reachMethod&gt;\]
148  \[-t &lt;timeOut&gt;\] \[-v\] \[-A\] \[-O &lt;outputOrdering&gt;\]
149  \[-R &lt;reorder&gt;\] \[-T\]]
150
151  CommandDescription [This command synthesizes a network to have as few
152  literals as possible and outputs a blif file and an equation file.  Those
153  files are the results of the synthesis. By default, the names of the files
154  are model_name.ml.blif and model_name.eq unless users specify the model_name
155  explicitly using -o option. But, when the output blif file is read in sis, it
156  may have slightly different number of literals. This problem will be fixed in
157  the later version.  Currently, this command can be used only with CUDD
158  package.
159
160  Designs described in BLIF or BLIF-MV format can be synthesized by this
161  command. However, multiple valued variables are not supported. Hence, signals
162  in the designs described in BLIF-MV need to be restricted to binary values.
163
164  There are 4 divisor functions to find a good divisor of a function. Neither
165  of them consistently generates the best result. And, there are 2 factoring
166  methods: simple factoring and generic factoring. Also, neither of two always
167  does better than the other.  <p>
168
169  Command options:<p>
170
171  <dl>
172
173  <dt> -d &lt;divisor&gt;
174  <dd> Choose a divisor.<p>
175  <dd>
176  0 : Fast divisor. We find a divisor on a ZDD graph. As soon as any
177  shared node(variable) is found, the variable is returned as a divisor.
178  <p>
179
180  1 : (default) Least occuring literal divisor. If a variable occurs the least
181  frequently(but, should be more than one) in cubes, it returns the
182  variable as a divisor. <p>
183
184  2 : Most occuring literal divisor. If a variable occurs the most frequently
185  in cubes, it returns the variable as a divisor. <p>
186
187  3 : Level-0 divisor. It finds a divisor that is a level-0 cokernel.
188  <p>
189
190  <dt> -e
191  <dd> Dump the synthesized circuit in equation format also. Default is
192  not to.  <p>
193
194  <dt> -f &lt;factoringMethod&gt;
195  <dd> Choose a factoring method.<p>
196  <dd>
197  0 : (default) Simple factoring. This method uses a simple recursion. First,
198  it finds a proper divisor of a function, then divide the function by the
199  divisor, then it gets a quotient and a remainder. And, it does the
200  same thing recursively for each divisor, quotient, and
201  remainder. <p>
202
203  1 : Generic factoring. This method is quite similar to the simple
204  factoring, but it does more in terms of considering cube-free and
205  common divisor and literal factoring. But, it does not always generate
206  better results than the simple factoring does. <p>
207
208  <dt> -h
209  <dd> Print the command usage. <p>
210
211  <dt> -i &lt;prefix&gt;
212  <dd> Specify the prefix of internal node names. By default, the prefix
213  is "_n". <p>
214
215  <dt> -o &lt;fileHead&gt;
216  <dd> Specify the output file name (without extension). By default, the model
217  name in a blif file is used. <p>
218
219  <dt> -r &lt;reachMethod&gt;
220  <dd> If the network is sequential, then use unreachable states as dont cares
221  in the optimization. By default no reachability analysis is performed. See
222  -A option of command compute_reach for more details. The various options
223  are:<p>
224  <dd>
225  0 : Do not use dont cares (default). <p>
226
227  1 : Use normal breadth first search method for reachability analysis. <p>
228
229  2 : Use high density traversal method for reachablity analysis. <p>
230
231  3 : Use approximate unreachable states(a subset of actual unreachable states)
232  as dont cares. <p>
233
234  <dt> -t &lt;timeOut&gt;
235  <dd> Time in seconds allowed to perform synthesize_network.  The default is
236  no limit.<p>
237
238  <dt> -v
239  <dd> Print debug information. <p>
240
241  <dt> -A
242  <dd> Allow realignment to ZDD/BDD after BDD/ZDD reordering, respectively.
243  This option is effective when only one reordering in BDD or ZDD is enabled.
244
245  <dt> -O &lt;outputOrdering&gt;
246  <dd> Choose an output ordering method. <p>
247  <dd>
248  0 : No ordering. <p>
249
250  1 : (default) Use support variable set of output functions. <p>
251
252  2 : Use BDD size of output functions. <p>
253
254  <dt> -R &lt;reorder&gt;
255  <dd> Allow reordering in BDD and/or ZDD. <p>
256  <dd>
257  0 or n : (default) No reordering neither in BDD nor in ZDD. <p>
258
259  1 or b : Allows reordering only in BDD, not in ZDD. <p>
260
261  2 or z : Allows reordering only in ZDD, not in BDD. <p>
262
263  3 or a : Allows reordering both in BDD and in ZDD. <p>
264
265  <dt> -T
266  <dd> Try to share more nodes during symbolic factorization. Existing
267  divisors are checked for potential reuse before extracting divisors from the
268  current boolean function.<p>
269
270  <\dl>
271  ]
272
273******************************************************************************/
274static int
275CommandSynthesizeNetwork(Hrc_Manager_t **hmgr,
276                         int argc,
277                         char **argv)
278{
279  Ntk_Network_t *network1;
280  Ntk_Node_t *node;
281  bdd_manager *ddManager;
282  int timeOutPeriod;
283  int createdMgr;
284  int factoring, divisor;
285  int unreachDC, verbosity;
286  int result, varOrdered;
287  long initialTime, finalTime;
288  char *filehead,*filename;
289  char *prefix;
290  FILE *fp;
291  int c;
292  lsList dummy = (lsList) 0;
293  lsGen gen;
294  Synth_InfoData_t *synthInfo;
295  char *reorder = NIL(char);
296  int reordering;
297  int trySharing;
298  int realign;
299  int outputOrdering;
300  boolean eqn;
301
302  if (bdd_get_package_name() != CUDD) {
303    (void) fprintf(vis_stderr,
304 "** synth error: synthesize_network can be used only with the CUDD package\n");
305    (void) fprintf(vis_stderr,
306                   "** synth error: Please link with CUDD package\n");
307    return 1;
308  }
309
310  /* To keep the Alpha compilers happy. */
311  network1 = NIL(Ntk_Network_t);
312  node = NIL(Ntk_Node_t);
313  ddManager = NIL(bdd_manager);
314  synthInfo = NIL(Synth_InfoData_t);
315
316  /* These are the default values. */
317  timeOutPeriod   = 0;
318  createdMgr      = 0;
319  factoring       = 0; /* Simple factoring algorithm. */
320  divisor         = 1; /* Quick divisor */
321  unreachDC       = 0; /* Do not use unreachable states as DCs */
322  filehead        = NIL(char);
323  filename        = NIL(char);
324  prefix          = NIL(char);
325  fp              = NIL(FILE);
326  reordering      = 0;
327  trySharing      = 0;
328  realign         = 0;
329  verbosity       = 0;
330  varOrdered      = 0;
331  outputOrdering  = 0;
332  eqn             = 0;
333  util_getopt_reset();
334
335  while((c = util_getopt(argc, argv, "d:ef:hi:o:r:t:vAO:R:TV:")) != EOF) {
336    switch(c) {
337    case 'd':
338      divisor = atoi(util_optarg);
339      if (divisor < 0 || divisor > 3)
340        goto usage;
341      break;
342    case 'e':
343      eqn = 1;
344      break;
345    case 'f':
346      factoring = atoi(util_optarg);
347      if (factoring < 0 || factoring > 1)
348        goto usage;
349      break;
350    case 'h':
351      goto usage;
352    case 'i':
353      prefix = util_strsav(util_optarg);
354      break;
355    case 'o':
356      filehead = util_strsav(util_optarg);
357      break;
358    case 'r':
359      unreachDC = atoi(util_optarg);
360      break;
361    case 't':
362      timeOutPeriod = atoi(util_optarg);
363      break;
364    case 'v':
365      verbosity = 1;
366      break;
367    case 'A':
368      realign = 1;
369      break;
370    case 'O':
371      outputOrdering = atoi(util_optarg);
372      if (outputOrdering < 0 || outputOrdering > 2)
373        goto usage;
374      SynthSetOutputOrdering(outputOrdering);
375      break;
376    case 'R':
377      reorder = util_strsav(util_optarg);
378      if (reorder[0] == '0' || reorder[0] == 'n')
379        reordering = 0;
380      else if (reorder[0] == '1' || reorder[0] == 'b')
381        reordering = 1;
382      else if (reorder[0] == '2' || reorder[0] == 'z')
383        reordering = 2;
384      else if (reorder[0] == '3' || reorder[0] == 'a')
385        reordering = 3;
386      else
387        goto usage;
388      break;
389    case 'T':
390      trySharing = 1;
391      break;
392    case 'V':
393      VerifyTreeMode = atoi(util_optarg);
394      break;
395    default:
396      if (util_optarg)
397        (void) fprintf(vis_stderr,
398                        "** synth error: Unknown option %s\n",util_optarg);
399      else
400        (void) fprintf(vis_stderr,"** synth error: Unknown option ?\n");
401      goto usage;
402    }
403  }
404
405  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
406    (void)fprintf(vis_stderr,"** synth error: The hierarchy manager is empty.");
407    (void)fprintf(vis_stderr,"** synth error: Read in design.\n");
408    goto endgame;
409  }
410
411  network1 = (Ntk_Network_t *) 
412    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
413                         NTK_HRC_NODE_APPL_KEY);
414
415  if(network1 == NIL(Ntk_Network_t)) {
416    (void) fprintf(vis_stderr, "** synth error: There is no network. ");
417    (void) fprintf(vis_stderr,"** synth error:Use flatten_hierarchy.\n");
418    goto endgame;
419  }
420
421  /* Check if the current network has signals with multiple values. */
422  if (TestIsNetworkMultipleValued(network1)) {
423    (void) fprintf(vis_stderr,
424                   "** synth error: Circuit has multiple valued variables.\n");
425    (void) fprintf(vis_stderr,
426        "** synth error: This command works with boolean signals only.\n");
427    goto endgame;
428  }
429
430  if (!filehead)
431    filehead = util_strsav(Ntk_NetworkReadName(network1));
432
433  /* Check if the output equation file already exists */
434  if (eqn) {
435    filename = util_strcat3(filehead,".eq","");
436    fp = Cmd_FileOpen(filename,"r",NIL(char *),1);
437    if (fp) {
438      (void) fprintf(vis_stderr,
439                "** synth error: Output equation file %s already exists.\n",
440                filename);
441      (void) fprintf(vis_stderr,
442                "** synth error: Please specify another name.\n");
443      fclose(fp);
444      FREE(filename);
445      goto endgame;
446    }
447    FREE(filename);
448  }
449  /* Check if the output blif file already exists */
450  filename = util_strcat3(filehead,".ml.blif","");
451  fp = Cmd_FileOpen(filename,"r",NIL(char *),1);
452  if (fp) {
453    (void) fprintf(vis_stderr,
454                   "** synth error: Output blif file %s already exists.\n",
455                   filename);
456    (void) fprintf(vis_stderr,"** synth error: Please specify another name.\n");
457    fclose(fp);
458    FREE(filename);
459    goto endgame;
460  }
461  FREE(filename);
462
463  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
464     Ntk_NetworkReadNumInputs(network1)) {
465    (void) fprintf(vis_stderr,
466                   "** synth error: Pseudo inputs present in the network.\n");
467    (void) fprintf(vis_stderr,
468                   "** synth error: Cannot synthesize the network\n");
469    goto endgame;
470  }
471
472  ddManager = (bdd_manager *) Ntk_NetworkReadMddManager(network1);
473  if (ddManager == NIL(bdd_manager)) {
474    ddManager = (bdd_manager *)Ntk_NetworkInitializeMddManager(network1);
475    if (ddManager == NIL(bdd_manager)) {
476      (void) fprintf(vis_stderr,
477                     "** synth error: Could not create Mdd Manager\n");
478      goto endgame;
479    }
480    createdMgr = 1;
481  }
482
483  /* Check if the network has the variables ordered.
484   * For combinational synthesis we are only interested in the primary
485   * input variables. But for sequential synthesis we need primary inputs,
486   * present state variables and next state variables (to use in
487   * reachability analysis and use the unreachable states as dont cares).
488   */
489
490  if (Ord_NetworkTestAreVariablesOrdered(network1, Ord_InputAndLatch_c) == 
491      FALSE) {
492    Ord_NetworkOrderVariables(network1,Ord_RootsByDefault_c,
493                              Ord_NodesByDefault_c, FALSE,
494                              Ord_InputAndLatch_c,Ord_Unassigned_c,
495                              dummy,0);
496    varOrdered = 1;
497  }
498   
499  /* Start the timer. */
500  if (timeOutPeriod > 0){
501    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
502    (void) alarm(timeOutPeriod);
503    if (setjmp(timeOutEnv) > 0) {
504      (void) fprintf(vis_stderr, "** synth warning: Timeout occurred after ");
505      (void) fprintf(vis_stderr, "%d seconds.\n", timeOutPeriod);
506      alarm(0);
507      goto endgame;
508    }
509  }
510
511  synthInfo = Synth_InitializeInfo(factoring,divisor,unreachDC,
512                                   reordering,trySharing,realign,
513                                   filehead,prefix,eqn);
514  if (!synthInfo)
515    goto endgame;
516
517  /* Synthesize.*/
518  initialTime = util_cpu_time();
519
520  result = Synth_SynthesizeNetwork(network1,NIL(graph_t), 
521                                   NIL(st_table),synthInfo,
522                                   verbosity);
523
524  finalTime = util_cpu_time();
525
526  if (result) {
527    (void) fprintf(vis_stdout, "%-20s%10ld\n", "analysis time =",
528                   (finalTime-initialTime)/1000);
529  } else {
530    (void) fprintf(vis_stdout, "** synth error: Could not synthesize.\n");
531  }
532
533  /* Set the mdd id's for all the nodes to unassigned if it
534   * was specifically set in this routine.
535   */
536  if (varOrdered) {
537    Ntk_NetworkForEachPrimaryInput(network1,gen,node) {
538      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);
539    }
540    Ntk_NetworkForEachLatch(network1,gen,node) {
541      Ntk_Node_t *shadow;
542      shadow = Ntk_NodeReadShadow(node);
543      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);   
544      Ntk_NodeSetMddId(shadow,NTK_UNASSIGNED_MDD_ID);   
545    }
546  }
547
548  if (createdMgr) {
549    mdd_quit((mdd_manager *)ddManager);
550    Ntk_NetworkSetMddManager(network1,NIL(mdd_manager));
551  }
552
553  if (reorder)
554    FREE(reorder);
555  if (filehead)
556    FREE(filehead);
557  if (prefix)
558    FREE(prefix);
559
560  if (synthInfo)
561    Synth_FreeInfo(synthInfo);
562
563  alarm(0);
564  return 0;  /* normal exit */
565
566 endgame:
567  if (varOrdered) {
568    Ntk_NetworkForEachNode(network1,gen,node) {
569      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);
570    }
571  }
572
573  if (createdMgr) {
574    mdd_quit((mdd_manager *)ddManager);
575    Ntk_NetworkSetMddManager(network1,NIL(mdd_manager));
576  }
577
578  if (reorder)
579    FREE(reorder);
580  if(filehead)
581    FREE(filehead);
582  if(prefix)
583    FREE(prefix);
584
585  if (synthInfo)
586    Synth_FreeInfo(synthInfo);
587
588  return 1;
589
590 usage:
591  (void) fprintf(vis_stderr, "usage: synthesize_network [-d divisor] [-e] [-f factoringMethod] [-h] [-i prefix] [-o fileHead] [-r reachMethod] [-t timeOut] [-v] [-A] [-O outputOrdering] [-R reorder] [-T]\n");
592  (void) fprintf(vis_stderr, "   -d n\t\tChoose a divisor function (0-4)\n");
593  (void) fprintf(vis_stderr, "   \t\t\t0: Fast divisor\n");
594  (void) fprintf(vis_stderr,
595                 "   \t\t\t1: Least occuring literal divisor (default)\n");
596  (void) fprintf(vis_stderr, "   \t\t\t2: Most occuring literal divisor\n");
597  (void) fprintf(vis_stderr, "   \t\t\t3: Level-0 kernel divisor\n");
598  (void) fprintf(vis_stderr, "   -e n\t\tOutput equation format file\n");
599  (void) fprintf(vis_stderr, "   -f n\t\tChoose a factoring method(0-1)\n");
600  (void) fprintf(vis_stderr, "   \t\t\t0: Simple factoring (default)\n");
601  (void) fprintf(vis_stderr, "   \t\t\t1: Generic factoring\n");
602  (void) fprintf(vis_stderr, "   -h\t\tPrint the command usage\n");
603  (void) fprintf(vis_stderr, "   -i prefix\tPrefix of internal node names.\n");
604  (void) fprintf(vis_stderr,
605                 "   -o name\tName of output file (without extension)\n");
606  (void) fprintf(vis_stderr,
607                 "   -r n\t\tUse unreachable states for sequential circuits\n");
608  (void) fprintf(vis_stderr, "   \t\tas dont cares(0-3)\n");
609  (void) fprintf(vis_stderr,
610         "   \t\t\t0: Do not use unreachable states (default).\n");
611  (void) fprintf(vis_stderr,
612         "   \t\t\t1: Use normal BFS method for reachability analysis.\n");
613  (void) fprintf(vis_stderr,
614         "   \t\t\t2: Use high density method for reachability analysis.\n");
615  (void) fprintf(vis_stderr,
616         "   \t\t\t3: Use approximate unreachable states as dont cares.\n");
617  (void) fprintf(vis_stderr, "   -t time\tTime out period (in seconds)\n");
618  (void) fprintf(vis_stderr, "   -v \t\tVerbosity On.\n");
619  (void) fprintf(vis_stderr,
620                 "   -A \t\tAllow realignment after BDD/ZDD reordering.\n");
621  (void) fprintf(vis_stderr,
622                 "   -O n\t\tChoose an output ordering method(0-2)\n");
623  (void) fprintf(vis_stderr, "   \t\t\t0: no ordering\n");
624  (void) fprintf(vis_stderr, "   \t\t\t1: support variable set (default)\n");
625  (void) fprintf(vis_stderr, "   \t\t\t2: BDD size\n");
626  (void) fprintf(vis_stderr, "   -R n\t\tSet reordering (0-3)\n");
627  (void) fprintf(vis_stderr, "   \t\t\t0 or n: no reordering (default)\n");
628  (void) fprintf(vis_stderr, "   \t\t\t1 or b: reordering in only BDD\n");
629  (void) fprintf(vis_stderr, "   \t\t\t2 or z: reordering on only ZDD\n");
630  (void) fprintf(vis_stderr, "   \t\t\t3 or a: reordering on both\n");
631  (void) fprintf(vis_stderr, "   -T \t\tTry to share mode nodes.\n");
632  return 1;    /* error exit */
633}
634
635/**Function********************************************************************
636
637  Synopsis    [Handler for timeout.]
638
639  Description [This function is called when a time out occurs.]
640
641  SideEffects []
642
643  SeeAlso []
644
645******************************************************************************/
646static void
647TimeOutHandle(void)
648{
649  longjmp(timeOutEnv, 1);
650}
651
652
653/**Function********************************************************************
654
655  Synopsis    [Checks whether the network has multiple valued signals.]
656
657  Description [Checks whether the network has multiple valued
658  signals. Returns 1 if true, else 0.]
659
660  SideEffects [None]
661
662  SeeAlso []
663
664******************************************************************************/
665static int
666TestIsNetworkMultipleValued(Ntk_Network_t *network)
667{
668  Ntk_Node_t *node;
669  lsGen gen;
670  Var_Variable_t *var;
671  int numValues;
672
673  Ntk_NetworkForEachNode(network,gen,node) {
674    var = Ntk_NodeReadVariable(node);
675    numValues = Var_VariableReadNumValues(var);
676    if (numValues > 2) {
677      lsFinish(gen);
678      return 1;
679    }
680  }
681  return 0;
682}
Note: See TracBrowser for help on using the repository browser.