source: vis_dev/vis-2.3/src/part/partPart.c @ 43

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

vis2.3

File size: 49.0 KB
RevLine 
[14]1/**CFile************************************************************************
2
3  FileName    [partPart.c]
4
5  PackageName [part]
6
7  Synopsis [Routines to initialize the command <em>build_partition_mdds</em>,
8  create and delete internal data structures of the partition, and print
9  information about the partition.]
10
11  Author      [Abelardo Pardo]
12
13  Copyright   [This file was created at the University of Colorado at
14  Boulder.  The University of Colorado at Boulder makes no warranty
15  about the suitability of this software for any purpose.  It is
16  presented on an AS IS basis.]
17
18******************************************************************************/
19
20#include "partInt.h"
21
22static char rcsid[] UNUSED = "$Id: partPart.c,v 1.45 2009/04/11 01:47:18 fabio Exp $";
23
24/**AutomaticStart*************************************************************/
25
26/*---------------------------------------------------------------------------*/
27/* Static function prototypes                                                */
28/*---------------------------------------------------------------------------*/
29
30static void PrintVertexDescription(FILE *fp, vertex_t *vertexPtr, int order);
31
32/**AutomaticEnd***************************************************************/
33
34/*---------------------------------------------------------------------------*/
35/* Definition of exported functions                                          */
36/*---------------------------------------------------------------------------*/
37
38/**Function********************************************************************
39
40  Synopsis [Deletes the graph created for the partition and all the information
41  attached to it.]
42
43  SideEffects []
44
45  SeeAlso     [PartPartitionInfoFree PartVertexInfoFree]
46
47******************************************************************************/
48void
49Part_PartitionFree(
50   graph_t *partition)
51{
52  /* Delete the graph information */
53  g_free(partition, PartPartitionInfoFree, PartVertexInfoFree,
54         (void (*)(gGeneric))0);
55} /* End of Part_PartitionFree */
56
57
58/**Function********************************************************************
59
60  Synopsis    [Call-back function to free a partition.]
61
62  Description [This function will be stored in the network together with the
63  pointer to the structure. Whenever the network deletes the partitioning
64  information, this function is called and it will deallocate the partition and
65  the information attached to it.]
66
67  SideEffects []
68
69  SeeAlso     [Ntk_NetworkAddApplInfo]
70
71******************************************************************************/
72void
73Part_PartitionFreeCallback(
74   void *data)
75{
76  Part_PartitionFree((graph_t *) data);
77} /* End of Part_PartitionFreeCallback */
78
79/**Function********************************************************************
80
81  Synopsis    [Finds a vertex in the graph with a certain name.]
82
83  Description [Given a name, it returns a pointer to a vertex structure if
84  there is a vertex with that name in the partition. Otherwise it returns a
85  NULL pointer.]
86
87  SideEffects []
88
89  SeeAlso     [PartPartitionInfo]
90
91******************************************************************************/
92vertex_t *
93Part_PartitionFindVertexByName(
94  graph_t *partition,
95  char *name)
96{
97  vertex_t *result = NIL(vertex_t);
98  st_table *table = PartPartitionReadNameToVertex(partition);
99
100  if (table != NIL(st_table)) {
101    st_lookup(table, name, &result);
102  } /* End of if */
103
104  return result;
105} /* End of Part_PartitionFindVertexByName */
106
107/**Function********************************************************************
108
109  Synopsis    [Finds a vertex in the graph with a certain MddId.]
110
111  Description [Given a MddId, it returns a pointer to a vertex structure if
112  there is a vertex with that mddId in the partition. Otherwise it returns a
113  NULL pointer.]
114
115  SideEffects []
116
117  SeeAlso     [PartVertexInfo]
118
119******************************************************************************/
120vertex_t *
121Part_PartitionFindVertexByMddId(
122  graph_t *partition,
123  int mddId)
124{
125  vertex_t *result = NIL(vertex_t);
126  st_table *table = PartPartitionReadMddIdToVertex(partition);
127
128  if (table != NIL(st_table)) {
129    st_lookup(table, (char *)(long)mddId, &result);
130  } /* End of if */
131
132  return result;
133} /* End of Part_PartitionFindVertexByMddId */
134
135/**Function********************************************************************
136
137  Synopsis [Returns the name of the entity from which the partition
138  was created.]
139
140  SideEffects []
141
142  SeeAlso     [PartPartitionInfo]
143
144******************************************************************************/
145char *
146Part_PartitionReadName(
147   graph_t *partition)
148{
149  return PartPartitionReadName(partition);
150} /* End of Part_PartitionReadName */
151
152/**Function********************************************************************
153
154  Synopsis [Returns the method which was used to create the partition graph.]
155
156  SideEffects []
157
158  SeeAlso     [PartPartitionInfo]
159
160******************************************************************************/
161Part_PartitionMethod
162Part_PartitionReadMethod(
163  graph_t *partition)
164{
165  Part_PartitionMethod  method;
166
167  method = PartPartitionReadMethod(partition);
168  if (method == Part_Default_c)
169    method = Part_Frontier_c;
170  return(method);
171} /* End of Part_PartitionReadMethod */
172
173/**Function********************************************************************
174
175  Synopsis    [Returns the partition method as a string.]
176
177  Description [Returns the method stored in the partition as a new
178  string. The caller of the function has the responsibility of freeing
179  the string. The possible values of the string are: "Inputs-Outputs",
180  "Total", "Partial" or "Frontier".]
181
182  SideEffects []
183
184  SeeAlso     [Part_PartitionPrintStats]
185
186******************************************************************************/
187char *
188Part_PartitionObtainMethodAsString(
189  graph_t *partition)
190{
191  char *resultString;
192
193  assert(partition != NIL(graph_t));
194
195  switch(PartPartitionReadMethod(partition)) {
196    case Part_Total_c:
197      resultString = util_strsav("Total");
198      break;
199    case Part_Partial_c:
200      resultString = util_strsav("Partial");
201      break;
202    case Part_InOut_c:
203      resultString = util_strsav("Inputs-Outputs");
204      break;
205    case Part_Frontier_c:
206    case Part_Default_c:
207      resultString = util_strsav("Frontier");
208      break;
209    case Part_Boundary_c:
210      resultString = util_strsav("Boundary");
211      break;
212    case Part_Fine_c:
213      resultString = util_strsav("Fine");
214      break;
215    default:
216      fail("Unexpected Partition method.");
217  }
218
219  return resultString;
220} /* End of Part_PartitionObtainMethodAsString */
221
222/**Function********************************************************************
223
224  Synopsis    [Function to read the manager attached to the partition.]
225
226  SideEffects []
227
228  SeeAlso     [PartPartitionInfo]
229
230******************************************************************************/
231mdd_manager *
232Part_PartitionReadMddManager(
233  graph_t *partition)
234{
235  return PartPartitionReadMddManager(partition);
236} /* End of Part_PartitionReadMddManager */
237
238/**Function********************************************************************
239
240  Synopsis    [Returns the type of a vertex.]
241
242  SideEffects []
243
244  SeeAlso     [PartVertexInfo Part_VertexType]
245
246******************************************************************************/
247Part_VertexType
248Part_VertexReadType(
249  vertex_t *vertexPtr)
250{
251  return PartVertexReadType(vertexPtr);
252} /* End of Part_VertexReadType */
253
254/**Function********************************************************************
255
256  Synopsis    [Reads the name attached to a vertex.]
257
258  SideEffects []
259
260  SeeAlso     [PartVertexInfo]
261
262******************************************************************************/
263char *
264Part_VertexReadName(
265  vertex_t *vertexPtr)
266{
267  return PartVertexReadName(vertexPtr);
268} /* End of Part_VertexReadName */
269
270/**Function********************************************************************
271
272  Synopsis    [Reads the clusterMembers field  of a vertex.]
273
274  Description [This function does not make sure that the vertex is of clustered
275  type. It is the responsibility of the caller to guarantee that.]
276
277  SideEffects []
278
279  SeeAlso     [PartVertexInfo]
280
281******************************************************************************/
282array_t *
283Part_VertexReadClusterMembers(
284  vertex_t *vertexPtr)
285{
286  return PartVertexReadClusterMembers(vertexPtr);
287} /* End of Part_VertexReadClusterMembers */
288
289/**Function********************************************************************
290
291  Synopsis    [Reads the multi-valued function attached to a vertex.]
292
293  Description [This function does not make sure that the vertex is of single
294  type.  It is the responsibility of the caller to guarantee that.]
295
296  SideEffects []
297
298  SeeAlso     [PartVertexInfo]
299
300******************************************************************************/
301Mvf_Function_t *
302Part_VertexReadFunction(
303  vertex_t *vertexPtr)
304{
305    return PartVertexReadFunction(vertexPtr);
306} /* End of Part_VertexReadFunction */
307
308
309/**Function********************************************************************
310
311  Synopsis    [Sets the multi-valued function of a vertex.]
312
313  SideEffects []
314
315  SeeAlso     [PartVertexInfo]
316
317******************************************************************************/
318void
319Part_VertexSetFunction(
320  vertex_t *vertexPtr,
321  Mvf_Function_t *mvf)
322{
323  assert(PartVertexReadType(vertexPtr) != Part_VertexCluster_c);
324
325  PartVertexSetFunction(vertexPtr, mvf);
326} /* End of Part_VertexSetFunction */
327
328
329/**Function********************************************************************
330
331  Synopsis    [Reads the MddId attached to a vertex.]
332
333  SideEffects []
334
335  SeeAlso     [PartVertexInfo]
336
337******************************************************************************/
338int
339Part_VertexReadMddId(
340  vertex_t *vertexPtr)
341{
342    return PartVertexReadMddId(vertexPtr);
343} /* End of Part_VertexReadMddId */
344
345/**Function********************************************************************
346
347  Synopsis    [Test of a vertex is member of a cluster.]
348
349  SideEffects []
350
351  SeeAlso     [PartVertexInfo Part_VertexReadType]
352
353******************************************************************************/
354boolean
355Part_VertexTestIsClustered(
356  vertex_t *vertexPtr)
357{
358  return PartVertexTestIsClustered(vertexPtr);
359} /* End of Part_VertexTestIsClustered */
360
361/**Function********************************************************************
362
363  Synopsis    [Executes the selected partitioning method.]
364
365  Description [Given a network, and a method, the function creates a partition
366  by using the specified method. This function may be called from any point in
367  the code to create a partition.  In particular, the command partition uses
368  this function to create the partition and store it in the network.<p>
369
370  The function receives two lists of pointers to network nodes, the roots and
371  the leaves. The function will create the partition of the subnetwork between
372  the root and the leave nodes. As a special case, if both lists are passed NIL
373  values, the root and leave lists default to combinational outputs and
374  combinational inputs respectively.
375
376  The parameter <tt>careSet</tt> specifies which minterms in the input space are
377  considered.
378
379  The <tt>nodes</tt> parameter is an optional list of nodes that may be
380  specified in case the <tt>partial</tt> method is used. It represents the set
381  of nodes in the network to be preserved when building the partition. The
382  boolean variable <tt>inTermsOfLeaves</tt> is valid only in the case of
383  the <tt>total</tt> method and provides the option of creating the functions
384  attached to the vertices in terms of the combinational inputs or in terms of
385  their immediate fanin.  Two additional parameters are provided to control the
386  verbosity and the intensity of the sanity check applied to the computation.<p>
387
388  This function is called by the command build_partition_mdds which has a
389  time-out option.  In the event of the execution time going over the time out,
390  the control is returned to the prompt and all the memory allocated by the
391  internal procedures is leaked.]
392
393  SideEffects []
394
395  SeeAlso     [part.h]
396
397******************************************************************************/
398graph_t *
399Part_NetworkCreatePartition(
400  Ntk_Network_t *network,
401  Hrc_Node_t *hnode,
402  char *name,
403  lsList rootList,
404  lsList leaveList,
405  mdd_t *careSet,
406  Part_PartitionMethod method,
407  lsList nodes,
408  boolean inTermsOfLeaves,
409  int verbose,
410  int sanityCheck)
411{
412  graph_t    *partition;
413  long       lap = 0;
414
415  if (verbose) {
416    lap = util_cpu_time();
417  } /* End of if */
418
419  /* Create the new graph to represent the partition */
420  partition = g_alloc();
421  partition->user_data =
422    (gGeneric)PartPartitionInfoCreate(name,
423                                      Ntk_NetworkReadMddManager(network),
424                                      method);
425
426  switch (method) {
427    case Part_Partial_c:
428      if (verbose) {
429        (void) fprintf(vis_stdout, "Partitioning the system by the Partial");
430        (void) fprintf(vis_stdout, " method\n");
431      } /* End of if */
432      PartPartitionPartial(network, partition, rootList, leaveList, careSet,
433                           nodes, inTermsOfLeaves);
434      break;
435    case Part_Boundary_c:
436      if (verbose) {
437        (void) fprintf(vis_stdout, "Partitioning the system by the Boundary");
438        (void) fprintf(vis_stdout, " method\n");
439      } /* End of if */
440      PartPartitionBoundary(network, hnode, partition, rootList, leaveList, careSet,
441                           inTermsOfLeaves);
442      break;
443    case Part_Total_c:
444      if (verbose) {
445        (void) fprintf(vis_stdout, "Partitioning the circuit by the Total");
446        (void) fprintf(vis_stdout, " method\n");
447      } /* End of if */
448      PartPartitionTotal(network, partition, rootList, leaveList, careSet,
449                         inTermsOfLeaves);
450      break;
451    case Part_Frontier_c:
452    case Part_Default_c:
453      if (verbose) {
454        (void) fprintf(vis_stdout, "Partitioning the circuit by the Frontier");
455        (void) fprintf(vis_stdout, " method\n");
456      } /* End of if */
457      PartPartitionFrontier(network, partition, rootList, leaveList, careSet);
458      break;
459    case Part_Fine_c:
460      if (verbose) {
461        (void) fprintf(vis_stdout, "Partitioning the circuit for the fine-grain");
462        (void) fprintf(vis_stdout, " method\n");
463      } /* End of if */
464      PartPartitionFineGrain(network, partition, careSet);
465      break;
466    case Part_InOut_c:
467      if (verbose) {
468        (void) fprintf(vis_stdout, "Partitioning the circuit by the");
469        (void) fprintf(vis_stdout, " Input-Output method\n");
470      } /* End of if */
471      PartPartitionInputsOutputs(network, partition, rootList,
472                                 leaveList, careSet);
473      break;
474    default:
475      (void) fprintf(vis_stdout, "Partition method not implemented yet\n");
476      break;
477  }
478
479  if (sanityCheck >0) {
480    PartPartitionSanityCheck(partition, sanityCheck);
481  }
482
483  if (verbose) {
484    (void) fprintf(vis_stdout, "%.2f (secs) spent in partitioning.\n",
485                   (util_cpu_time() - lap)/1000.0);
486  } /* End of if */
487
488  return partition;
489} /* End of Part_NetworkCreatePartition */
490
491/**Function********************************************************************
492
493  Synopsis    [Creates a duplicate of a partition.]
494
495  SideEffects []
496
497  SeeAlso     [PartVertexInfo, PartPartitionInfo]
498
499******************************************************************************/
500graph_t *
501Part_PartitionDuplicate(
502  graph_t *partition)
503{
504  graph_t          *result;
505  lsGen            gen;
506  vertex_t         *fromVertex;
507  vertex_t         *toVertex;
508  edge_t           *edgePtr;
509
510  result = g_alloc();
511  result->user_data =
512    (gGeneric)PartPartitionInfoCreate(PartPartitionReadName(partition),
513                                      PartPartitionReadMddManager(partition),
514                                      PartPartitionReadMethod(partition));
515  foreach_vertex(partition, gen, fromVertex) {
516    char *name;
517    int  mddId;
518
519    name = PartVertexReadName(fromVertex);
520    mddId = PartVertexReadMddId(fromVertex);
521    toVertex = g_add_vertex(result);
522
523    st_insert(PartPartitionReadNameToVertex(result), name, (char *)toVertex);
524
525    if (mddId != NTK_UNASSIGNED_MDD_ID) {
526      st_insert(PartPartitionReadMddIdToVertex(result), (char *)(long)mddId,
527                (char *)toVertex);
528    } /* End of if */
529
530    if (PartVertexReadType(fromVertex) == Part_VertexSingle_c) {
531      Mvf_Function_t *mdd;
532
533      mdd = Mvf_FunctionDuplicate(PartVertexReadFunction(fromVertex));
534      toVertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, mdd,
535                                                                 mddId);
536    }
537    if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
538      toVertex->user_data =
539        (gGeneric)PartVertexInfoCreateCluster(name, Part_VertexReadClusterMembers(fromVertex));
540    }
541  }
542
543  foreach_edge(partition, gen, edgePtr) {
544    vertex_t *fromVertexCopy;
545    vertex_t *toVertexCopy;
546
547    fromVertex = g_e_source(edgePtr);
548    toVertex = g_e_dest(edgePtr);
549
550    st_lookup(PartPartitionReadNameToVertex(result),
551              PartVertexReadName(fromVertex), &fromVertexCopy);
552    st_lookup(PartPartitionReadNameToVertex(result),
553              PartVertexReadName(toVertex), &toVertexCopy);
554
555    g_add_edge(fromVertexCopy, toVertexCopy);
556  }
557
558  return result;
559} /* End of Part_PartitionDuplicate */
560
561
562/**Function********************************************************************
563
564  Synopsis    [Create reduced partition according to given CTL formulae]
565
566  Comments    [Combinational root and leave nodes are combinational support
567  nodes of given CTL properties.]
568
569  SideEffects []
570
571  SeeAlso     []
572
573******************************************************************************/
574graph_t *
575Part_PartCreatePartitionWithCTL(
576  Hrc_Manager_t **hmgr,
577  Part_PartitionMethod method,
578  int verbose,
579  int sanityCheck,
580  boolean inTermsOfLeaves,
581  array_t *ctlArray,
582  array_t *fairArray)
583{
584  return Part_PartCreatePartitionWithCtlAndLtl(hmgr, method, verbose,
585                                               sanityCheck, inTermsOfLeaves,
586                                               ctlArray, NIL(array_t),
587                                               fairArray);
588}
589
590/**Function********************************************************************
591
592  Synopsis    [Create reduced partition according to given CTL formulae]
593
594  Comments    [Combinational root and leave nodes are combinational support
595  nodes of given CTL properties.]
596
597  SideEffects []
598
599  SeeAlso     []
600
601******************************************************************************/
602graph_t *
603Part_PartCreatePartitionWithCtlAndLtl(
604  Hrc_Manager_t **hmgr,
605  Part_PartitionMethod method,
606  int verbose,
607  int sanityCheck,
608  boolean inTermsOfLeaves,
609  array_t *ctlArray,
610  array_t *ltlArray,
611  array_t *fairArray)
612{
613  char          *modelName;
614  Hrc_Node_t    *currentNode;
615  graph_t       *partition;
616  lsList        latchInputList;
617  lsGen         gen;
618  Ntk_Node_t    *node;
619  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
620
621  latchInputList = lsCreate();
622  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
623  modelName = Hrc_NodeReadModelName(currentNode);
624
625  if (method != Part_InOut_c){
626    return NIL(graph_t);
627  }
628
629  PartGetLatchInputListFromCtlAndLtl(network, ctlArray, ltlArray, fairArray,
630                                     latchInputList, FALSE);
631
632  Ntk_NetworkForEachCombOutput(network, gen, node){
633    if (Ntk_NodeTestIsLatchInitialInput(node)){
634      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
635    }
636  }
637
638  /*
639   * Execute the partition algorithm. If rootList and leaveList are null,
640   * graph includes all network nodes
641   */
642  partition = Part_NetworkCreatePartition(network, currentNode, modelName,
643                 latchInputList, (lsList)0, NIL(mdd_t), method, (lsList)0,
644                 inTermsOfLeaves, verbose, sanityCheck);
645
646  lsDestroy(latchInputList, (void (*)(lsGeneric))0);
647  return partition;
648}
649
650
651/**Function********************************************************************
652
653  Synopsis    [Change partition to include new vertex in root list]
654
655  Comments    [Current partition in increased to include all next state
656  functions for all members in rootList.]
657
658  SideEffects []
659
660  SeeAlso     []
661
662******************************************************************************/
663int
664Part_PartitionChangeRoots(
665  Ntk_Network_t *network,
666  graph_t *partition,
667  lsList  rootList,
668  int verbosity)
669{
670  if (Part_PartitionReadMethod(partition) != Part_InOut_c){
671    return 0;
672  }
673
674  return
675   PartPartitionInOutChangeRoots(network, partition, rootList, verbosity);
676}
677
678
679/**Function********************************************************************
680
681  Synopsis    [Reads the partition attached to a network.]
682
683  SideEffects []
684
685  SeeAlso     [CommandBuildPartitionMdds]
686
687******************************************************************************/
688graph_t *
689Part_NetworkReadPartition(
690  Ntk_Network_t *network)
691{
692  return (graph_t *)Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY);
693} /* End of Part_NetworkReadPartition */
694
695
696/**Function********************************************************************
697
698  Synopsis    [Adds a vertex to the partition representing a set of vertices.]
699
700  SideEffects []
701
702  SeeAlso     [PartVertexInfo]
703
704******************************************************************************/
705vertex_t *
706Part_PartitionCreateClusterVertex(
707  graph_t *partition,
708  char *name,
709  array_t *arrayOfVertices)
710{
711  vertex_t *newVertex;
712
713  newVertex = g_add_vertex(partition);
714  newVertex->user_data = (gGeneric)PartVertexInfoCreateCluster(name,
715                                                               arrayOfVertices);
716
717  return(newVertex);
718
719} /* End of Part_PartitionCreateClusterVertex */
720
721/**Function********************************************************************
722
723  Synopsis    [ Partition by adding vertices for the nodes in rootList
724  and leaveList.  A node in leaveList may already have a corresponding
725  vertex in the partition graph -- Only creating the new vertex if not exists.
726  Nodes in rootList should NOT have existing vertices in the partition graph.
727  (The caller should guarantee this)
728
729  This routine is for the use in the 'ltl' package. We assume the partition
730  method is Part_Frontier_c.]
731
732  SideEffects [partition might be changed.]
733
734  SeeAlso     [PartPartitionFrontier]
735
736******************************************************************************/
737void
738Part_UpdatePartitionFrontier(
739  Ntk_Network_t *network,
740  graph_t *partition,
741  lsList  rootList,
742  lsList  leaveList,
743  mdd_t   *careSet)
744{
745  PartUpdateFrontier(network, partition, rootList, leaveList, careSet);
746}
747
748/**Function********************************************************************
749
750  Synopsis    [Removes a cluster vertex from the partition.]
751
752  SideEffects []
753
754  SeeAlso     [PartVertexInfo]
755
756******************************************************************************/
757void
758Part_VertexInfoFreeCluster(
759  vertex_t *vertexPtr)
760{
761  if (PartVertexReadType(vertexPtr) == Part_VertexCluster_c) {
762    g_delete_vertex(vertexPtr, PartVertexInfoFree, (void (*)(gGeneric))0);
763  } /* End of then */
764  else {
765    (void) fprintf(vis_stderr, "Warning -- Inconsistent vertex deletion in");
766    (void) fprintf(vis_stderr, " partition package\n");
767  }
768} /* End of Part_VertexInfoFreeCluster */
769
770/**Function********************************************************************
771
772  Synopsis [Test if the functions attached to a set of vertices in the
773  partition are completely specified.]
774
775  Description [Given a set of vertices (roots) build their functions in terms
776  of a second set of vertices (leaves) and test if the functions are
777  completely specified.]
778
779  SideEffects []
780
781  SeeAlso     [Part_PartitionTestDeterministic]
782
783******************************************************************************/
784boolean
785Part_PartitionTestCompletelySp(
786  graph_t *partition,
787  array_t *roots,
788  st_table *leaves)
789{
790  array_t *mvfFunctions;
791  vertex_t *vertexPtr;
792  Mvf_Function_t *functionPtr;
793  boolean result = TRUE;
794  int i;
795  char *vertexName;
796
797  mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
798
799  arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
800    vertexPtr = array_fetch(vertex_t *, roots, i);
801    vertexName = PartVertexReadName(vertexPtr);
802    if (!Mvf_FunctionTestIsCompletelySpecified(functionPtr)) {
803      error_append("Vertex ");
804      error_append(vertexName);
805      error_append(" is not completely specified\n");
806      result = FALSE;
807    } /* End of if */
808
809    /* We don't need the Mvf_Function any more, so we delete it */
810    Mvf_FunctionFree(functionPtr);
811  }
812
813  /* Clean up*/
814  array_free(mvfFunctions);
815
816  return result;
817} /* End of Part_PartitionTestCompletelySp */
818
819/**Function********************************************************************
820
821  Synopsis    [Test if the functions attached to a set of vertices in the
822  partition are deterministic.]
823
824  Description [Given a set of vertices (roots) build their functions in terms
825  of a second set of vertices (leaves) and test if the functions are
826  deterministic.]
827
828  SideEffects []
829
830  SeeAlso     [Part_PartitionTestCompletelySp]
831
832******************************************************************************/
833boolean
834Part_PartitionTestDeterministic(
835  graph_t *partition,
836  array_t *roots,
837  st_table *leaves)
838{
839  array_t *mvfFunctions;
840  vertex_t *vertexPtr;
841  Mvf_Function_t *functionPtr;
842  boolean result = TRUE;
843  int i;
844  char *vertexName;
845
846  mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
847
848  arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
849    vertexPtr = array_fetch(vertex_t *, roots, i);
850    vertexName = PartVertexReadName(vertexPtr);
851    if (!Mvf_FunctionTestIsDeterministic(functionPtr)) {
852      error_append("Vertex ");
853      error_append(vertexName);
854      error_append(" is non-deterministic\n");
855      result = FALSE;
856    } /* End of if */
857
858    /* We don't need the Mvf_Function any more, so we delete it */
859    Mvf_FunctionFree(functionPtr);
860  }
861
862  /* Clean up*/
863  array_free(mvfFunctions);
864
865  return result;
866} /* End of Part_PartitionTestDeterministic */
867
868/**Function********************************************************************
869
870  Synopsis    [Create latch input nodes list from CTL properties and fairness
871  constraints]
872
873  Comments    []
874
875  SideEffects [latchInputList is changed]
876
877  SeeAlso     []
878
879******************************************************************************/
880int
881Part_PartitionGetLatchInputListFromCTL(
882  Ntk_Network_t *network,
883  array_t *ctlArray,
884  array_t *fairArray,
885  lsList  latchInputList)
886{
887  return PartGetLatchInputListFromCTL( network, ctlArray, fairArray,
888                                       latchInputList);
889}
890
891/**Function********************************************************************
892
893  Synopsis    [Create latch input nodes list from CTL properties and fairness
894  constraints]
895
896  Comments    []
897
898  SideEffects [latchInputList is changed]
899
900  SeeAlso     []
901
902******************************************************************************/
903int
904Part_PartitionGetLatchInputListFromCtlAndLtl(
905  Ntk_Network_t *network,
906  array_t *ctlArray,
907  array_t *ltlArray,
908  array_t *fairArray,
909  lsList  latchInputList,
910  boolean stopAtLatch)
911{
912  return PartGetLatchInputListFromCtlAndLtl( network, ctlArray, ltlArray,
913                                             fairArray,
914                                             latchInputList, stopAtLatch);
915}
916
917/**Function********************************************************************
918
919  Synopsis    [Prints statistics about the partition DAG.]
920
921  Comments    [If the parameter printNodeNames is true, the function prints
922  names of the network nodes represented by vertices in the partition graph.]
923
924  SideEffects []
925
926  SeeAlso     [PartPartitionInfo]
927
928******************************************************************************/
929void
930Part_PartitionPrintStats(
931  FILE *fp,
932  graph_t *partition,
933  boolean printNodeNames)
934{
935  lsList vertexList = g_get_vertices(partition);
936  vertex_t *vertexPtr;
937  array_t *functions;
938  Mvf_Function_t* vertexFunction;
939  mdd_t *mddPtr;
940  lsGen gen;
941  char *methodName;
942  int numVertices = lsLength(vertexList);
943  int numSources;
944  int numSinks;
945  int i;
946
947  /* Obtain the method name as a string */
948  methodName = Part_PartitionObtainMethodAsString(partition);
949
950  /*
951   * Count the number of sources and sinks and at the same time store all the
952   * bdd_t of every vertex in a common array to compute the shared size.
953   */
954  numSources = 0;
955  numSinks = 0;
956  functions = array_alloc(mdd_t *, 0);
957  if (printNodeNames) {
958    (void) fprintf(fp, "Network nodes represented as vertices in the ");
959    (void) fprintf(fp, "partition:\n");
960  }
961  foreach_vertex(partition, gen, vertexPtr) {
962    if (lsLength(g_get_in_edges(vertexPtr)) == 0) {
963      numSources++;
964    } /* End of if */
965    if (lsLength(g_get_out_edges(vertexPtr)) == 0) {
966      numSinks++;
967    } /* End of if */
968    if (PartVertexReadType(vertexPtr) == Part_VertexSingle_c) {
969      if (printNodeNames) {
970        if (PartVertexReadName(vertexPtr) != NIL(char)) {
971          (void) fprintf(fp, "%s\n", PartVertexReadName(vertexPtr));
972        }
973      }
974      vertexFunction = PartVertexReadFunction(vertexPtr);
975      if (vertexFunction != NIL(Mvf_Function_t)) {
976        Mvf_FunctionForEachComponent(vertexFunction, i, mddPtr) {
977          array_insert_last(mdd_t *, functions, mddPtr);
978        }
979      } /* End of if */
980    } /* End of if */
981  } /* foreach_vertex*/
982
983  /* Print results */
984  (void)fprintf(fp, "Method %s, %d sinks, %d sources,", methodName, numSinks, numSources);
985  (void)fprintf(fp, " %d total vertices,", numVertices);
986  (void)fprintf(fp, " %ld mdd nodes\n", bdd_size_multiple(functions));
987
988  /* Clean up */
989  FREE(methodName);
990  array_free(functions);
991
992  return;
993} /* End of Part_PartitionPrintStats */
994
995/*---------------------------------------------------------------------------*/
996/* Definition of internal functions                                          */
997/*---------------------------------------------------------------------------*/
998
999/**Function********************************************************************
1000
1001  Synopsis [Initializes the information attached to the graph of the
1002  partition.]
1003
1004  Description [Allocates the memory needed for the information attached to the
1005  graph structure.]
1006
1007  SideEffects []
1008
1009  SeeAlso     [PartPartitionInfo PartPartitionInfoFree]
1010
1011******************************************************************************/
1012PartPartitionInfo_t *
1013PartPartitionInfoCreate(
1014  char *name,
1015  mdd_manager *manager,
1016  Part_PartitionMethod method)
1017{
1018  PartPartitionInfo_t *recordPartition = ALLOC(PartPartitionInfo_t, 1);
1019
1020  recordPartition->name          = util_strsav(name);
1021  recordPartition->method        = method;
1022  recordPartition->mddManager    = manager;
1023  recordPartition->nameToVertex  = st_init_table(strcmp,st_strhash);
1024  recordPartition->mddIdToVertex = st_init_table(st_numcmp, st_numhash);
1025
1026  return recordPartition;
1027} /* End of PartPartitionInfoCreate */
1028
1029/**Function********************************************************************
1030
1031  Synopsis [Deallocates the user information in the graph.]
1032
1033  Description [Deallocates the user information in the graph. Does not free the
1034  MDD manager associated with the partition.]
1035
1036  SideEffects []
1037
1038  SeeAlso     [PartPartitionInfoCreate]
1039
1040******************************************************************************/
1041void
1042PartPartitionInfoFree(
1043  gGeneric partitionInfo)
1044{
1045  if (((PartPartitionInfo_t *)partitionInfo)->name != NIL(char)) {
1046    FREE(((PartPartitionInfo_t *)partitionInfo)->name);
1047  }
1048
1049  st_free_table(((PartPartitionInfo_t *)partitionInfo)->nameToVertex);
1050  st_free_table(((PartPartitionInfo_t *)partitionInfo)->mddIdToVertex);
1051
1052  FREE(partitionInfo);
1053} /* End of PartPartitionInfoFree */
1054
1055/**Function********************************************************************
1056
1057  Synopsis [Initializes the information attached to a single vertex.]
1058
1059  SideEffects []
1060
1061  SeeAlso     [PartVertexInfo]
1062
1063******************************************************************************/
1064PartVertexInfo_t *
1065PartVertexInfoCreateSingle(
1066  char *name,
1067  Mvf_Function_t *mvf,
1068  int mddId)
1069{
1070  PartVertexInfo_t *result;
1071
1072  result                    = ALLOC(PartVertexInfo_t, 1);
1073  result->type              = Part_VertexSingle_c;
1074  result->name              = util_strsav(name);
1075  result->functionality.mvf = mvf;
1076  result->mddId             = mddId;
1077  result->isClustered       = 0;
1078
1079  return result;
1080} /* End of PartVertexInfoCreateSingle */
1081
1082/**Function********************************************************************
1083
1084  Synopsis    [Creates a cluster vertex in the partition.]
1085
1086  SideEffects []
1087
1088  SeeAlso     [PartVertexInfo]
1089
1090******************************************************************************/
1091PartVertexInfo_t *
1092PartVertexInfoCreateCluster(
1093  char *name,
1094  array_t *vertexArray)
1095{
1096  PartVertexInfo_t *result;
1097  vertex_t *auxPtr;
1098  int i;
1099
1100  /* Make sure all the nodes are simple nodes */
1101  for(i = 0; i < array_n(vertexArray); i++) {
1102    auxPtr = array_fetch(vertex_t *, vertexArray, i);
1103    if (PartVertexReadType(auxPtr) == Part_VertexCluster_c) {
1104      fail("Only one level of hierarchy allowed in the partition");
1105    } /* End of if */
1106    if (PartVertexTestIsClustered(auxPtr)) {
1107      fail("Partition: Clustering vertex already member of another cluster");
1108    } /* End of then */
1109    else {
1110      PartVertexSetIsClustered(auxPtr, 1);
1111    }
1112  } /* End of for */
1113
1114  result                               = ALLOC(PartVertexInfo_t, 1);
1115  result->type                         = Part_VertexCluster_c;
1116  result->name                         = util_strsav(name);
1117  result->functionality.clusterMembers = array_dup(vertexArray);
1118
1119  result->mddId                        = NTK_UNASSIGNED_MDD_ID;
1120  result->isClustered                  = 0;
1121
1122  return result;
1123} /* End of PartVertexInfoCreateCluster */
1124
1125/**Function********************************************************************
1126
1127  Synopsis [Deallocates the user information attached to a vertex.]
1128
1129  SideEffects []
1130
1131  SeeAlso     [PartVertexInfo]
1132
1133******************************************************************************/
1134void
1135PartVertexInfoFree(
1136  gGeneric vertexInfo
1137   )
1138{
1139  if (((PartVertexInfo_t *)vertexInfo)->type == Part_VertexSingle_c) {
1140    /* Free the function attached to the node if any */
1141    if (((PartVertexInfo_t *)vertexInfo)->functionality.mvf !=
1142        NIL(Mvf_Function_t)) {
1143      Mvf_FunctionFree(((PartVertexInfo_t *)vertexInfo)->functionality.mvf);
1144    } /* End of if */
1145  } /* End of then */
1146  else {
1147    if (((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers !=
1148        NIL(array_t)) {
1149      array_free(((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers);
1150    } /* End of if */
1151  } /* End of if-then-else */
1152
1153  if (((PartVertexInfo_t *)vertexInfo)->name != NIL(char)) {
1154    FREE(((PartVertexInfo_t *)vertexInfo)->name);
1155  }
1156
1157  FREE(vertexInfo);
1158} /* End of PartVertexInfoFree */
1159
1160/**Function********************************************************************
1161
1162  Synopsis [Verifies that the information in the nameToVertex table of
1163  a graph is consistent.]
1164
1165  SideEffects []
1166
1167  SeeAlso     [PartPartitionInfo]
1168
1169******************************************************************************/
1170void
1171PartPartitionSanityCheck(
1172  graph_t *partition,
1173  int intensity)
1174{
1175  st_table *table;
1176  lsList vertexList = g_get_vertices(partition);
1177  lsGen lgen;
1178  vertex_t *vertex, *rvertex;
1179
1180  /* Consistency in the nameToVertex table */
1181  table = PartPartitionReadNameToVertex(partition);
1182
1183  /*
1184   * The number of elements in the nameToVertex table and the number
1185   * of vertices agrees
1186   */
1187  if (lsLength(g_get_vertices(partition)) != st_count(table)) {
1188    (void) fprintf(vis_stderr, "Warning -- NameToVertex table incomplete in ");
1189    (void) fprintf(vis_stderr, " graph\n");
1190    if (intensity > 1) {
1191      (void) fprintf(vis_stderr, "  %d vertices in the graph and %d entries",
1192                     lsLength(g_get_vertices(partition)),
1193                     st_count(table));
1194      (void) fprintf(vis_stderr, " in the nameToVertex table\n");
1195    } /* End of if */
1196  } /* End of if */
1197
1198  lsForEachItem(vertexList, lgen, vertex) {
1199    char *name = PartVertexReadName(vertex);
1200    if (!st_lookup(table, name, &rvertex) ||
1201        strcmp(PartVertexReadName(vertex),PartVertexReadName(rvertex)) != 0) {
1202      (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in");
1203      (void) fprintf(vis_stderr, " the partition data-base\n");
1204    }
1205  }
1206
1207  /* Consistency in the mddIdToVertexTable */
1208  table = PartPartitionReadMddIdToVertex(partition);
1209  lsForEachItem(vertexList, lgen, vertex) {
1210    int mddId = PartVertexReadMddId(vertex);
1211    if((mddId != NTK_UNASSIGNED_MDD_ID) &&
1212       (!st_lookup(table, (char *)(long)mddId, &rvertex) ||
1213        PartVertexReadMddId(vertex) != PartVertexReadMddId(rvertex))) {
1214      (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
1215      (void) fprintf(vis_stderr, " partition data-base\n");
1216    }
1217  }
1218
1219  /*
1220   * Make sure that the mdd Id NTK_UNASSIGNED_MDD_ID does not appear in the
1221   * mddIdToVertex node.
1222   */
1223  table = PartPartitionReadMddIdToVertex(partition);
1224  if (st_is_member(table, (char *) NTK_UNASSIGNED_MDD_ID)) {
1225    (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
1226    (void) fprintf(vis_stderr, " partition data-base\n");
1227  } /* End of if */
1228
1229  /* Check the Mvfs in the vertices of the partition.*/
1230  if (intensity > 1) {
1231    lsForEachItem(vertexList, lgen, vertex) {
1232      Mvf_Function_t *function = PartVertexReadFunction(vertex);
1233      int i;
1234
1235      (void) fprintf(vis_stderr, "Vertex: %s, mddId: %d, Clustered: %c\n",
1236                     PartVertexReadName(vertex),
1237                     PartVertexReadMddId(vertex),
1238                     (PartVertexReadType(vertex) == Part_VertexCluster_c)?'t':'f');
1239      for(i = 0; i < Mvf_FunctionReadNumComponents(function); i ++) {
1240        mdd_t *unit = Mvf_FunctionObtainComponent(function, i);
1241        boolean x;
1242
1243        if (intensity > 2) {
1244          (void) fprintf(vis_stderr, "BDD_T: %lx, %lx\n",
1245                         (unsigned long) bdd_get_node(unit, &x),
1246                         (unsigned long) mdd_get_manager(unit));
1247        }
1248      } /* End of for */
1249    }
1250  } /* End of if */
1251
1252  /* ToDo: Check for redundant name in the list of vertices */
1253} /* End of PartPartitionSanityCheck */
1254
1255/**Function********************************************************************
1256
1257  Synopsis    [Computes the support of an array of mdds.]
1258
1259  Description [Computes the support of a multi-valued function. It is
1260  just the union of the supports of every component of the function.]
1261
1262  Comment [The reason why is it returned in a table is because it's very likely
1263  that questions such as, "is certain Id part of the support ?"  will happen.]
1264
1265  SideEffects []
1266
1267  SeeAlso     [PartVertexCreateFaninEdges]
1268
1269******************************************************************************/
1270st_table *
1271PartCreateFunctionSupportTable(
1272  Mvf_Function_t *mvf)
1273{
1274  mdd_manager  *mddManager;        /* Manager for the MDDs */
1275  array_t      *support;
1276  st_table     *mddSupport = st_init_table(st_numcmp, st_numhash);
1277  int          numComponents = Mvf_FunctionReadNumComponents(mvf);
1278  int          j, k;
1279  mdd_t        *unit;
1280
1281  assert(numComponents!= 0);
1282
1283  mddManager = Mvf_FunctionReadMddManager(mvf);
1284
1285  /*
1286   * compute the support of an mdd as the union of supports of every
1287   * function component
1288   */
1289  for(j = 0; j < numComponents; j++) {
1290    unit = Mvf_FunctionReadComponent(mvf, j);
1291    support = mdd_get_support(mddManager, unit);
1292
1293    /* For every element of its support */
1294    for(k = 0; k < array_n(support); k++) {
1295      st_insert(mddSupport, (char *)(long)array_fetch(int, support, k), (char *)0);
1296    } /* End of for */
1297    array_free(support);
1298  } /* End of for */
1299
1300  return mddSupport;
1301} /* End of PartCreateFunctionSupportTable */
1302
1303/**Function********************************************************************
1304
1305  Synopsis [Creates fanin edges of a vertex based on MDD support.]
1306
1307  Description [Computes the support of the function attached to a vertex and
1308  adds to the graph the edges from the vertices representing those variables
1309  to the given vertex.]
1310
1311  SideEffects []
1312
1313******************************************************************************/
1314void
1315PartPartitionCreateVertexFaninEdges(
1316  graph_t  *partition,
1317  vertex_t *vertexPtr)
1318{
1319  vertex_t       *fromVertex;
1320  Mvf_Function_t *vertexFunction;
1321  st_table       *support;
1322  st_table       *mddIdToVertex;
1323  st_generator   *stGen;
1324  long            mddId;
1325
1326  mddIdToVertex = PartPartitionReadMddIdToVertex(partition);
1327  vertexFunction = PartVertexReadFunction(vertexPtr);
1328  support = PartCreateFunctionSupportTable(vertexFunction);
1329
1330  /* Create the edges for every element in support */
1331  st_foreach_item(support, stGen, &mddId, NULL) {
1332    st_lookup(mddIdToVertex, (char *)mddId, &fromVertex);
1333    /* Make sure no self loops are created */
1334    if (fromVertex != vertexPtr) {
1335      g_add_edge(fromVertex, vertexPtr);
1336    } /* End of if */
1337  }
1338
1339  st_free_table(support);
1340} /* End of PartPartitionCreateVertexFaninEdges */
1341
1342/**Function********************************************************************
1343
1344  Synopsis [Prints information about the Partition through standard output.]
1345
1346  Description [ The format used for printing is <b>dot</b>, a tool for
1347  graph visualization developed at AT&T. It can be obtained from <a
1348  href="http://www.research.att.com/orgs/ssr/book/reuse">
1349  http://www.research.att.com/orgs/ssr/book/reuse</a>. The function
1350  receives as a parameter a file pointer in case the print wants to be
1351  redirected. This function is used by the command routine
1352  CommandPrintPartition.]
1353
1354  SideEffects []
1355
1356******************************************************************************/
1357int
1358PartPartitionPrint(
1359  FILE *fp,
1360  graph_t *partition)
1361{
1362  lsGen      gen;           /* To iterate over edges */
1363  edge_t     *edgePtr;      /* Will hold the edge being processed */
1364  vertex_t   *fromVertex;   /* Will hold the vertex source of the edge */
1365  vertex_t   *toVertex;     /* Will hold the destination of the edge */
1366  st_table   *vertexToId;   /* To lookup the ordinal of a vertex */
1367  time_t      now           = time(0);
1368  struct tm  *nowStructPtr  = localtime(& now);
1369  char       *nowTxt        = asctime(nowStructPtr);
1370  char       *partitionName = PartPartitionReadName(partition);
1371  int        vertexId;
1372  int        clusterId;
1373
1374  /*
1375   * Write out the header for the output file.
1376   */
1377
1378  (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
1379  (void) fprintf(fp, "# partition name: %s\n", partitionName);
1380  (void) fprintf(fp, "# generated: %s", nowTxt);
1381  (void) fprintf(fp, "#\n");
1382
1383  (void) fprintf(fp, "# Partition with %d vertices and %d edges\n",
1384                 lsLength(g_get_vertices(partition)),
1385                 lsLength(g_get_edges(partition)));
1386
1387  (void) fprintf(fp, "digraph \"%s\" {\n  rotate=90;\n", partitionName);
1388  (void) fprintf(fp, "  margin=0.5;\n  label=\"%s\";\n", partitionName);
1389  (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
1390
1391
1392  vertexToId = st_init_table(st_ptrcmp, st_ptrhash);
1393
1394  vertexId = 0;
1395  clusterId = 0;
1396  foreach_vertex(partition, gen, fromVertex) {
1397    if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
1398      array_t *members = PartVertexReadClusterMembers(fromVertex);
1399      vertex_t *auxPtr;
1400      int i;
1401
1402      (void) fprintf(fp, "  subgraph cluster%d {\n", clusterId++);
1403      (void) fprintf(fp, "    label = \"%s\";\n",
1404                     PartVertexReadName(fromVertex));
1405      arrayForEachItem(vertex_t *, members, i, auxPtr) {
1406        (void) fprintf(fp, "  ");
1407        st_insert(vertexToId, (char *)auxPtr, (char *)(long)vertexId);
1408        PrintVertexDescription(fp, auxPtr, vertexId++);
1409      }
1410      (void) fprintf(fp, "  }\n");
1411    } /* End of then */
1412    else if (!PartVertexTestIsClustered(fromVertex)) {
1413      st_insert(vertexToId, (char *)fromVertex, (char *)(long)vertexId);
1414      PrintVertexDescription(fp, fromVertex, vertexId++);
1415    }
1416
1417  }
1418
1419  foreach_edge(partition, gen, edgePtr) {
1420    fromVertex = g_e_source(edgePtr);
1421    toVertex = g_e_dest(edgePtr);
1422
1423    st_lookup_int(vertexToId, (char *)fromVertex, &vertexId);
1424    (void) fprintf(fp, "  node%d -> ", vertexId);
1425
1426    st_lookup_int(vertexToId, (char *)toVertex, &vertexId);
1427    (void) fprintf(fp, "node%d;\n", vertexId);
1428  } /* End of foreach_edge */
1429
1430  (void) fprintf(fp, "}\n");
1431
1432  st_free_table(vertexToId);
1433
1434  return 1;
1435} /* End of PartPartitionPrint */
1436
1437
1438/**Function********************************************************************
1439
1440  Synopsis    [Create latch nodes list and leave nodes list form
1441  CTL properties and fairness constraints]
1442
1443  Comments    []
1444
1445  SideEffects []
1446
1447  SeeAlso     []
1448
1449******************************************************************************/
1450int
1451PartGetLatchInputListFromCTL(
1452  Ntk_Network_t *network,
1453  array_t *ctlArray,
1454  array_t *fairArray,
1455  lsList  latchInputList)
1456{
1457  return PartGetLatchInputListFromCtlAndLtl(network, ctlArray, NIL(array_t),
1458                                            fairArray, latchInputList,
1459                                            FALSE);
1460}
1461
1462/**Function********************************************************************
1463
1464  Synopsis [Create latch inputs list form properties and fairness
1465  constraints]
1466
1467  Comments [Return all the Cone-Of-Influence nodes if stopAtLatch is
1468  FALSE; otherwise, return only the nodes up to the immediate
1469  support.]
1470
1471  SideEffects []
1472
1473  SeeAlso     []
1474
1475******************************************************************************/
1476int
1477PartGetLatchInputListFromCtlAndLtl(
1478  Ntk_Network_t *network,
1479  array_t *ctlArray,
1480  array_t *ltlArray,
1481  array_t *fairArray,
1482  lsList  latchInputList,
1483  boolean stopAtLatch)
1484{
1485  int i;
1486  Ctlp_Formula_t  *ctlFormula;
1487  Ctlsp_Formula_t *ltlFormula;
1488  st_table *formulaNodes;
1489  st_generator *stGen;
1490  array_t *nodeArray;
1491  array_t *formulaCombNodes;
1492  Ntk_Node_t *node;
1493
1494
1495  formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
1496
1497  if ( formulaNodes == NIL(st_table)){
1498    return 0;
1499  }
1500
1501 /*
1502  * Extract nodes in CTL/LTL properties
1503  */
1504  if ( ctlArray != NIL(array_t)){
1505    arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
1506      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
1507    }
1508  }
1509  if ( ltlArray != NIL(array_t)){
1510    arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
1511      Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
1512    }
1513  }
1514
1515 /*
1516  * Extract nodes in fairness properties
1517  */
1518  if ( fairArray != NIL(array_t)){
1519    arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
1520      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
1521    }
1522  }
1523
1524  nodeArray = array_alloc( Ntk_Node_t *, 0 );
1525  st_foreach_item( formulaNodes, stGen, &node, NULL) {
1526    array_insert_last( Ntk_Node_t *, nodeArray, node );
1527  }
1528
1529  st_free_table( formulaNodes );
1530
1531 /*
1532  * Get all combinational support nodes in network from formula nodes
1533  */
1534  formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
1535                     nodeArray, stopAtLatch );
1536  array_free(nodeArray);
1537 /*
1538  * Root list includes latch data input nodes
1539  */
1540  arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
1541    if ( Ntk_NodeTestIsLatch( node ) ) {
1542      Ntk_Node_t *tempNode = Ntk_LatchReadDataInput( node );
1543      lsNewEnd(latchInputList, (lsGeneric)tempNode, LS_NH);
1544    }
1545  }
1546
1547  array_free(formulaCombNodes);
1548
1549  return 1;
1550}
1551
1552/**Function********************************************************************
1553
1554  Synopsis [Create latch nodes list form properties and fairness
1555  constraints]
1556
1557  Comments [Return all the Cone-Of-Influence nodes if stopAtLatch is
1558  FALSE; otherwise, return only the nodes up to the immediate
1559  support.]
1560
1561  SideEffects []
1562
1563  SeeAlso     []
1564
1565******************************************************************************/
1566int
1567PartGetLatchListFromCtlAndLtl(
1568  Ntk_Network_t *network,
1569  array_t *ctlArray,
1570  array_t *ltlArray,
1571  array_t *fairArray,
1572  lsList  latchInputList,
1573  boolean stopAtLatch)
1574{
1575  int i;
1576  Ctlp_Formula_t  *ctlFormula;
1577  Ctlsp_Formula_t *ltlFormula;
1578  st_table *formulaNodes;
1579  st_generator *stGen;
1580  array_t *nodeArray;
1581  array_t *formulaCombNodes;
1582  Ntk_Node_t *node;
1583
1584
1585  formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
1586
1587  if ( formulaNodes == NIL(st_table)){
1588    return 0;
1589  }
1590
1591 /*
1592  * Extract nodes in CTL/LTL properties
1593  */
1594  if ( ctlArray != NIL(array_t)){
1595    arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
1596      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
1597    }
1598  }
1599  if ( ltlArray != NIL(array_t)){
1600    arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
1601      Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
1602    }
1603  }
1604
1605 /*
1606  * Extract nodes in fairness properties
1607  */
1608  if ( fairArray != NIL(array_t)){
1609    arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
1610      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
1611    }
1612  }
1613
1614  nodeArray = array_alloc( Ntk_Node_t *, 0 );
1615  st_foreach_item( formulaNodes, stGen, &node, NULL) {
1616    array_insert_last( Ntk_Node_t *, nodeArray, node );
1617  }
1618
1619  st_free_table( formulaNodes );
1620
1621 /*
1622  * Get all combinational support nodes in network from formula nodes
1623  */
1624  formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
1625                     nodeArray, stopAtLatch );
1626  array_free(nodeArray);
1627 /*
1628  * Root list includes latch data input nodes
1629  */
1630  arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
1631    if ( Ntk_NodeTestIsLatch( node ) ) {
1632      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
1633    }
1634  }
1635
1636  array_free(formulaCombNodes);
1637
1638  return 1;
1639}
1640
1641/*---------------------------------------------------------------------------*/
1642/* Definition of static functions                                            */
1643/*---------------------------------------------------------------------------*/
1644
1645
1646/**Function********************************************************************
1647
1648  Synopsis    [Prints the declaration of a vertex in dot format.]
1649
1650  SideEffects []
1651
1652  SeeAlso     [Part_PartitionPrint]
1653
1654******************************************************************************/
1655static void
1656PrintVertexDescription(
1657  FILE *fp,
1658  vertex_t *vertexPtr,
1659  int order)
1660{
1661  char *name = PartVertexReadName(vertexPtr);
1662
1663  (void) fprintf(fp, "  node%d [label=", order);
1664  if (name != NIL(char)) {
1665    (void) fprintf(fp, "\"%s\"", name);
1666  }
1667  else {
1668    (void) fprintf(fp, "\"None\"");
1669  }
1670  (void) fprintf(fp, "]; \n");
1671} /* End of PrintVertexDescription */
Note: See TracBrowser for help on using the repository browser.