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

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

vis2.3

File size: 40.3 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [truesimUtil.c]
4
5  PackageName [truesim]
6
7  Synopsis    [Utility functions for the truesim package.]
8
9  Description [Utility functions for the truesim package. Various
10  functions include: to compute the topological depth of a node in
11  a network, file IO for reading and dumping bit-vector patterns for
12  simulation, generating random patterns, and API for accessing
13  simulation information for nodes in the network.]
14
15  Author      [Balakrishna Kumthekar]
16
17  Copyright [This file was created at the University of Colorado at Boulder.
18  The University of Colorado at Boulder makes no warranty about the suitability
19  of this software for any purpose.  It is presented on an AS IS basis.]
20
21******************************************************************************/
22
23#include "truesimInt.h"
24
25/*---------------------------------------------------------------------------*/
26/* Constant declarations                                                     */
27/*---------------------------------------------------------------------------*/
28
29#define MAX_LENGTH 20000 /* Max. length of a string while reading a file */
30#define UNASSIGNED_DEPTH -1 /* Unassigned depth for a node */
31#define TOKENS " \t\n" /* For parsing delay-load file */
32#define DEFAULT_PROB 0.5
33
34/*---------------------------------------------------------------------------*/
35/* Type declarations                                                         */
36/*---------------------------------------------------------------------------*/
37
38
39/*---------------------------------------------------------------------------*/
40/* Structure declarations                                                    */
41/*---------------------------------------------------------------------------*/
42
43
44/*---------------------------------------------------------------------------*/
45/* Variable declarations                                                     */
46/*---------------------------------------------------------------------------*/
47
48extern int truesimVerbose;
49
50/**AutomaticStart*************************************************************/
51
52/*---------------------------------------------------------------------------*/
53/* Static function prototypes                                                */
54/*---------------------------------------------------------------------------*/
55
56static void GetInputs(char *buffer, Ntk_Network_t *network, array_t *inputArray);
57static void GetPatternVectors(FILE *fp, int vecLen, array_t *patternArray);
58static long NodeComputeDepth(Ntk_Node_t * node);
59static long NodeReadDepth(Ntk_Node_t * node);
60static void NodeSetDepth(Ntk_Node_t * node, long depth);
61static enum st_retval stFloatFree(char *key, char *value, char *arg);
62static float computeProbabilityRecur(Ntk_Network_t *network, st_table *nodeToSimTable, st_table *seenTable, bdd_node *bddNode);
63
64/**AutomaticEnd***************************************************************/
65
66
67/*---------------------------------------------------------------------------*/
68/* Definition of exported functions                                          */
69/*---------------------------------------------------------------------------*/
70
71/**Function********************************************************************
72
73   Synopsis [Update topological depth of nodes in the network. This
74   can be used when the network changes structurally.]
75   
76   SideEffects [None]
77   
78   SeeAlso [Truesim_NetworkComputeNodeDepths]
79
80******************************************************************************/
81void
82Truesim_NetworkUpdateNodeTopologicalDepth(
83  Ntk_Network_t *network)
84{
85  array_t *depthArray,*levelArray;
86  Ntk_Node_t *node;
87  st_table *nodeToSimTable;
88  Truesim_Info_t *simInfo;
89  int i,j;
90 
91  simInfo = (Truesim_Info_t *)
92    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
93  nodeToSimTable = simInfo->nodeToSimTable;
94  depthArray = simInfo->depthArray;
95
96  if (depthArray) {
97    arrayForEachItem(array_t *,depthArray,i,levelArray) {
98      array_free(levelArray);
99    }
100    array_free(depthArray);
101  }
102 
103  depthArray = Truesim_NetworkComputeNodeDepths(network);
104  simInfo->depthArray = depthArray;
105  arrayForEachItem(array_t *,depthArray,i,levelArray) {
106    arrayForEachItem(Ntk_Node_t *,levelArray,j,node) {
107      TrueSim_t *sim;
108      st_lookup(nodeToSimTable,(char *)node,&sim);
109      sim->depth = i;
110    }
111  }
112
113  return;
114} /* End of Truesim_NetworkUpdateNodeTopologicalDepth */
115
116
117/**Function********************************************************************
118
119  Synopsis [Reads the input probabilities of primary inputs from a given file.]
120
121  SideEffects [inputArray and probArray are updated.]
122 
123  SeeAlso [Truesim_GeneratePrimaryInputProbs]
124
125******************************************************************************/
126void
127Truesim_ReadInputProbabilities(
128  Ntk_Network_t *network,
129  char *probFile,
130  array_t *inputArray,
131  array_t *probArray)
132{
133  char str[MAX_LENGTH];
134  float prob;
135  FILE *fp;
136  Ntk_Node_t *node;
137
138  if(probFile == 0 || probFile[0] == '\0') {
139    (void) fprintf(vis_stderr,
140                   "** truesim warning: Probability file was not specified.\n");
141    return;   
142  }
143  /* Read the probabilities. */
144  if ((fp = Cmd_FileOpen(probFile,"r",NIL(char *),1)) == NIL(FILE)) {
145    lsGen gen;
146    (void) fprintf(vis_stderr,
147                   "** truesim warning: Could not open %s for reading.\n", probFile);
148    (void) fprintf(vis_stderr,
149                   "** truesim warning: Using probability as 0.5 for all inputs.\n");
150    Ntk_NetworkForEachPrimaryInput(network,gen,node) {
151      array_insert_last(float,probArray,DEFAULT_PROB);
152      array_insert_last(Ntk_Node_t *,inputArray,node);     
153    }
154  } else {
155    while (fscanf(fp,"%s %f\n",str,&prob) != EOF) {
156      node = Ntk_NetworkFindNodeByName(network,str);
157      if (!node || !Ntk_NodeTestIsPrimaryInput(node)) {
158        (void) fprintf(vis_stderr,
159                       "** truesim warning: No PI with name %s. Ignored.\n",str);
160      } else {
161        if (prob > 1.0 || prob < 0.0) {
162          (void) fprintf(vis_stderr,
163                         "** truesim warning: %s has invalid prob. %f\n",
164                         str,prob);
165          (void) fprintf(vis_stderr,
166                        "** truesim warning: Assuming 0.5 instead\n");
167          prob = DEFAULT_PROB;
168        }
169        array_insert_last(float,probArray,prob);
170        array_insert_last(Ntk_Node_t *,inputArray,node);
171      }
172    }
173    fclose(fp);
174  }
175} /* End of Truesim_ReadInputProbabilities */
176
177
178/**Function********************************************************************
179
180  Synopsis [Generate random probabilities for PI. The probabilites are written
181  to probFile.]
182
183  SideEffects [The probabilites are written to probFile.]
184
185  SeeAlso [Truesim_ReadInputProbabilities, Truesim_GenerateRandomVectors]
186
187******************************************************************************/
188void
189Truesim_GeneratePrimaryInputProbs(
190  Ntk_Network_t *network,
191  char *probFile)
192{
193  FILE *fp;
194  Ntk_Node_t *node;
195  lsGen gen;
196
197  if ((fp = Cmd_FileOpen(probFile,"w",NIL(char *),1)) == NIL(FILE)) {
198    fprintf(vis_stderr,"** truesim error: Cannot open %s for writing\n",probFile);
199    return;
200  }
201  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
202    fprintf(fp,"%s %f\n",
203            Ntk_NodeReadName(node),
204            ((double)util_random()/(double)(MODULUS1 - 2)));
205  }
206  fclose(fp);
207
208} /* End of Truesim_GeneratePrimaryInputProbs */
209
210
211/**Function********************************************************************
212
213  Synopsis [Read simulation vectors from simFile.]
214
215  Description [Read simulation vectors from simFile. The input file looks
216  like below:
217
218  .i c n d o e p f q g r h s i t j u k a l b m
219  .s
220  0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ;
221  0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ;
222  0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ;
223  0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ;
224
225  The .i statement specifies the primary inputs of the network. The patterns
226  start after .s key word. Each vector is a space separated list of bits and
227  ends in a semi-colon. The length of any vector should be equal to the number
228  of signals specified in the .i statement. A line starting with # is a
229  comment. The format is simple but strict and so few checks are performed.
230 
231  inputArray is the array of Ntk_Node_t for primary inputs. patternArray
232  is the array of bit-vectors to be simulated.]
233
234  SideEffects [inputArray and patternArray are updated.]
235
236  SeeAlso [Truesim_ReadInputProbabilities]
237
238******************************************************************************/
239int
240Truesim_ReadSimulationVectors(
241  Ntk_Network_t *network,
242  char *simFile,
243  array_t *inputArray,
244  array_t *patternArray)
245{
246
247  char buffer[MAX_LENGTH];
248  FILE *fp;
249  boolean readInputs;
250 
251  fp = Cmd_FileOpen(simFile,"r",NIL(char *),1);
252  if (fp == NIL(FILE)) {
253    (void) fprintf(vis_stderr,
254                   "** truesim error: Cannot open %s for reading sim. vectors.\n",
255                   simFile);
256    return 0;
257  }
258
259  readInputs = TRUE;
260  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
261    if (buffer[0] == '#' || buffer[0] == '\n') 
262      continue;
263    if (buffer[0] == '.' && buffer[1] == 'i') {
264      if (!readInputs) {
265        (void) fprintf(vis_stderr,
266                       "** spfd error: .i statement encountered earlier.\n");
267        fclose(fp);
268        return 0;
269      }
270      GetInputs(buffer,network,inputArray);
271      readInputs = FALSE;
272    } else if (buffer[0] == '.' && buffer[1] == 's') {
273        int vecLen = array_n(inputArray);
274        if (!vecLen) {
275          /* Error reading pattern file. */
276          fclose(fp);
277          return 0;
278        }
279        GetPatternVectors(fp,vecLen,patternArray);
280        break;
281    } else {
282      (void) fprintf(vis_stdout,
283                     "** spfd warning: Skipping %s\n",buffer);
284    }
285  } /* End of while */
286  fclose(fp);
287
288  return 1;
289} /* End of Truesim_ReadSimulationVectors */
290
291
292/**Function********************************************************************
293
294  Synopsis [Generate random vectors. ]
295
296  Description [Generate random vectors. probArray specifies the signal
297  probabilities for PIs of the network. patternArray stores the individual
298  vectors. numInputs is the number of primary inputs in the network. 'N'
299  patterns are generated.]
300
301  SideEffects [None]
302
303  SeeAlso []
304
305******************************************************************************/
306array_t *
307Truesim_GenerateRandomVectors(
308  Ntk_Network_t *network,
309  array_t *probArray,
310  array_t *patternArray,
311  int numInputs,
312  int N)
313{
314  char *strPtr;
315  float prob;
316  double randomValue;
317  int i,j;
318
319  /* We generate N+1 vectors as the first one is an initialization vector */
320  for (i = 0; i <= N; i++) {
321    strPtr = ALLOC(char,numInputs+1);
322    strPtr[numInputs] = '\0';
323    for (j = 0; j < numInputs; j++) {
324      prob = array_fetch(float,probArray,j);
325      randomValue = ((double)util_random()/(double)(MODULUS1 - 2));
326      if ((double) prob < randomValue)
327        strPtr[j] = '0';
328      else 
329        strPtr[j] = '1';
330    }
331    array_insert_last(char *,patternArray,strPtr);
332  }
333  return patternArray;
334} /* End of Truesim_GenerateRandomVectors */
335
336
337/**Function********************************************************************
338
339  Synopsis [Output vectors to outFile.]
340
341  SideEffects [None]
342
343  SeeAlso []
344
345******************************************************************************/
346void
347Truesim_DumpSimulationVectors(
348  Ntk_Network_t *network,                         
349  array_t *inputArray,
350  array_t *patternArray,
351  char *outFile)
352{
353  FILE *fp;
354  int i; unsigned int j;
355  char *str;
356  Ntk_Node_t *node;
357 
358  if ((fp = Cmd_FileOpen(outFile,"w",NIL(char *),1)) == NIL(FILE)) {
359    fprintf(vis_stderr,
360            "** truesim error: Could not open %s for writing\n",outFile);
361    return;
362  }
363  /* Print the intput array */
364  fprintf(fp,".i ");
365  arrayForEachItem(Ntk_Node_t *,inputArray,i,node) {
366    fprintf(fp,"%s ",Ntk_NodeReadName(node));
367  }
368  fprintf(fp,"\n");
369
370  /* Print the pattern vectors */
371  fprintf(fp,".s\n");
372  arrayForEachItem(char *,patternArray,i,str) {
373    for (j = 0; j < strlen(str); j++)
374      fprintf(fp,"%c ",str[j]);
375    fprintf(fp,";\n");
376  }
377  fclose(fp);
378} /* End of Truesim_DumpSimulationVectors */
379
380
381/**Function********************************************************************
382
383  Synopsis    [Computes the depth of each node in the network.]
384
385  Description [Computes the depth of each node in the network. The
386  depth of a node is defined inductively: PI and nodes with no
387  inputs, have depth 0. Otherwise, the depth of a node is 1 more than
388  the maximum depth over the node's fanins.  Intuitively, the depth of
389  a node is the length of the longest (backward) path from the node to
390  a latch, primary input, pseudo input, or constant.
391
392  The returned array is an array of array_t * of nodes. For ex.
393
394  (n1,n2) (n4,n7,n9) (n3,n8) (n6,n5).
395 
396  Nodes, n1 and n2 have depth of 0, n4,n7, and n9 have a depth of 1, and
397  so on. ]
398
399  SideEffects [Uses undef field of Ntk_Node_t.]
400
401  SeeAlso     []
402
403******************************************************************************/
404array_t *
405Truesim_NetworkComputeNodeDepths(
406  Ntk_Network_t *network)
407{
408  lsList rootList;
409  lsGen       gen;
410  Ntk_Node_t *node;
411  long maxDepth;
412  int i;
413  array_t *tempArray,*depthArray;
414  long noDepthCount = 0;
415
416  rootList = Ntk_NetworkReadPrimaryOutputs(network);
417 
418  /* Initialize the depth of each node to unassigned.  */
419  Ntk_NetworkForEachNode(network, gen, node) {
420    NodeSetDepth(node, UNASSIGNED_DEPTH);
421  }
422
423  /* Start the recursive computation from each root.  */
424  lsForEachItem(rootList, gen, node) {
425    (void) NodeComputeDepth(node);
426  }
427
428  /* Now segregate the nodes according to their depth */
429  /* Find the maximum depth */
430  maxDepth = UNASSIGNED_DEPTH;
431  lsForEachItem(rootList,gen,node) {
432    long depth = NodeReadDepth(node);
433    if (depth > maxDepth)
434      maxDepth = depth;
435  }
436  /* Put the nodes in an array according to their depths. */
437  depthArray = array_alloc(array_t *, maxDepth+1);
438  for (i = 0; i < maxDepth+1; i++) {
439    tempArray = array_alloc(Ntk_Node_t *, 0);
440    array_insert_last(array_t *,depthArray,tempArray);
441  }
442  Ntk_NetworkForEachNode(network,gen,node) {
443    long depth = NodeReadDepth(node);
444    array_t *temp = NIL(array_t);
445
446    if (depth != UNASSIGNED_DEPTH) {
447      temp = array_fetch(array_t *,depthArray,depth);
448      array_insert_last(Ntk_Node_t *,temp,node);
449    }else
450      noDepthCount++;
451  }
452  if (noDepthCount > 0)
453    fprintf(vis_stderr, "Truesim Warning: %ld nodes have no computed depth.\n",
454            noDepthCount);
455
456  return depthArray;
457}
458
459
460/**Function********************************************************************
461
462  Synopsis [Returns topological depth of a node.]
463
464  SideEffects [None]
465
466  SeeAlso []
467
468******************************************************************************/
469int
470Truesim_NetworkReadNodeDepth(
471  Ntk_Network_t *network,
472  Ntk_Node_t *node)
473{
474  Truesim_Info_t *simInfo;
475  st_table *nodeToSimTable;
476  TrueSim_t *sim;
477 
478  simInfo = (Truesim_Info_t *)
479    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
480  nodeToSimTable = simInfo->nodeToSimTable;
481
482  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
483    return TRUESIM_ERROR_VALUE;
484  } else {
485    return sim->depth;
486  }
487 
488} /* End of Truesim_NetworkReadNodeDepth */
489
490
491/**Function********************************************************************
492
493  Synopsis [Returns a node's signal probability.]
494
495  SideEffects [None]
496
497  SeeAlso []
498
499******************************************************************************/
500float
501Truesim_NetworkReadNodeProbability(
502  Ntk_Network_t *network,
503  Ntk_Node_t *node)
504{
505  Truesim_Info_t *simInfo;
506  st_table *nodeToSimTable;
507  TrueSim_t *sim;
508 
509  simInfo = (Truesim_Info_t *)
510    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
511  nodeToSimTable = simInfo->nodeToSimTable;
512
513  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
514    return (float) TRUESIM_ERROR_VALUE;
515  } else {
516    return sim->prob;
517  }
518 
519} /* End of Truesim_NetworkReadNodeProbability */
520
521
522/**Function********************************************************************
523
524  Synopsis [Returns a node's switching probability.]
525
526  SideEffects [None]
527
528  SeeAlso []
529
530******************************************************************************/
531float
532Truesim_NetworkReadNodeSwitchingProb(
533  Ntk_Network_t *network,
534  Ntk_Node_t *node)
535{
536  Truesim_Info_t *simInfo;
537  st_table *nodeToSimTable;
538  TrueSim_t *sim;
539 
540  simInfo = (Truesim_Info_t *)
541    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
542  nodeToSimTable = simInfo->nodeToSimTable;
543
544  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
545    return (float) TRUESIM_ERROR_VALUE;
546  } else {
547    return sim->switching;
548  }
549 
550} /* End of Truesim_NetworkReadNodeSwitchingProb */
551
552
553/**Function********************************************************************
554
555  Synopsis [Returns a node's load.]
556
557  SideEffects [None]
558
559  SeeAlso []
560
561******************************************************************************/
562float
563Truesim_NetworkReadNodeLoad(
564  Ntk_Network_t *network,
565  Ntk_Node_t *node)
566{
567  Truesim_Info_t *simInfo;
568  st_table *nodeToSimTable;
569  TrueSim_t *sim;
570 
571  simInfo = (Truesim_Info_t *)
572    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
573  nodeToSimTable = simInfo->nodeToSimTable;
574
575  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
576    return (float) TRUESIM_ERROR_VALUE;
577  } else {
578    return sim->load;
579  }
580 
581} /* End of Truesim_NetworkReadNodeLoad */
582
583
584/**Function********************************************************************
585
586  Synopsis [Returns a node's delay.]
587
588  SideEffects [None]
589
590  SeeAlso []
591
592******************************************************************************/
593float
594Truesim_NetworkReadNodeDelay(
595  Ntk_Network_t *network,
596  Ntk_Node_t *node)
597{
598  Truesim_Info_t *simInfo;
599  st_table *nodeToSimTable;
600  TrueSim_t *sim;
601 
602  simInfo = (Truesim_Info_t *)
603    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
604  nodeToSimTable = simInfo->nodeToSimTable;
605
606  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
607    return (float) TRUESIM_ERROR_VALUE;
608  } else {
609    return sim->delay;
610  }
611 
612} /* End of Truesim_NetworkReadNodeDelay */
613
614
615/**Function********************************************************************
616
617  Synopsis [Set a node's load.]
618
619  SideEffects [None]
620
621  SeeAlso []
622
623******************************************************************************/
624boolean
625Truesim_NetworkSetNodeLoad(
626  Ntk_Network_t *network,
627  Ntk_Node_t *node,
628  float load)
629{
630  Truesim_Info_t *simInfo;
631  st_table *nodeToSimTable;
632  TrueSim_t *sim;
633 
634  simInfo = (Truesim_Info_t *)
635    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
636  if (!simInfo)
637    goto error;
638 
639  nodeToSimTable = simInfo->nodeToSimTable;
640  if (!nodeToSimTable)
641    goto error;
642 
643  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
644    goto error;
645  } else {
646    sim->load = load;
647  }
648  return TRUE;
649
650 error:
651  (void) fprintf(vis_stderr,
652                 "** truesim error: Network not initialized for simulation.\n");
653  (void) fprintf(vis_stderr,
654                 "** truesim error: Call Truesim_InitializeSimulation.\n");
655  return FALSE;
656 
657} /* End of Truesim_NetworkSetNodeLoad */
658
659
660/**Function********************************************************************
661
662  Synopsis [Set a node's delay.]
663
664  SideEffects [None]
665
666  SeeAlso []
667
668******************************************************************************/
669boolean
670Truesim_NetworkSetNodeDelay(
671  Ntk_Network_t *network,
672  Ntk_Node_t *node,
673  float delay)
674{
675  Truesim_Info_t *simInfo;
676  st_table *nodeToSimTable;
677  TrueSim_t *sim;
678 
679  simInfo = (Truesim_Info_t *)
680    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
681  if (!simInfo)
682    goto error;
683 
684  nodeToSimTable = simInfo->nodeToSimTable;
685  if (!nodeToSimTable)
686    goto error;
687 
688  if (!st_lookup(nodeToSimTable,node,&sim)) {
689    goto error;
690  } else {
691    sim->delay = delay;
692  }
693  return TRUE;
694
695 error:
696  (void) fprintf(vis_stderr,
697                 "** truesim error: Network not initialized for simulation.\n");
698  (void) fprintf(vis_stderr,
699                 "** truesim error: Call Truesim_InitializeSimulation.\n");
700  return FALSE;
701 
702} /* End of Truesim_NetworkSetNodeDelay */
703
704
705/**Function********************************************************************
706
707  Synopsis [Set a node's static probability.]
708
709  SideEffects [None]
710
711  SeeAlso []
712
713******************************************************************************/
714boolean
715Truesim_NetworkSetNodeStaticProb(
716  Ntk_Network_t *network,
717  Ntk_Node_t *node,
718  float prob)
719{
720  Truesim_Info_t *simInfo;
721  st_table *nodeToSimTable;
722  TrueSim_t *sim;
723 
724  simInfo = (Truesim_Info_t *)
725    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
726  if (!simInfo)
727    goto error;
728 
729  nodeToSimTable = simInfo->nodeToSimTable;
730  if (!nodeToSimTable)
731    goto error;
732 
733  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
734    goto error;
735  } else {
736    sim->prob = prob;
737  }
738  return TRUE;
739
740 error:
741  (void) fprintf(vis_stderr,
742                 "** truesim error: Network not initialized for simulation.\n");
743  (void) fprintf(vis_stderr,
744                 "** truesim error: Call Truesim_InitializeSimulation.\n");
745  return FALSE;
746 
747} /* End of Truesim_NetworkSetNodeStaticProb */
748
749
750/**Function********************************************************************
751
752  Synopsis [Set a node's switching (transition) probability.]
753
754  SideEffects [None]
755
756  SeeAlso []
757
758******************************************************************************/
759boolean
760Truesim_NetworkSetNodeSwitchingProb(
761  Ntk_Network_t *network,
762  Ntk_Node_t *node,
763  float switching)
764{
765  Truesim_Info_t *simInfo;
766  st_table *nodeToSimTable;
767  TrueSim_t *sim;
768 
769  simInfo = (Truesim_Info_t *)
770    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
771  if (!simInfo)
772    goto error;
773 
774  nodeToSimTable = simInfo->nodeToSimTable;
775  if (!nodeToSimTable)
776    goto error;
777 
778  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
779    goto error;
780  } else {
781    sim->switching = switching;
782  }
783  return TRUE;
784
785 error:
786  (void) fprintf(vis_stderr,
787                 "** truesim error: Network not initialized for simulation.\n");
788  (void) fprintf(vis_stderr,
789                 "** truesim error: Call Truesim_InitializeSimulation.\n");
790  return FALSE;
791 
792} /* End of Truesim_NetworkSetNodeSwitchingProb */
793
794
795/**Function********************************************************************
796
797  Synopsis [Given a BDD of a network node, compute it's probability. This
798  function assumes that the variables in the support of the BDD belong to the
799  network and those corresponding nodes have their signal probabilites set.]
800
801  SideEffects [None]
802
803  SeeAlso []
804
805******************************************************************************/
806float
807Truesim_BddNodeComputeProbability(
808  Ntk_Network_t *network,
809  bdd_node *func)
810{
811  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
812  Truesim_Info_t *simInfo;
813  st_table *nodeToSimTable;
814  float prob,*dummy;
815  st_table *table;
816  bdd_node *one,*zero;
817 
818  simInfo = (Truesim_Info_t *)
819    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
820  nodeToSimTable = simInfo->nodeToSimTable;
821
822  one = bdd_read_one(ddManager);
823  zero = bdd_read_logic_zero(ddManager);
824 
825  if (func == zero)
826    return 0.0;
827  if (func == one)
828    return 1.0;
829
830  table = st_init_table(st_ptrcmp,st_ptrhash);
831  dummy = ALLOC(float,1);
832  *dummy = 1.0;
833  st_insert(table,(char *)one,(char *)dummy);
834
835  prob = computeProbabilityRecur(network,nodeToSimTable,table,func);
836  st_foreach(table,stFloatFree,NIL(char));
837  st_free_table(table);
838
839  return prob;
840 
841} /* End of Truesim_BddNodeComputeProbability */
842
843/*---------------------------------------------------------------------------*/
844/* Definition of internal functions                                          */
845/*---------------------------------------------------------------------------*/
846/**Function********************************************************************
847
848  Synopsis [Evaluate a node given the state of its fanin.]
849
850  Description [Evaluate a node given the state of its fanin. For
851  example, if the function at 'node' is y = a + b and node 'a' has
852  a value '0' and node 'b' has value '1', (due to propagation of
853  bit-vectors during simulation), we evaluate the node 'y' to have a
854  value '1'. ]
855
856  SideEffects [None]
857
858  SeeAlso []
859
860******************************************************************************/
861char 
862TruesimEvaluateNode(
863  Ntk_Node_t *node,
864  graph_t *partition,
865  bdd_manager *ddManager,
866  st_table *nodeToSimTable)
867{
868  bdd_t *faninBdd,*nodeBdd,*tempBdd;
869  vertex_t *vertex;
870  Mvf_Function_t *nodeMvf;
871  char next;
872 
873  /* Compute the cube for the fanin of node. For ex. if y = a + b, and a =
874  '1' and b = '0', the cube faninBdd is ab' */
875  faninBdd = TruesimComputeFaninMinterm(ddManager,node,nodeToSimTable);
876  vertex = Part_PartitionFindVertexByMddId(partition,
877                                           Ntk_NodeReadMddId(node));
878  nodeMvf = Part_VertexReadFunction(vertex);
879  nodeBdd = array_fetch(bdd_t *,nodeMvf,1);
880
881  /* Evaluate the node */
882  tempBdd = bdd_cofactor(nodeBdd,faninBdd);
883  next = bdd_is_tautology(tempBdd,TRUE) ? '1' : '0';
884
885  bdd_free(tempBdd);
886  bdd_free(faninBdd);
887 
888  return next;
889 
890} /* End of TruesimEvaluateNode */
891
892
893/**Function********************************************************************
894
895  Synopsis [Read the node to simulation structure table.]
896
897  SideEffects [None]
898
899  SeeAlso []
900
901******************************************************************************/
902st_table *
903TruesimNetworkReadSimTable(
904  Ntk_Network_t *network)
905{
906  Truesim_Info_t *simInfo;
907
908  simInfo = (Truesim_Info_t *)
909    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
910
911  return simInfo->nodeToSimTable;
912 
913} /* End of TruesimNetworkReadSimTable */
914
915
916/**Function********************************************************************
917
918  Synopsis [Read the depthArray of the network.]
919
920  SideEffects [None]
921
922  SeeAlso []
923
924******************************************************************************/
925array_t *
926TruesimNetworkReadDepthArray(Ntk_Network_t *network)
927{
928  Truesim_Info_t *simInfo;
929
930  simInfo = (Truesim_Info_t *)
931    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
932  return simInfo->depthArray;
933 
934}
935
936
937/**Function********************************************************************
938
939  Synopsis [Initialize the Truesim_t structure for each node in the network.]
940
941  SideEffects [None]
942
943  SeeAlso []
944
945******************************************************************************/
946void
947TruesimInitializeActivityFields(
948  Ntk_Network_t *network,                       
949  st_table *nodeToSimTable)
950{
951  Ntk_Node_t *node;
952  lsGen gen;
953
954  Ntk_NetworkForEachNode(network,gen,node) {
955    TrueSim_t *sim;
956    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
957      (void) fprintf(vis_stderr,"** truesim fatal: In TruesimInitializeActitivyFields\n");
958      assert(0);
959    }
960    sim->value = '0';
961    sim->prob = 0.0;
962    sim->switching = 0.0;
963    sim->event = NIL(Event);
964  }
965} /* End of TruesimInitializeActivityFields */
966
967
968/**Function********************************************************************
969
970  Synopsis [Returns a BDD minterm for a node based on the state of the
971  node's fanin.]
972
973  Description [[Returns a BDD minterm for a node based on the state of
974  the node's fanin. For ex. if y = a + b, and a = '1' and b = '0',
975  the minterm is the BDD of ab'.  ]
976 
977  SideEffects [None]
978
979  SeeAlso []
980
981******************************************************************************/
982bdd_t *
983TruesimComputeFaninMinterm(
984  bdd_manager *ddManager,
985  Ntk_Node_t *node,
986  st_table *nodeToSimTable)
987{
988  int numFanin = Ntk_NodeReadNumFanins(node);
989  int *phase;
990  bdd_node **vars,*temp;
991  Ntk_Node_t *fanin;
992  TrueSim_t *sim;
993  int i;
994
995  vars = ALLOC(bdd_node *,numFanin);
996  phase = ALLOC(int,numFanin);
997  Ntk_NodeForEachFanin(node,i,fanin) {
998    int id;
999
1000    if (!st_lookup(nodeToSimTable,(char *)fanin,&sim)) {
1001      (void) fprintf(vis_stderr,"** truesim fatal: In TruesimComputeFaninMinterm\n");     
1002      assert(0);
1003    }
1004    id = Ntk_NodeReadMddId(fanin);
1005    vars[i] = bdd_bdd_ith_var(ddManager,id);
1006    phase[i] = (sim->value == '1') ? 1:0;
1007  }
1008  temp = bdd_bdd_compute_cube(ddManager,vars,phase,numFanin);
1009  bdd_ref(temp);
1010
1011  FREE(phase);
1012  FREE(vars);
1013
1014  return (bdd_construct_bdd_t(ddManager,temp));
1015
1016} /* End of TruesimComputeFaninMinterm */
1017
1018
1019/**Function********************************************************************
1020
1021  Synopsis [Print PI/PO names for better readability of simulation output.]
1022
1023  SideEffects [None]
1024
1025  SeeAlso []
1026
1027******************************************************************************/
1028void
1029TruesimPrintNameHeader(Ntk_Network_t *network)
1030{
1031  lsGen gen;
1032  Ntk_Node_t *node;
1033
1034  /* Print PIs first */
1035  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
1036    (void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
1037  }
1038
1039  if (truesimVerbose > 3) {
1040    (void) fprintf(vis_stdout," -- ");
1041    /* Print internal nodes next */
1042    Ntk_NetworkForEachNode(network,gen,node) {
1043      if (!Ntk_NodeTestIsPrimaryInput(node) &&
1044          !Ntk_NodeTestIsPrimaryOutput(node)) {
1045        (void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
1046      }
1047    }
1048  }
1049 
1050  /* Print POs last */
1051  (void) fprintf(vis_stdout," -- ");
1052  Ntk_NetworkForEachPrimaryOutput(network,gen,node) {
1053    (void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
1054  }
1055  (void) fprintf(vis_stdout,"\n");
1056
1057  return ;
1058 
1059} /* End of TruesimPrintNameHeader  */
1060
1061
1062/**Function********************************************************************
1063
1064  Synopsis [Print the logic state of network nodes.]
1065
1066  SideEffects [None]
1067
1068  SeeAlso []
1069
1070******************************************************************************/
1071void
1072TruesimPrintNetworkNodeLogicState(Ntk_Network_t *network)
1073{
1074  st_table *nodeToSimTable;
1075  TrueSim_t *sim;
1076  lsGen gen;
1077  Ntk_Node_t *node;
1078
1079  nodeToSimTable = TruesimNetworkReadSimTable(network);
1080
1081  /* Print PIs first */
1082  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
1083    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
1084      (void) fprintf(vis_stderr,
1085                     "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
1086      assert(0);
1087    }
1088    (void) fprintf(vis_stdout,"%c ",sim->value);
1089  }
1090
1091  if (truesimVerbose > 3) {
1092    (void) fprintf(vis_stdout," -- ");
1093    /* Print internal nodes next */
1094    Ntk_NetworkForEachNode(network,gen,node) {
1095      if (!Ntk_NodeTestIsPrimaryInput(node) &&
1096          !Ntk_NodeTestIsPrimaryOutput(node)) {
1097        if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
1098          (void) fprintf(vis_stderr,
1099                         "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
1100          assert(0);
1101        }
1102        (void) fprintf(vis_stdout,"%c ",sim->value);
1103      }
1104    }
1105  }
1106
1107  /* Print POs last */
1108  (void) fprintf(vis_stdout," -- ");
1109  Ntk_NetworkForEachPrimaryOutput(network,gen,node) {
1110    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
1111      (void) fprintf(vis_stderr,
1112                     "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
1113      assert(0);
1114    }
1115    (void) fprintf(vis_stdout,"%c ",sim->value);
1116  }
1117  (void) fprintf(vis_stdout,"\n");
1118
1119  return ;
1120 
1121} /* End of TruesimPrintNodeLogicState  */
1122
1123
1124/**Function********************************************************************
1125
1126  Synopsis [Read delay and load values from a given file. The format is
1127 
1128  nodeName delay load
1129 
1130  The format is strict and few checks are performed. A line starting
1131  with # is considered a comment. Delay and load values are specified
1132  one per line.]
1133
1134  SideEffects [None]
1135
1136  SeeAlso []
1137
1138******************************************************************************/
1139void
1140TruesimReadDelayFile(
1141  Ntk_Network_t *network,
1142  char *delayFile,
1143  st_table *nodeToSimTable)
1144{
1145  char buffer[MAX_LENGTH], *ptr;
1146  FILE *fp;
1147  lsGen gen;
1148  TrueSim_t *sim;
1149  Ntk_Node_t *node;
1150
1151  fp = Cmd_FileOpen(delayFile,"r",NIL(char *),1);
1152  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
1153    if (buffer[0] == '#' || buffer[0] == '\n') 
1154      continue;
1155    if (truesimVerbose > 10) {
1156      (void) fprintf(vis_stdout,"%s",buffer);
1157    }
1158    ptr = strtok(buffer,TOKENS);
1159    node = Ntk_NetworkFindNodeByName(network,ptr);
1160    if (!node) {
1161      (void) fprintf(vis_stderr, "** truesim warning: %s not in the network\n",
1162                     ptr);
1163      (void) fprintf(vis_stderr, "** truesim warning: Values ignored ...\n");
1164      continue;
1165    }
1166    sim = ALLOC(TrueSim_t,1);
1167    ptr = strtok(NIL(char),TOKENS);
1168    if (ptr) {
1169      sim->delay = atof(ptr);
1170    }
1171    ptr = strtok(NIL(char),TOKENS);
1172    if (ptr) {
1173      sim->load = atof(ptr);
1174    }
1175    st_insert(nodeToSimTable, (char *)node, (char *)sim);
1176    if (truesimVerbose > 10) {
1177      (void) fprintf(vis_stdout,"%s %f %f\n",Ntk_NodeReadName(node),
1178                     sim->delay,sim->load);
1179    }
1180  }
1181
1182  /* Now check that all the nodes have load and delay values. If a
1183     node delay/load value is not initialized, set it to default. */
1184
1185  Ntk_NetworkForEachNode(network,gen,node) {
1186    if (!st_lookup(nodeToSimTable,(char *)node, &sim)) {
1187      sim = ALLOC(TrueSim_t,1);
1188      sim->delay = 1.0;
1189      sim->load = 0.0;
1190      st_insert(nodeToSimTable, (char *)node, (char *)sim);
1191    }
1192    if (sim->delay == 0.0)
1193      sim->delay = 1.0;
1194    /* if (Ntk_NodeTestIsPrimaryInput(node))
1195       sim->delay = 0.0; */
1196  }
1197  fclose(fp);
1198  return;
1199} /* End of TruesimReadDelayFile */
1200
1201
1202/*---------------------------------------------------------------------------*/
1203/* Definition of static functions                                            */
1204/*---------------------------------------------------------------------------*/
1205
1206/**Function********************************************************************
1207
1208  Synopsis [Read PI names from the string.]
1209
1210  Description [Read PI names from the string. This function is called
1211  in Truesim_ReadSimulationVectors. ]
1212
1213  SideEffects [Primary input nodes are returned in inputArray.]
1214
1215  SeeAlso [GetPatternVectors]
1216
1217******************************************************************************/
1218static void
1219GetInputs(
1220  char *buffer,
1221  Ntk_Network_t *network,
1222  array_t *inputArray)
1223{
1224  char internalBuf[MAX_LENGTH];
1225  long i,index;
1226  Ntk_Node_t *node;
1227
1228  index = 2;
1229  while (buffer[index] != '\0') {
1230    if (buffer[index] == ' ' ||
1231        buffer[index] == '\t' ||
1232        buffer[index] == '\n') {
1233      index++;
1234      continue;
1235    }
1236    i = 0;
1237    while (buffer[index] != ' ' && buffer[index] != '\t'
1238           && buffer[index] != '\n') {
1239      internalBuf[i] = buffer[index];
1240      i++;
1241      index++;
1242    } /* End of while */
1243    if (i > 0); {
1244      internalBuf[i] = '\0';
1245      node = Ntk_NetworkFindNodeByName(network,internalBuf);
1246      if (node)
1247        array_insert_last(Ntk_Node_t *,inputArray,node);
1248      else {
1249        (void) fprintf(vis_stderr,
1250                       "** truesim error: %s not found in the circuit.\n", 
1251                       internalBuf);
1252      }
1253      index++;
1254    }
1255  } /* End of while */
1256} /* End of GetInputs */
1257
1258
1259/**Function********************************************************************
1260
1261  Synopsis [Read the pattern vectors from the simulation file.]
1262
1263  Description [Read the pattern vectors from the simulation file. This
1264  function is called in Truesim_ReadSimulationVectors. The length of the
1265  vectors specified in the file should be of vecLen.]
1266
1267  SideEffects [The bit-vectors are returned in patternArray.]
1268
1269  SeeAlso [GetInputs]
1270
1271******************************************************************************/
1272static void
1273GetPatternVectors(
1274  FILE *fp,
1275  int vecLen,
1276  array_t *patternArray)
1277{
1278  char buffer[MAX_LENGTH];
1279  char internalBuf[MAX_LENGTH];
1280  char *str;
1281  int index,i,j;
1282  boolean skip;
1283
1284  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
1285    index = i = 0;
1286    if (buffer[0] == '\n' ||
1287        buffer[0] == '#')
1288      continue;
1289    while (buffer[index] != '\0') {
1290      if (buffer[index] == ' ' ||
1291          buffer[index] == ';' ||
1292          buffer[index] == '\n') {
1293        index++;
1294        continue;
1295      }
1296      internalBuf[i] = buffer[index];
1297      i++;
1298      index++;
1299    }
1300    if (i > 0) {
1301      internalBuf[i] = '\0';
1302      /* Ascertain that internalBuf has only '0's and '1's. */
1303      skip = FALSE;      j = 0;
1304      while (internalBuf[j] != '\0') {
1305        if ((internalBuf[j] != '0') && (internalBuf[j] != '1')) {
1306          skip = TRUE;
1307          break;
1308        }
1309        j++;
1310      }
1311      if (skip) {
1312        (void) fprintf(vis_stdout,
1313                       "** spfd warning: Invalid vector < %s > is ignored.\n",
1314                       internalBuf);
1315      } else if ((unsigned) vecLen != strlen(internalBuf)) {
1316        (void) fprintf(vis_stdout,
1317                       "** spfd warning: Length < %ld > of < %s > incorrect.\n",
1318                       (long) strlen(internalBuf), internalBuf);
1319        (void) fprintf(vis_stdout,
1320                       "** spfd warning: Ignoring < %s > .\n",internalBuf);
1321      } else {
1322        str = util_strsav(internalBuf);
1323        array_insert_last(char *,patternArray,str);
1324      }
1325    }
1326  }
1327} /* End of GetPatternVectors */
1328
1329
1330/**Function********************************************************************
1331
1332  Synopsis    [Computes the depth of a node.]
1333
1334  SideEffects [Changes the undef field of the node.]
1335
1336  SeeAlso     [NetworkComputeNodeDepths]
1337
1338******************************************************************************/
1339
1340/**Function********************************************************************
1341
1342  Synopsis    [Computes the depth of a node.]
1343
1344  SideEffects [Changes the undef field of the node.]
1345
1346  SeeAlso     [NetworkComputeNodeDepths]
1347
1348******************************************************************************/
1349static long
1350NodeComputeDepth(
1351  Ntk_Node_t * node)
1352{
1353  long depth = NodeReadDepth(node);
1354
1355  /* If the node's depth has already been computed (i.e. it's not
1356   unassigned), then just return it below.  If it's unassigned, then
1357   recursively compute it.  */
1358  if (depth == UNASSIGNED_DEPTH) {
1359    if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) {
1360      /* PI and nodes with no fanins, get depth 0. This is the
1361        terminal case of recursion.  */
1362      depth = 0;
1363    } else {
1364      int i;
1365      Ntk_Node_t *fanin;
1366      /* Compute the depth of each fanin node in the support of node,
1367        and maintain the maximum.  We start depth at 0 for max
1368        calculation.  */
1369      depth = 0;
1370      Ntk_NodeForEachFanin(node, i, fanin) { 
1371        long faninDepth = NodeComputeDepth(fanin);
1372
1373        depth = (depth > faninDepth) ? depth:faninDepth;
1374      }
1375     
1376      /* The depth of node is one more than the max depths of its
1377       fanins.  */
1378      depth++;
1379    }
1380
1381    /* Store the depth.  */
1382    NodeSetDepth(node, depth);
1383  }
1384 
1385  return depth;
1386}
1387
1388
1389/**Function********************************************************************
1390
1391  Synopsis    [Reads the depth of a node.]
1392
1393  SideEffects [None]
1394
1395  SeeAlso     [NodeSetDepth]
1396
1397******************************************************************************/
1398static long
1399NodeReadDepth(
1400  Ntk_Node_t * node)
1401{
1402  return ((long) Ntk_NodeReadUndef(node));
1403}
1404
1405
1406/**Function********************************************************************
1407
1408  Synopsis    [Sets the depth of a node.]
1409
1410  SideEffects [Changes the undef field of the node.]
1411
1412  SeeAlso     [NodeReadDepth]
1413
1414******************************************************************************/
1415static void
1416NodeSetDepth(
1417  Ntk_Node_t * node,
1418  long depth)
1419{
1420  Ntk_NodeSetUndef(node, (void *) depth);
1421}
1422
1423/**Function********************************************************************
1424
1425  Synopsis [Free float pointed in an st_table.]
1426
1427  SideEffects [None]
1428
1429  SeeAlso []
1430
1431******************************************************************************/
1432static enum st_retval
1433stFloatFree(
1434  char *key,
1435  char *value,
1436  char *arg)
1437{
1438  float *dummy;
1439  dummy = (float *)value;
1440
1441  if (dummy)
1442    FREE(dummy);
1443
1444  return (ST_CONTINUE);
1445
1446} /* End of stFloatFree */
1447
1448
1449/**Function********************************************************************
1450
1451  Synopsis [Recursive function of Truesim_BddNodeComputeProbability]
1452
1453  Description [Compute the probability of a function represented by
1454  ADD. For example, Probability of a Boolean function f being 1 is given
1455  as follows:
1456 
1457  Prob(f(x) == 1) = Prob(x) * Prob(f_x) + (1.0 - Prob(x)) * Prob(f_x')
1458 
1459  The probability values for the support of f is stored in
1460  nodeToSimTable. ]
1461
1462  SideEffects [None]
1463
1464  SeeAlso [Truesim_BddNodeComputeProbability]
1465
1466******************************************************************************/
1467static float
1468computeProbabilityRecur(
1469  Ntk_Network_t *network,
1470  st_table *nodeToSimTable,
1471  st_table *seenTable,
1472  bdd_node *bddNode)
1473{
1474  float value,*probability,*dummy;
1475  float valueL,valueR;
1476  Ntk_Node_t *networkNode;
1477  TrueSim_t *sim;
1478  bdd_node *N,*Nv,*Nnv;
1479
1480  N = bdd_regular(bddNode);
1481
1482  if (st_lookup(seenTable,(char *)N,&dummy)) {
1483    return ((N != bddNode) ? 1.0 - *dummy : *dummy);
1484  }
1485 
1486  Nv = bdd_bdd_T(N);
1487  Nnv = bdd_bdd_E(N);
1488
1489  /* Recur on the children */
1490  valueR = computeProbabilityRecur(network,nodeToSimTable,seenTable,Nv);
1491  valueL = computeProbabilityRecur(network,nodeToSimTable,seenTable,Nnv);
1492
1493  networkNode = Ntk_NetworkFindNodeByMddId(network,bdd_node_read_index(N));
1494  if (st_lookup(nodeToSimTable,(char *)networkNode,&sim)) {
1495    value = sim->prob;
1496    probability = ALLOC(float,1);
1497    *probability = value * valueR + (1.0 - value) * valueL;
1498  } else {
1499    fprintf(vis_stderr,
1500            "** truesim error: Could not find prob. for node %s\n",
1501            Ntk_NodeReadName(networkNode));
1502    return (float) TRUESIM_ERROR_VALUE;
1503  }
1504
1505  st_insert(seenTable,(char *)N,(char *)probability);
1506
1507  return ((N != bddNode) ? 1.0 - *probability : *probability);
1508
1509} /* End of computeProbabilityRecur */
Note: See TracBrowser for help on using the repository browser.