abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddCache.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddCache.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Functions for cache insertion and lookup.]
8 
9  Description [Internal procedures included in this module:
10  <ul>
11  <li> cuddInitCache()
12  <li> cuddCacheInsert()
13  <li> cuddCacheInsert2()
14  <li> cuddCacheLookup()
15  <li> cuddCacheLookupZdd()
16  <li> cuddCacheLookup2()
17  <li> cuddCacheLookup2Zdd()
18  <li> cuddConstantLookup()
19  <li> cuddCacheProfile()
20  <li> cuddCacheResize()
21  <li> cuddCacheFlush()
22  <li> cuddComputeFloorLog2()
23  </ul>
24  Static procedures included in this module:
25  <ul>
26  </ul> ]
27 
28  SeeAlso []
29 
30  Author [Fabio Somenzi]
31 
32  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
33 
34  All rights reserved.
35 
36  Redistribution and use in source and binary forms, with or without
37  modification, are permitted provided that the following conditions
38  are met:
39 
40  Redistributions of source code must retain the above copyright
41  notice, this list of conditions and the following disclaimer.
42 
43  Redistributions in binary form must reproduce the above copyright
44  notice, this list of conditions and the following disclaimer in the
45  documentation and/or other materials provided with the distribution.
46 
47  Neither the name of the University of Colorado nor the names of its
48  contributors may be used to endorse or promote products derived from
49  this software without specific prior written permission.
50 
51  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
54  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
55  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
56  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
57  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
59  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
61  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62  POSSIBILITY OF SUCH DAMAGE.]
63 
64 ******************************************************************************/
65 
66 #include "misc/util/util_hack.h"
67 #include "cuddInt.h"
68 
70 
71 
72 
73 /*---------------------------------------------------------------------------*/
74 /* Constant declarations */
75 /*---------------------------------------------------------------------------*/
76 
77 #ifdef DD_CACHE_PROFILE
78 #define DD_HYSTO_BINS 8
79 #endif
80 
81 /*---------------------------------------------------------------------------*/
82 /* Stucture declarations */
83 /*---------------------------------------------------------------------------*/
84 
85 
86 /*---------------------------------------------------------------------------*/
87 /* Type declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 
91 /*---------------------------------------------------------------------------*/
92 /* Variable declarations */
93 /*---------------------------------------------------------------------------*/
94 
95 #ifndef lint
96 static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.34 2009/02/19 16:17:50 fabio Exp $";
97 #endif
98 
99 /*---------------------------------------------------------------------------*/
100 /* Macro declarations */
101 /*---------------------------------------------------------------------------*/
102 
103 
104 /**AutomaticStart*************************************************************/
105 
106 /*---------------------------------------------------------------------------*/
107 /* Static function prototypes */
108 /*---------------------------------------------------------------------------*/
109 
110 
111 /**AutomaticEnd***************************************************************/
112 
113 
114 /*---------------------------------------------------------------------------*/
115 /* Definition of exported functions */
116 /*---------------------------------------------------------------------------*/
117 
118 /*---------------------------------------------------------------------------*/
119 /* Definition of internal functions */
120 /*---------------------------------------------------------------------------*/
121 
122 
123 /**Function********************************************************************
124 
125  Synopsis [Initializes the computed table.]
126 
127  Description [Initializes the computed table. It is called by
128  Cudd_Init. Returns 1 in case of success; 0 otherwise.]
129 
130  SideEffects [None]
131 
132  SeeAlso [Cudd_Init]
133 
134 ******************************************************************************/
135 int
137  DdManager * unique /* unique table */,
138  unsigned int cacheSize /* initial size of the cache */,
139  unsigned int maxCacheSize /* cache size beyond which no resizing occurs */)
140 {
141  int i;
142  unsigned int logSize;
143 #ifndef DD_CACHE_PROFILE
144  DdNodePtr *mem;
145  ptruint offset;
146 #endif
147 
148  /* Round cacheSize to largest power of 2 not greater than the requested
149  ** initial cache size. */
150  logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2));
151  cacheSize = 1 << logSize;
152 // unique->acache = ABC_ALLOC(DdCache,cacheSize+1);
153  unique->acache = ABC_ALLOC(DdCache,cacheSize+2);
154  if (unique->acache == NULL) {
155  unique->errorCode = CUDD_MEMORY_OUT;
156  return(0);
157  }
158  /* If the size of the cache entry is a power of 2, we want to
159  ** enforce alignment to that power of two. This happens when
160  ** DD_CACHE_PROFILE is not defined. */
161 #ifdef DD_CACHE_PROFILE
162  unique->cache = unique->acache;
163  unique->memused += (cacheSize) * sizeof(DdCache);
164 #else
165  mem = (DdNodePtr *) unique->acache;
166 // offset = (ptruint) mem & (sizeof(DdCache) - 1);
167 // mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr);
168  offset = (ptruint) mem & (32 - 1);
169  mem += (32 - offset) / sizeof(DdNodePtr);
170  unique->cache = (DdCache *) mem;
171 // assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0);
172  assert(((ptruint) unique->cache & (32 - 1)) == 0);
173  unique->memused += (cacheSize+1) * sizeof(DdCache);
174 #endif
175  unique->cacheSlots = cacheSize;
176  unique->cacheShift = sizeof(int) * 8 - logSize;
177  unique->maxCacheHard = maxCacheSize;
178  /* If cacheSlack is non-negative, we can resize. */
179  unique->cacheSlack = (int) ddMin(maxCacheSize,
181  2 * (int) cacheSize;
182  Cudd_SetMinHit(unique,DD_MIN_HIT);
183  /* Initialize to avoid division by 0 and immediate resizing. */
184  unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1);
185  unique->cacheHits = 0;
186  unique->totCachehits = 0;
187  /* The sum of cacheMisses and totCacheMisses is always correct,
188  ** even though cacheMisses is larger than it should for the reasons
189  ** explained above. */
190  unique->totCacheMisses = -unique->cacheMisses;
191  unique->cachecollisions = 0;
192  unique->cacheinserts = 0;
193  unique->cacheLastInserts = 0;
194  unique->cachedeletions = 0;
195 
196  /* Initialize the cache */
197  for (i = 0; (unsigned) i < cacheSize; i++) {
198  unique->cache[i].h = 0; /* unused slots */
199  unique->cache[i].data = NULL; /* invalid entry */
200 #ifdef DD_CACHE_PROFILE
201  unique->cache[i].count = 0;
202 #endif
203  }
204 
205  return(1);
206 
207 } /* end of cuddInitCache */
208 
209 
210 /**Function********************************************************************
211 
212  Synopsis [Inserts a result in the cache.]
213 
214  Description []
215 
216  SideEffects [None]
217 
218  SeeAlso [cuddCacheInsert2 cuddCacheInsert1]
219 
220 ******************************************************************************/
221 void
223  DdManager * table,
224  ptruint op,
225  DdNode * f,
226  DdNode * g,
227  DdNode * h,
228  DdNode * data)
229 {
230  int posn;
231  unsigned hash;
232  register DdCache *entry;
233  ptruint uf, ug, uh;
234  ptruint ufc, ugc, uhc;
235 
236  uf = (ptruint) f | (op & 0xe);
237  ug = (ptruint) g | (op >> 4);
238  uh = (ptruint) h;
239 
240  ufc = (ptruint) cuddF2L(f) | (op & 0xe);
241  ugc = (ptruint) cuddF2L(g) | (op >> 4);
242  uhc = (ptruint) cuddF2L(h);
243 
244  hash = ddCHash2_(uhc,ufc,ugc);
245 // posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
246  posn = hash >> table->cacheShift;
247  entry = &table->cache[posn];
248 
249  table->cachecollisions += entry->data != NULL;
250  table->cacheinserts++;
251 
252  entry->f = (DdNode *) uf;
253  entry->g = (DdNode *) ug;
254  entry->h = uh;
255  entry->data = data;
256 #ifdef DD_CACHE_PROFILE
257  entry->count++;
258 #endif
259  entry->hash = hash;
260 
261 } /* end of cuddCacheInsert */
262 
263 
264 /**Function********************************************************************
265 
266  Synopsis [Inserts a result in the cache for a function with two
267  operands.]
268 
269  Description []
270 
271  SideEffects [None]
272 
273  SeeAlso [cuddCacheInsert cuddCacheInsert1]
274 
275 ******************************************************************************/
276 void
278  DdManager * table,
279  DD_CTFP op,
280  DdNode * f,
281  DdNode * g,
282  DdNode * data)
283 {
284  int posn;
285  unsigned hash;
286  register DdCache *entry;
287 
288  hash = ddCHash2_(op,cuddF2L(f),cuddF2L(g));
289 // posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
290  posn = hash >> table->cacheShift;
291  entry = &table->cache[posn];
292 
293  if (entry->data != NULL) {
294  table->cachecollisions++;
295  }
296  table->cacheinserts++;
297 
298  entry->f = f;
299  entry->g = g;
300  entry->h = (ptruint) op;
301  entry->data = data;
302 #ifdef DD_CACHE_PROFILE
303  entry->count++;
304 #endif
305  entry->hash = hash;
306 
307 } /* end of cuddCacheInsert2 */
308 
309 
310 /**Function********************************************************************
311 
312  Synopsis [Inserts a result in the cache for a function with two
313  operands.]
314 
315  Description []
316 
317  SideEffects [None]
318 
319  SeeAlso [cuddCacheInsert cuddCacheInsert2]
320 
321 ******************************************************************************/
322 void
324  DdManager * table,
325  DD_CTFP1 op,
326  DdNode * f,
327  DdNode * data)
328 {
329  int posn;
330  unsigned hash;
331  register DdCache *entry;
332 
333  hash = ddCHash2_(op,cuddF2L(f),cuddF2L(f));
334 // posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
335  posn = hash >> table->cacheShift;
336  entry = &table->cache[posn];
337 
338  if (entry->data != NULL) {
339  table->cachecollisions++;
340  }
341  table->cacheinserts++;
342 
343  entry->f = f;
344  entry->g = f;
345  entry->h = (ptruint) op;
346  entry->data = data;
347 #ifdef DD_CACHE_PROFILE
348  entry->count++;
349 #endif
350  entry->hash = hash;
351 
352 } /* end of cuddCacheInsert1 */
353 
354 
355 /**Function********************************************************************
356 
357  Synopsis [Looks up in the cache for the result of op applied to f,
358  g, and h.]
359 
360  Description [Returns the result if found; it returns NULL if no
361  result is found.]
362 
363  SideEffects [None]
364 
365  SeeAlso [cuddCacheLookup2 cuddCacheLookup1]
366 
367 ******************************************************************************/
368 DdNode *
370  DdManager * table,
371  ptruint op,
372  DdNode * f,
373  DdNode * g,
374  DdNode * h)
375 {
376  int posn;
377  DdCache *en,*cache;
378  DdNode *data;
379  ptruint uf, ug, uh;
380  ptruint ufc, ugc, uhc;
381 
382  uf = (ptruint) f | (op & 0xe);
383  ug = (ptruint) g | (op >> 4);
384  uh = (ptruint) h;
385 
386  ufc = (ptruint) cuddF2L(f) | (op & 0xe);
387  ugc = (ptruint) cuddF2L(g) | (op >> 4);
388  uhc = (ptruint) cuddF2L(h);
389 
390  cache = table->cache;
391 #ifdef DD_DEBUG
392  if (cache == NULL) {
393  return(NULL);
394  }
395 #endif
396 
397  posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
398  en = &cache[posn];
399  if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && en->h==uh) {
400  data = Cudd_Regular(en->data);
401  table->cacheHits++;
402  if (data->ref == 0) {
403  cuddReclaim(table,data);
404  }
405  return(en->data);
406  }
407 
408  /* Cache miss: decide whether to resize. */
409  table->cacheMisses++;
410 
411  if (table->cacheSlack >= 0 &&
412  table->cacheHits > table->cacheMisses * table->minHit) {
413  cuddCacheResize(table);
414  }
415 
416  return(NULL);
417 
418 } /* end of cuddCacheLookup */
419 
420 
421 /**Function********************************************************************
422 
423  Synopsis [Looks up in the cache for the result of op applied to f,
424  g, and h.]
425 
426  Description [Returns the result if found; it returns NULL if no
427  result is found.]
428 
429  SideEffects [None]
430 
431  SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]
432 
433 ******************************************************************************/
434 DdNode *
436  DdManager * table,
437  ptruint op,
438  DdNode * f,
439  DdNode * g,
440  DdNode * h)
441 {
442  int posn;
443  DdCache *en,*cache;
444  DdNode *data;
445  ptruint uf, ug, uh;
446  ptruint ufc, ugc, uhc;
447 
448  uf = (ptruint) f | (op & 0xe);
449  ug = (ptruint) g | (op >> 4);
450  uh = (ptruint) h;
451 
452  ufc = (ptruint) cuddF2L(f) | (op & 0xe);
453  ugc = (ptruint) cuddF2L(g) | (op >> 4);
454  uhc = (ptruint) cuddF2L(h);
455 
456  cache = table->cache;
457 #ifdef DD_DEBUG
458  if (cache == NULL) {
459  return(NULL);
460  }
461 #endif
462 
463  posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
464  en = &cache[posn];
465  if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
466  en->h==uh) {
467  data = Cudd_Regular(en->data);
468  table->cacheHits++;
469  if (data->ref == 0) {
470  cuddReclaimZdd(table,data);
471  }
472  return(en->data);
473  }
474 
475  /* Cache miss: decide whether to resize. */
476  table->cacheMisses++;
477 
478  if (table->cacheSlack >= 0 &&
479  table->cacheHits > table->cacheMisses * table->minHit) {
480  cuddCacheResize(table);
481  }
482 
483  return(NULL);
484 
485 } /* end of cuddCacheLookupZdd */
486 
487 
488 /**Function********************************************************************
489 
490  Synopsis [Looks up in the cache for the result of op applied to f
491  and g.]
492 
493  Description [Returns the result if found; it returns NULL if no
494  result is found.]
495 
496  SideEffects [None]
497 
498  SeeAlso [cuddCacheLookup cuddCacheLookup1]
499 
500 ******************************************************************************/
501 DdNode *
503  DdManager * table,
504  DD_CTFP op,
505  DdNode * f,
506  DdNode * g)
507 {
508  int posn;
509  DdCache *en,*cache;
510  DdNode *data;
511 
512  cache = table->cache;
513 #ifdef DD_DEBUG
514  if (cache == NULL) {
515  return(NULL);
516  }
517 #endif
518 
519  posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
520  en = &cache[posn];
521  if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
522  data = Cudd_Regular(en->data);
523  table->cacheHits++;
524  if (data->ref == 0) {
525  cuddReclaim(table,data);
526  }
527  return(en->data);
528  }
529 
530  /* Cache miss: decide whether to resize. */
531  table->cacheMisses++;
532 
533  if (table->cacheSlack >= 0 &&
534  table->cacheHits > table->cacheMisses * table->minHit) {
535  cuddCacheResize(table);
536  }
537 
538  return(NULL);
539 
540 } /* end of cuddCacheLookup2 */
541 
542 
543 /**Function********************************************************************
544 
545  Synopsis [Looks up in the cache for the result of op applied to f.]
546 
547  Description [Returns the result if found; it returns NULL if no
548  result is found.]
549 
550  SideEffects [None]
551 
552  SeeAlso [cuddCacheLookup cuddCacheLookup2]
553 
554 ******************************************************************************/
555 DdNode *
557  DdManager * table,
558  DD_CTFP1 op,
559  DdNode * f)
560 {
561  int posn;
562  DdCache *en,*cache;
563  DdNode *data;
564 
565  cache = table->cache;
566 #ifdef DD_DEBUG
567  if (cache == NULL) {
568  return(NULL);
569  }
570 #endif
571 
572  posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
573  en = &cache[posn];
574  if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
575  data = Cudd_Regular(en->data);
576  table->cacheHits++;
577  if (data->ref == 0) {
578  cuddReclaim(table,data);
579  }
580  return(en->data);
581  }
582 
583  /* Cache miss: decide whether to resize. */
584  table->cacheMisses++;
585 
586  if (table->cacheSlack >= 0 &&
587  table->cacheHits > table->cacheMisses * table->minHit) {
588  cuddCacheResize(table);
589  }
590 
591  return(NULL);
592 
593 } /* end of cuddCacheLookup1 */
594 
595 
596 /**Function********************************************************************
597 
598  Synopsis [Looks up in the cache for the result of op applied to f
599  and g.]
600 
601  Description [Returns the result if found; it returns NULL if no
602  result is found.]
603 
604  SideEffects [None]
605 
606  SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd]
607 
608 ******************************************************************************/
609 DdNode *
611  DdManager * table,
612  DD_CTFP op,
613  DdNode * f,
614  DdNode * g)
615 {
616  int posn;
617  DdCache *en,*cache;
618  DdNode *data;
619 
620  cache = table->cache;
621 #ifdef DD_DEBUG
622  if (cache == NULL) {
623  return(NULL);
624  }
625 #endif
626 
627  posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
628  en = &cache[posn];
629  if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
630  data = Cudd_Regular(en->data);
631  table->cacheHits++;
632  if (data->ref == 0) {
633  cuddReclaimZdd(table,data);
634  }
635  return(en->data);
636  }
637 
638  /* Cache miss: decide whether to resize. */
639  table->cacheMisses++;
640 
641  if (table->cacheSlack >= 0 &&
642  table->cacheHits > table->cacheMisses * table->minHit) {
643  cuddCacheResize(table);
644  }
645 
646  return(NULL);
647 
648 } /* end of cuddCacheLookup2Zdd */
649 
650 
651 /**Function********************************************************************
652 
653  Synopsis [Looks up in the cache for the result of op applied to f.]
654 
655  Description [Returns the result if found; it returns NULL if no
656  result is found.]
657 
658  SideEffects [None]
659 
660  SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd]
661 
662 ******************************************************************************/
663 DdNode *
665  DdManager * table,
666  DD_CTFP1 op,
667  DdNode * f)
668 {
669  int posn;
670  DdCache *en,*cache;
671  DdNode *data;
672 
673  cache = table->cache;
674 #ifdef DD_DEBUG
675  if (cache == NULL) {
676  return(NULL);
677  }
678 #endif
679 
680  posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
681  en = &cache[posn];
682  if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
683  data = Cudd_Regular(en->data);
684  table->cacheHits++;
685  if (data->ref == 0) {
686  cuddReclaimZdd(table,data);
687  }
688  return(en->data);
689  }
690 
691  /* Cache miss: decide whether to resize. */
692  table->cacheMisses++;
693 
694  if (table->cacheSlack >= 0 &&
695  table->cacheHits > table->cacheMisses * table->minHit) {
696  cuddCacheResize(table);
697  }
698 
699  return(NULL);
700 
701 } /* end of cuddCacheLookup1Zdd */
702 
703 
704 /**Function********************************************************************
705 
706  Synopsis [Looks up in the cache for the result of op applied to f,
707  g, and h.]
708 
709  Description [Looks up in the cache for the result of op applied to f,
710  g, and h. Assumes that the calling procedure (e.g.,
711  Cudd_bddIteConstant) is only interested in whether the result is
712  constant or not. Returns the result if found (possibly
713  DD_NON_CONSTANT); otherwise it returns NULL.]
714 
715  SideEffects [None]
716 
717  SeeAlso [cuddCacheLookup]
718 
719 ******************************************************************************/
720 DdNode *
722  DdManager * table,
723  ptruint op,
724  DdNode * f,
725  DdNode * g,
726  DdNode * h)
727 {
728  int posn;
729  DdCache *en,*cache;
730  ptruint uf, ug, uh;
731  ptruint ufc, ugc, uhc;
732 
733  uf = (ptruint) f | (op & 0xe);
734  ug = (ptruint) g | (op >> 4);
735  uh = (ptruint) h;
736 
737  ufc = (ptruint) cuddF2L(f) | (op & 0xe);
738  ugc = (ptruint) cuddF2L(g) | (op >> 4);
739  uhc = (ptruint) cuddF2L(h);
740 
741  cache = table->cache;
742 #ifdef DD_DEBUG
743  if (cache == NULL) {
744  return(NULL);
745  }
746 #endif
747  posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
748  en = &cache[posn];
749 
750  /* We do not reclaim here because the result should not be
751  * referenced, but only tested for being a constant.
752  */
753  if (en->data != NULL &&
754  en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) {
755  table->cacheHits++;
756  return(en->data);
757  }
758 
759  /* Cache miss: decide whether to resize. */
760  table->cacheMisses++;
761 
762  if (table->cacheSlack >= 0 &&
763  table->cacheHits > table->cacheMisses * table->minHit) {
764  cuddCacheResize(table);
765  }
766 
767  return(NULL);
768 
769 } /* end of cuddConstantLookup */
770 
771 
772 /**Function********************************************************************
773 
774  Synopsis [Computes and prints a profile of the cache usage.]
775 
776  Description [Computes and prints a profile of the cache usage.
777  Returns 1 if successful; 0 otherwise.]
778 
779  SideEffects [None]
780 
781  SeeAlso []
782 
783 ******************************************************************************/
784 int
786  DdManager * table,
787  FILE * fp)
788 {
789  DdCache *cache = table->cache;
790  int slots = table->cacheSlots;
791  int nzeroes = 0;
792  int i, retval;
793  double exUsed;
794 
795 #ifdef DD_CACHE_PROFILE
796  double count, mean, meansq, stddev, expected;
797  long max, min;
798  int imax, imin;
799  double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */
800  int nbins = DD_HYSTO_BINS;
801  int bin;
802  long thiscount;
803  double totalcount, exStddev;
804 
805  meansq = mean = expected = 0.0;
806  max = min = (long) cache[0].count;
807  imax = imin = 0;
808  totalcount = 0.0;
809 
810  hystogramQ = ABC_ALLOC(double, nbins);
811  if (hystogramQ == NULL) {
812  table->errorCode = CUDD_MEMORY_OUT;
813  return(0);
814  }
815  hystogramR = ABC_ALLOC(double, nbins);
816  if (hystogramR == NULL) {
817  ABC_FREE(hystogramQ);
818  table->errorCode = CUDD_MEMORY_OUT;
819  return(0);
820  }
821  for (i = 0; i < nbins; i++) {
822  hystogramQ[i] = 0;
823  hystogramR[i] = 0;
824  }
825 
826  for (i = 0; i < slots; i++) {
827  thiscount = (long) cache[i].count;
828  if (thiscount > max) {
829  max = thiscount;
830  imax = i;
831  }
832  if (thiscount < min) {
833  min = thiscount;
834  imin = i;
835  }
836  if (thiscount == 0) {
837  nzeroes++;
838  }
839  count = (double) thiscount;
840  mean += count;
841  meansq += count * count;
842  totalcount += count;
843  expected += count * (double) i;
844  bin = (i * nbins) / slots;
845  hystogramQ[bin] += (double) thiscount;
846  bin = i % nbins;
847  hystogramR[bin] += (double) thiscount;
848  }
849  mean /= (double) slots;
850  meansq /= (double) slots;
851 
852  /* Compute the standard deviation from both the data and the
853  ** theoretical model for a random distribution. */
854  stddev = sqrt(meansq - mean*mean);
855  exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots);
856 
857  retval = fprintf(fp,"Cache average accesses = %g\n", mean);
858  if (retval == EOF) return(0);
859  retval = fprintf(fp,"Cache access standard deviation = %g ", stddev);
860  if (retval == EOF) return(0);
861  retval = fprintf(fp,"(expected = %g)\n", exStddev);
862  if (retval == EOF) return(0);
863  retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
864  if (retval == EOF) return(0);
865  retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
866  if (retval == EOF) return(0);
867  exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots));
868  retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
869  100.0 - (double) nzeroes * 100.0 / (double) slots,
870  exUsed);
871  if (retval == EOF) return(0);
872 
873  if (totalcount > 0) {
874  expected /= totalcount;
875  retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
876  if (retval == EOF) return(0);
877  retval = fprintf(fp," (expected bin value = %g)\nBy quotient:",
878  expected);
879  if (retval == EOF) return(0);
880  for (i = nbins - 1; i>=0; i--) {
881  retval = fprintf(fp," %.0f", hystogramQ[i]);
882  if (retval == EOF) return(0);
883  }
884  retval = fprintf(fp,"\nBy residue: ");
885  if (retval == EOF) return(0);
886  for (i = nbins - 1; i>=0; i--) {
887  retval = fprintf(fp," %.0f", hystogramR[i]);
888  if (retval == EOF) return(0);
889  }
890  retval = fprintf(fp,"\n");
891  if (retval == EOF) return(0);
892  }
893 
894  ABC_FREE(hystogramQ);
895  ABC_FREE(hystogramR);
896 #else
897  for (i = 0; i < slots; i++) {
898  nzeroes += cache[i].h == 0;
899  }
900  exUsed = 100.0 *
901  (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) /
902  (double) slots));
903  retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
904  100.0 - (double) nzeroes * 100.0 / (double) slots,
905  exUsed);
906  if (retval == EOF) return(0);
907 #endif
908  return(1);
909 
910 } /* end of cuddCacheProfile */
911 
912 
913 /**Function********************************************************************
914 
915  Synopsis [Resizes the cache.]
916 
917  Description []
918 
919  SideEffects [None]
920 
921  SeeAlso []
922 
923 ******************************************************************************/
924 void
926  DdManager * table)
927 {
928  DdCache *cache, *oldcache, *oldacache, *entry, *old;
929  int i;
930  int posn, shift;
931  unsigned int slots, oldslots;
932  double offset;
933  int moved = 0;
934  extern DD_OOMFP MMoutOfMemory;
935  DD_OOMFP saveHandler;
936 #ifndef DD_CACHE_PROFILE
937  ptruint misalignment;
938  DdNodePtr *mem;
939 #endif
940 
941  oldcache = table->cache;
942  oldacache = table->acache;
943  oldslots = table->cacheSlots;
944  slots = table->cacheSlots = oldslots << 1;
945 
946 #ifdef DD_VERBOSE
947  (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n",
948  oldslots, slots);
949  (void) fprintf(table->err,
950  "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
951  table->cacheHits, table->cacheMisses,
952  table->cacheHits / (table->cacheHits + table->cacheMisses));
953 #endif
954 
955  saveHandler = MMoutOfMemory;
956  MMoutOfMemory = Cudd_OutOfMem;
957 // table->acache = cache = ABC_ALLOC(DdCache,slots+1);
958  table->acache = cache = ABC_ALLOC(DdCache,slots+2);
959  MMoutOfMemory = saveHandler;
960  /* If we fail to allocate the new table we just give up. */
961  if (cache == NULL) {
962 #ifdef DD_VERBOSE
963  (void) fprintf(table->err,"Resizing failed. Giving up.\n");
964 #endif
965  table->cacheSlots = oldslots;
966  table->acache = oldacache;
967  /* Do not try to resize again. */
968  table->maxCacheHard = oldslots - 1;
969  table->cacheSlack = - (int) (oldslots + 1);
970  return;
971  }
972  /* If the size of the cache entry is a power of 2, we want to
973  ** enforce alignment to that power of two. This happens when
974  ** DD_CACHE_PROFILE is not defined. */
975 #ifdef DD_CACHE_PROFILE
976  table->cache = cache;
977 #else
978  mem = (DdNodePtr *) cache;
979 // misalignment = (ptruint) mem & (sizeof(DdCache) - 1);
980 // mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr);
981 // table->cache = cache = (DdCache *) mem;
982 // assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0);
983  misalignment = (ptruint) mem & (32 - 1);
984  mem += (32 - misalignment) / sizeof(DdNodePtr);
985  table->cache = cache = (DdCache *) mem;
986  assert(((ptruint) table->cache & (32 - 1)) == 0);
987 #endif
988  shift = --(table->cacheShift);
989  table->memused += (slots - oldslots) * sizeof(DdCache);
990  table->cacheSlack -= slots; /* need these many slots to double again */
991 
992  /* Clear new cache. */
993  for (i = 0; (unsigned) i < slots; i++) {
994  cache[i].data = NULL;
995  cache[i].h = 0;
996 #ifdef DD_CACHE_PROFILE
997  cache[i].count = 0;
998 #endif
999  }
1000 
1001  /* Copy from old cache to new one. */
1002  for (i = 0; (unsigned) i < oldslots; i++) {
1003  old = &oldcache[i];
1004  if (old->data != NULL) {
1005 // posn = ddCHash2(old->h,old->f,old->g,shift);
1006  posn = old->hash >> shift;
1007  entry = &cache[posn];
1008  entry->f = old->f;
1009  entry->g = old->g;
1010  entry->h = old->h;
1011  entry->data = old->data;
1012 #ifdef DD_CACHE_PROFILE
1013  entry->count = 1;
1014 #endif
1015  entry->hash = old->hash;
1016  moved++;
1017  }
1018  }
1019 
1020  ABC_FREE(oldacache);
1021 
1022  /* Reinitialize measurements so as to avoid division by 0 and
1023  ** immediate resizing.
1024  */
1025  offset = (double) (int) (slots * table->minHit + 1);
1026  table->totCacheMisses += table->cacheMisses - offset;
1027  table->cacheMisses = offset;
1028  table->totCachehits += table->cacheHits;
1029  table->cacheHits = 0;
1030  table->cacheLastInserts = table->cacheinserts - (double) moved;
1031 
1032 } /* end of cuddCacheResize */
1033 
1034 
1035 /**Function********************************************************************
1036 
1037  Synopsis [Flushes the cache.]
1038 
1039  Description []
1040 
1041  SideEffects [None]
1042 
1043  SeeAlso []
1044 
1045 ******************************************************************************/
1046 void
1048  DdManager * table)
1049 {
1050  int i, slots;
1051  DdCache *cache;
1052 
1053  slots = table->cacheSlots;
1054  cache = table->cache;
1055  for (i = 0; i < slots; i++) {
1056  table->cachedeletions += cache[i].data != NULL;
1057  cache[i].data = NULL;
1058  }
1059  table->cacheLastInserts = table->cacheinserts;
1060 
1061  return;
1062 
1063 } /* end of cuddCacheFlush */
1064 
1065 
1066 /**Function********************************************************************
1067 
1068  Synopsis [Returns the floor of the logarithm to the base 2.]
1069 
1070  Description [Returns the floor of the logarithm to the base 2.
1071  The input value is assumed to be greater than 0.]
1072 
1073  SideEffects [None]
1074 
1075  SeeAlso []
1076 
1077 ******************************************************************************/
1078 int
1080  unsigned int value)
1081 {
1082  int floorLog = 0;
1083 #ifdef DD_DEBUG
1084  assert(value > 0);
1085 #endif
1086  while (value > 1) {
1087  floorLog++;
1088  value >>= 1;
1089  }
1090  return(floorLog);
1091 
1092 } /* end of cuddComputeFloorLog2 */
1093 
1094 /*---------------------------------------------------------------------------*/
1095 /* Definition of static functions */
1096 /*---------------------------------------------------------------------------*/
1097 
1098 
1100 
DdHalfWord ref
Definition: cudd.h:280
DdNode * cuddCacheLookupZdd(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:435
DdNode * cuddCacheLookup2Zdd(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:610
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1047
void(* DD_OOMFP)(long)
Definition: cudd.h:324
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
DdNode * f
Definition: cuddInt.h:317
Definition: cudd.h:278
void cuddCacheInsert2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g, DdNode *data)
Definition: cuddCache.c:277
DdNode * data
Definition: cuddInt.h:319
unsigned int maxCacheHard
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:368
ptruint h
Definition: cuddInt.h:318
#define Cudd_Regular(node)
Definition: cudd.h:397
void cuddReclaim(DdManager *table, DdNode *n)
Definition: cuddRef.c:584
void cuddCacheInsert(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
Definition: cuddCache.c:222
FILE * err
Definition: cuddInt.h:442
DdNode * g
Definition: cuddInt.h:317
DdNode *(* DD_CTFP)(DdManager *, DdNode *, DdNode *)
Definition: cudd.h:321
DdNode *(* DD_CTFP1)(DdManager *, DdNode *)
Definition: cudd.h:322
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int cuddInitCache(DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)
Definition: cuddCache.c:136
double cachecollisions
Definition: cuddInt.h:457
#define DD_MIN_HIT
Definition: cuddInt.h:136
double cacheinserts
Definition: cuddInt.h:458
static int * entry
Definition: cuddGroup.c:122
ABC_PTRUINT_T ptruint
Definition: cuddInt.h:261
static ABC_NAMESPACE_IMPL_START char rcsid[] DD_UNUSED
Definition: cuddCache.c:96
DdNode * cuddCacheLookup2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:502
unsigned int cacheSlots
Definition: cuddInt.h:353
DdNode * cuddCacheLookup1(DdManager *table, DD_CTFP1 op, DdNode *f)
Definition: cuddCache.c:556
DdCache * cache
Definition: cuddInt.h:352
double totCacheMisses
Definition: cuddInt.h:456
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddCache.c:1079
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define ddMax(x, y)
Definition: cuddInt.h:832
static double max
Definition: cuddSubsetHB.c:134
static uint32_t hash(uint32_t x)
Definition: Map.h:38
double cacheLastInserts
Definition: cuddInt.h:459
double cacheHits
Definition: cuddInt.h:356
#define cuddF2L(f)
Definition: cuddInt.h:718
#define ddMin(x, y)
Definition: cuddInt.h:818
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:144
void Cudd_SetMinHit(DdManager *dd, unsigned int hr)
Definition: cuddAPI.c:1298
int cacheSlack
Definition: cuddInt.h:358
DdNode * cuddConstantLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:721
#define ddCHash2(o, f, g, s)
Definition: cuddInt.h:786
void cuddReclaimZdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:638
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
unsigned long memused
Definition: cuddInt.h:449
int cuddCacheProfile(DdManager *table, FILE *fp)
Definition: cuddCache.c:785
unsigned hash
Definition: cuddInt.h:323
#define ABC_FREE(obj)
Definition: abc_global.h:232
double cacheMisses
Definition: cuddInt.h:355
double minHit
Definition: cuddInt.h:357
#define ddCHash2_(o, f, g)
Definition: cuddInt.h:788
int cacheShift
Definition: cuddInt.h:354
int value
#define assert(ex)
Definition: util_old.h:213
double cachedeletions
Definition: cuddInt.h:460
DdCache * acache
Definition: cuddInt.h:351
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
DdNode * cuddCacheLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:369
DdNode * cuddCacheLookup1Zdd(DdManager *table, DD_CTFP1 op, DdNode *f)
Definition: cuddCache.c:664
void cuddCacheInsert1(DdManager *table, DD_CTFP1 op, DdNode *f, DdNode *data)
Definition: cuddCache.c:323
void cuddCacheResize(DdManager *table)
Definition: cuddCache.c:925
#define MMoutOfMemory
Definition: util_hack.h:38
double totCachehits
Definition: cuddInt.h:455