[13] | 1 | /* BDD package internal definitions */ |
---|
| 2 | |
---|
| 3 | |
---|
| 4 | #if !defined(_BDDINTH) |
---|
| 5 | #define _BDDINTH |
---|
| 6 | |
---|
| 7 | |
---|
| 8 | #include <setjmp.h> |
---|
| 9 | |
---|
| 10 | |
---|
| 11 | /* >>> Configuration things */ |
---|
| 12 | |
---|
| 13 | /* Define this for cache and unique sizes to be a power of 2. */ |
---|
| 14 | /* Probably not a good idea given the current simplistic hash function. */ |
---|
| 15 | |
---|
| 16 | /* #define POWER_OF_2_SIZES */ |
---|
| 17 | |
---|
| 18 | /* Define this if your C preprocessor is broken in such a way that */ |
---|
| 19 | /* token concatenation can be done with something like: */ |
---|
| 20 | /* #define CONCAT(f, g) f/''/g */ |
---|
| 21 | /* where /''/ above would be an empty comment (' => *) if this */ |
---|
| 22 | /* wasn't itself a comment. Most of the (non-ANSI) UNIX C preprocessors */ |
---|
| 23 | /* do seem to be broken, which is why this is defined. If your C */ |
---|
| 24 | /* preprocessor is ANSI, this shouldn't have any effect. */ |
---|
| 25 | |
---|
| 26 | #define BROKEN_CPP |
---|
| 27 | |
---|
| 28 | |
---|
| 29 | |
---|
| 30 | /* >>> All user-visible stuff */ |
---|
| 31 | |
---|
| 32 | #include "bdduser.h" |
---|
| 33 | |
---|
| 34 | |
---|
| 35 | #define ARGS(args) args |
---|
| 36 | |
---|
| 37 | |
---|
| 38 | /* Miscellaneous type definitions */ |
---|
| 39 | |
---|
| 40 | typedef struct hash_table_ *hash_table; |
---|
| 41 | |
---|
| 42 | |
---|
| 43 | /* >>> BDD data structures */ |
---|
| 44 | |
---|
| 45 | #if !defined(POWER_OF_2_SIZES) |
---|
| 46 | extern long bdd_primes[]; |
---|
| 47 | #endif |
---|
| 48 | |
---|
| 49 | |
---|
| 50 | /* Pointer tagging stuff */ |
---|
| 51 | |
---|
| 52 | #define POINTER(p) ((pointer)(((INT_PTR)(p)) & ~(INT_PTR)0x7)) |
---|
| 53 | #define BDD_POINTER(p) ((bdd)POINTER(p)) |
---|
| 54 | #define CACHE_POINTER(p) ((cache_entry)POINTER(p)) |
---|
| 55 | |
---|
| 56 | #define TAG(p) ((int)(((INT_PTR)(p)) & 0x7)) |
---|
| 57 | #define SET_TAG(p, t) ((pointer)((INT_PTR)POINTER(p) | (t))) |
---|
| 58 | |
---|
| 59 | #define TAG0(p) ((int)((INT_PTR)(p) & 0x1)) |
---|
| 60 | #define FLIP_TAG0(p) ((pointer)((INT_PTR)(p) ^ 0x1)) |
---|
| 61 | #define TAG0_HI(p) ((pointer)((INT_PTR)(p) | 0x1)) |
---|
| 62 | #define TAG0_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x1)) |
---|
| 63 | |
---|
| 64 | #define TAG1(p) ((int)((INT_PTR)(p) & 0x2)) |
---|
| 65 | #define FLIP_TAG1(p) ((pointer)((INT_PTR)(p) ^ 0x2)) |
---|
| 66 | #define TAG1_HI(p) ((pointer)((INT_PTR)(p) | 0x2)) |
---|
| 67 | #define TAG1_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x2)) |
---|
| 68 | |
---|
| 69 | #define TAG2(p) ((int)((INT_PTR)(p) & 0x4)) |
---|
| 70 | #define FLIP_TAG2(p) ((pointer)((INT_PTR)(p) ^ 0x4)) |
---|
| 71 | #define TAG2_HI(p) ((pointer)((INT_PTR)(p) | 0x4)) |
---|
| 72 | #define TAG2_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x4)) |
---|
| 73 | |
---|
| 74 | |
---|
| 75 | /* Indexes */ |
---|
| 76 | |
---|
| 77 | typedef unsigned short bdd_index_type; |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | /* Types of various BDD node fields */ |
---|
| 81 | |
---|
| 82 | typedef unsigned short bdd_indexindex_type; |
---|
| 83 | typedef unsigned char bdd_refcount_type; |
---|
| 84 | typedef unsigned char bdd_mark_type; |
---|
| 85 | |
---|
| 86 | |
---|
| 87 | /* A BDD node */ |
---|
| 88 | |
---|
| 89 | struct bdd_ |
---|
| 90 | { |
---|
| 91 | bdd_indexindex_type indexindex; |
---|
| 92 | /* Index into indexes table */ |
---|
| 93 | bdd_refcount_type refs; /* External reference count */ |
---|
| 94 | bdd_mark_type mark; /* Mark and temporary ref count */ |
---|
| 95 | INT_PTR data[2]; /* Then and else pointers, or data */ |
---|
| 96 | /* values for terminals */ |
---|
| 97 | struct bdd_ *next; |
---|
| 98 | }; |
---|
| 99 | |
---|
| 100 | |
---|
| 101 | /* Maximum reference counts */ |
---|
| 102 | |
---|
| 103 | #define BDD_MAX_REFS ((bdd_refcount_type)((1l << (8*sizeof(bdd_refcount_type))) - 1)) |
---|
| 104 | #define BDD_MAX_TEMP_REFS ((bdd_mark_type)((1l << (8*sizeof(bdd_mark_type)-1)) - 1)) |
---|
| 105 | |
---|
| 106 | #define BDD_GC_MARK ((bdd_mark_type)(1l << (8*sizeof(bdd_mark_type)-1))) |
---|
| 107 | |
---|
| 108 | |
---|
| 109 | /* Special indexindexes and indexes */ |
---|
| 110 | |
---|
| 111 | #define BDD_CONST_INDEXINDEX 0 |
---|
| 112 | #define BDD_MAX_INDEXINDEX ((bdd_indexindex_type)((1l << (8*sizeof(bdd_indexindex_type))) - 1)) |
---|
| 113 | #define BDD_MAX_INDEX ((bdd_index_type)((1l << (8*sizeof(bdd_index_type))) - 1)) |
---|
| 114 | |
---|
| 115 | |
---|
| 116 | /* Can this be done legally with a non-ANSI cpp? */ |
---|
| 117 | |
---|
| 118 | #define CONCAT_PTR(f) f##_ptr |
---|
| 119 | |
---|
| 120 | #if defined(CONCAT_PTR) |
---|
| 121 | /* Field accessing stuff */ |
---|
| 122 | |
---|
| 123 | #define BDD_SETUP(f) bdd CONCAT_PTR(f)=BDD_POINTER(f) |
---|
| 124 | #define BDD_RESET(f) CONCAT_PTR(f)=BDD_POINTER(f) |
---|
| 125 | #define BDD_INDEXINDEX(f) (CONCAT_PTR(f)->indexindex) |
---|
| 126 | #define BDD_DATA(f) (CONCAT_PTR(f)->data) |
---|
| 127 | #define BDD_DATA0(f) (CONCAT_PTR(f)->data[0]) |
---|
| 128 | #define BDD_DATA1(f) (CONCAT_PTR(f)->data[1]) |
---|
| 129 | #define BDD_REFS(f) (CONCAT_PTR(f)->refs) |
---|
| 130 | #define BDD_MARK(f) (CONCAT_PTR(f)->mark) |
---|
| 131 | #define BDD_TEMP_REFS(f) (CONCAT_PTR(f)->mark) |
---|
| 132 | |
---|
| 133 | |
---|
| 134 | /* Basic stuff stuff for indexes, testing, etc. */ |
---|
| 135 | |
---|
| 136 | #define BDD_INDEX(bddm, f) ((bddm)->indexes[BDD_INDEXINDEX(f)]) |
---|
| 137 | #define BDD_THEN(f) ((bdd)(BDD_DATA0(f) ^ TAG0(f))) |
---|
| 138 | #define BDD_ELSE(f) ((bdd)(BDD_DATA1(f) ^ TAG0(f))) |
---|
| 139 | #define BDD_SAME_OR_NEGATIONS(f, g) (CONCAT_PTR(f) == CONCAT_PTR(g)) |
---|
| 140 | #define BDD_IS_CONST(f) (BDD_INDEXINDEX(f) == BDD_CONST_INDEXINDEX) |
---|
| 141 | #else |
---|
| 142 | /* Field accessing stuff */ |
---|
| 143 | |
---|
| 144 | #define BDD_SETUP(f) |
---|
| 145 | #define BDD_RESET(f) |
---|
| 146 | #define BDD_INDEXINDEX(f) (BDD_POINTER(f)->indexindex) |
---|
| 147 | #define BDD_DATA(f) (BDD_POINTER(f)->data) |
---|
| 148 | #define BDD_DATA0(f) (BDD_POINTER(f)->data[0]) |
---|
| 149 | #define BDD_DATA1(f) (BDD_POINTER(f)->data[1]) |
---|
| 150 | #define BDD_REFS(f) (BDD_POINTER(f)->refs) |
---|
| 151 | #define BDD_MARK(f) (BDD_POINTER(f)->mark) |
---|
| 152 | #define BDD_TEMP_REFS(f) (BDD_POINTER(f)->mark) |
---|
| 153 | |
---|
| 154 | |
---|
| 155 | /* Basic stuff stuff for indexes, testing, etc. */ |
---|
| 156 | |
---|
| 157 | #define BDD_INDEX(bddm, f) ((bddm)->indexes[BDD_INDEXINDEX(f)]) |
---|
| 158 | #define BDD_THEN(f) ((bdd)(BDD_DATA0(f) ^ TAG0(f))) |
---|
| 159 | #define BDD_ELSE(f) ((bdd)(BDD_DATA1(f) ^ TAG0(f))) |
---|
| 160 | #define BDD_SAME_OR_NEGATIONS(f, g) (BDD_POINTER(f) == BDD_POINTER(g)) |
---|
| 161 | #define BDD_IS_CONST(f) (BDD_INDEXINDEX(f) == BDD_CONST_INDEXINDEX) |
---|
| 162 | #endif |
---|
| 163 | |
---|
| 164 | |
---|
| 165 | /* BDD complement flag stuff */ |
---|
| 166 | |
---|
| 167 | #define BDD_IS_OUTPOS(f) (!TAG0(f)) |
---|
| 168 | #define BDD_OUTPOS(f) ((bdd)TAG0_LO(f)) |
---|
| 169 | #define BDD_NOT(f) ((bdd)FLIP_TAG0(f)) |
---|
| 170 | |
---|
| 171 | |
---|
| 172 | /* Cofactoring stuff */ |
---|
| 173 | |
---|
| 174 | #define BDD_TOP_VAR2(top_indexindex, bddm, f, g)\ |
---|
| 175 | do\ |
---|
| 176 | if (BDD_INDEX(bddm, f) < BDD_INDEX(bddm, g))\ |
---|
| 177 | top_indexindex=BDD_INDEXINDEX(f);\ |
---|
| 178 | else\ |
---|
| 179 | top_indexindex=BDD_INDEXINDEX(g);\ |
---|
| 180 | while (0) |
---|
| 181 | |
---|
| 182 | #define BDD_TOP_VAR3(top_indexindex, bddm, f, g, h)\ |
---|
| 183 | do\ |
---|
| 184 | if (BDD_INDEX(bddm, f) < BDD_INDEX(bddm, g))\ |
---|
| 185 | {\ |
---|
| 186 | top_indexindex=BDD_INDEXINDEX(f);\ |
---|
| 187 | if ((bddm)->indexes[top_indexindex] > BDD_INDEX(bddm, h))\ |
---|
| 188 | top_indexindex=BDD_INDEXINDEX(h);\ |
---|
| 189 | }\ |
---|
| 190 | else\ |
---|
| 191 | {\ |
---|
| 192 | top_indexindex=BDD_INDEXINDEX(g);\ |
---|
| 193 | if ((bddm)->indexes[top_indexindex] > BDD_INDEX(bddm, h))\ |
---|
| 194 | top_indexindex=BDD_INDEXINDEX(h);\ |
---|
| 195 | }\ |
---|
| 196 | while (0) |
---|
| 197 | |
---|
| 198 | #define BDD_COFACTOR(top_indexindex, f, f_then, f_else)\ |
---|
| 199 | do\ |
---|
| 200 | if (BDD_INDEXINDEX(f) == top_indexindex)\ |
---|
| 201 | {\ |
---|
| 202 | f_then=BDD_THEN(f);\ |
---|
| 203 | f_else=BDD_ELSE(f);\ |
---|
| 204 | }\ |
---|
| 205 | else\ |
---|
| 206 | {\ |
---|
| 207 | f_then=f;\ |
---|
| 208 | f_else=f;\ |
---|
| 209 | }\ |
---|
| 210 | while (0) |
---|
| 211 | |
---|
| 212 | |
---|
| 213 | /* Ordering stuff */ |
---|
| 214 | |
---|
| 215 | #define BDD_OUT_OF_ORDER(f, g) ((INT_PTR)f > (INT_PTR)g) |
---|
| 216 | |
---|
| 217 | #if defined(CONCAT_PTR) |
---|
| 218 | #define BDD_SWAP(f, g)\ |
---|
| 219 | do\ |
---|
| 220 | {\ |
---|
| 221 | bdd _temp;\ |
---|
| 222 | _temp=f;\ |
---|
| 223 | f=g;\ |
---|
| 224 | g=_temp;\ |
---|
| 225 | _temp=CONCAT_PTR(f);\ |
---|
| 226 | CONCAT_PTR(f)=CONCAT_PTR(g);\ |
---|
| 227 | CONCAT_PTR(g)=_temp;\ |
---|
| 228 | }\ |
---|
| 229 | while (0) |
---|
| 230 | #else |
---|
| 231 | #define BDD_SWAP(f, g)\ |
---|
| 232 | do\ |
---|
| 233 | {\ |
---|
| 234 | bdd _temp;\ |
---|
| 235 | _temp=f;\ |
---|
| 236 | f=g;\ |
---|
| 237 | g=_temp;\ |
---|
| 238 | }\ |
---|
| 239 | while (0) |
---|
| 240 | #endif |
---|
| 241 | |
---|
| 242 | |
---|
| 243 | /* This gets the variable at the top of a node. */ |
---|
| 244 | |
---|
| 245 | #define BDD_IF(bddm, f) ((bddm)->variables[BDD_INDEXINDEX(f)]) |
---|
| 246 | |
---|
| 247 | |
---|
| 248 | /* Reference count stuff */ |
---|
| 249 | |
---|
| 250 | #define BDD_INCREFS(f)\ |
---|
| 251 | do\ |
---|
| 252 | {\ |
---|
| 253 | if (BDD_REFS(f) >= BDD_MAX_REFS-1)\ |
---|
| 254 | {\ |
---|
| 255 | BDD_REFS(f)=BDD_MAX_REFS;\ |
---|
| 256 | BDD_TEMP_REFS(f)=0;\ |
---|
| 257 | }\ |
---|
| 258 | else\ |
---|
| 259 | BDD_REFS(f)++;\ |
---|
| 260 | }\ |
---|
| 261 | while (0) |
---|
| 262 | |
---|
| 263 | #define BDD_DECREFS(f)\ |
---|
| 264 | do\ |
---|
| 265 | {\ |
---|
| 266 | if (BDD_REFS(f) < BDD_MAX_REFS)\ |
---|
| 267 | BDD_REFS(f)--;\ |
---|
| 268 | }\ |
---|
| 269 | while (0) |
---|
| 270 | |
---|
| 271 | #define BDD_TEMP_INCREFS(f)\ |
---|
| 272 | do\ |
---|
| 273 | {\ |
---|
| 274 | if (BDD_REFS(f) < BDD_MAX_REFS)\ |
---|
| 275 | {\ |
---|
| 276 | BDD_TEMP_REFS(f)++;\ |
---|
| 277 | if (BDD_TEMP_REFS(f) == BDD_MAX_TEMP_REFS)\ |
---|
| 278 | {\ |
---|
| 279 | BDD_REFS(f)=BDD_MAX_REFS;\ |
---|
| 280 | BDD_TEMP_REFS(f)=0;\ |
---|
| 281 | }\ |
---|
| 282 | }\ |
---|
| 283 | }\ |
---|
| 284 | while (0) |
---|
| 285 | |
---|
| 286 | #define BDD_TEMP_DECREFS(f)\ |
---|
| 287 | do\ |
---|
| 288 | {\ |
---|
| 289 | if (BDD_REFS(f) < BDD_MAX_REFS)\ |
---|
| 290 | BDD_TEMP_REFS(f)--;\ |
---|
| 291 | }\ |
---|
| 292 | while (0) |
---|
| 293 | |
---|
| 294 | #define BDD_IS_USED(f) ((BDD_MARK(f) & BDD_GC_MARK) != 0) |
---|
| 295 | |
---|
| 296 | |
---|
| 297 | /* Convert an internal reference to an external one and return. */ |
---|
| 298 | |
---|
| 299 | #define RETURN_BDD(thing)\ |
---|
| 300 | return (bdd_make_external(thing)) |
---|
| 301 | |
---|
| 302 | |
---|
| 303 | /* These return the constants. */ |
---|
| 304 | |
---|
| 305 | #define BDD_ONE(bddm) ((bddm)->one) |
---|
| 306 | #define BDD_ZERO(bddm) ((bddm)->zero) |
---|
| 307 | |
---|
| 308 | |
---|
| 309 | /* Cache entries */ |
---|
| 310 | |
---|
| 311 | struct cache_entry_ |
---|
| 312 | { |
---|
| 313 | INT_PTR slot[4]; |
---|
| 314 | }; |
---|
| 315 | |
---|
| 316 | typedef struct cache_entry_ *cache_entry; |
---|
| 317 | |
---|
| 318 | |
---|
| 319 | /* Cache entry tags; ITE is for IF-THEN-ELSE operations. TWO is for */ |
---|
| 320 | /* the two argument operations that return a BDD result. ONEDATA */ |
---|
| 321 | /* and TWODATA are for one and two argument operations that return */ |
---|
| 322 | /* double and single word data results. Everything else is under */ |
---|
| 323 | /* user control. */ |
---|
| 324 | |
---|
| 325 | #define CACHE_TYPE_ITE 0x0 |
---|
| 326 | #define CACHE_TYPE_TWO 0x1 |
---|
| 327 | #define CACHE_TYPE_ONEDATA 0x2 |
---|
| 328 | #define CACHE_TYPE_TWODATA 0x3 |
---|
| 329 | #define CACHE_TYPE_USER1 0x4 |
---|
| 330 | |
---|
| 331 | #define USER_ENTRY_TYPES 4 |
---|
| 332 | |
---|
| 333 | |
---|
| 334 | /* Operation numbers (for CACHE_TYPE_TWO) */ |
---|
| 335 | /* OP_RELPROD, OP_QNT and OP_SUBST need a reasonable number of holes */ |
---|
| 336 | /* after them since the variable association number is added to them */ |
---|
| 337 | /* to get the actual op. OP_COMP, OP_SWAP and OP_CMPTO need */ |
---|
| 338 | /* BDD_MAX_INDEX. OP_SWAPAUX needs 2*BDD_MAX_INDEX. Negative */ |
---|
| 339 | /* operation numbers denote temporaries and are generated as needed. */ |
---|
| 340 | |
---|
| 341 | #define OP_COFACTOR 100l |
---|
| 342 | #define OP_SATFRAC 200l |
---|
| 343 | #define OP_FWD 300l |
---|
| 344 | #define OP_REV 400l |
---|
| 345 | #define OP_RED 500l |
---|
| 346 | #define OP_EQUAL 600l |
---|
| 347 | #define OP_QNT 10000l |
---|
| 348 | #define OP_RELPROD 20000l |
---|
| 349 | #define OP_SUBST 30000l |
---|
| 350 | #define OP_COMP 100000l |
---|
| 351 | #define OP_CMPTO 200000l |
---|
| 352 | #define OP_SWAP 300000l |
---|
| 353 | #define OP_SWAPAUX 400000l |
---|
| 354 | |
---|
| 355 | |
---|
| 356 | /* Variable associations */ |
---|
| 357 | |
---|
| 358 | struct var_assoc_ |
---|
| 359 | { |
---|
| 360 | bdd *assoc; /* Array with associated BDDs */ |
---|
| 361 | long last; /* Indexindex for lowest variable */ |
---|
| 362 | }; |
---|
| 363 | |
---|
| 364 | typedef struct var_assoc_ *var_assoc; |
---|
| 365 | |
---|
| 366 | |
---|
| 367 | struct assoc_list_ |
---|
| 368 | { |
---|
| 369 | struct var_assoc_ va; /* The association */ |
---|
| 370 | int id; /* Identifier for this association */ |
---|
| 371 | int refs; /* Number of outstanding references */ |
---|
| 372 | struct assoc_list_ *next; /* The next association */ |
---|
| 373 | }; |
---|
| 374 | |
---|
| 375 | typedef struct assoc_list_ *assoc_list; |
---|
| 376 | |
---|
| 377 | |
---|
| 378 | /* Variable blocks */ |
---|
| 379 | |
---|
| 380 | struct block_ |
---|
| 381 | { |
---|
| 382 | long num_children; |
---|
| 383 | struct block_ **children; |
---|
| 384 | int reorderable; |
---|
| 385 | long first_index; |
---|
| 386 | long last_index; |
---|
| 387 | }; |
---|
| 388 | |
---|
| 389 | |
---|
| 390 | /* A cache bin; the cache is two-way associative. */ |
---|
| 391 | |
---|
| 392 | struct cache_bin_ |
---|
| 393 | { |
---|
| 394 | cache_entry entry[2]; /* LRU has index 1 */ |
---|
| 395 | }; |
---|
| 396 | |
---|
| 397 | typedef struct cache_bin_ cache_bin; |
---|
| 398 | |
---|
| 399 | |
---|
| 400 | /* The cache */ |
---|
| 401 | |
---|
| 402 | struct cache_ |
---|
| 403 | { |
---|
| 404 | cache_bin *table; /* The cache itself */ |
---|
| 405 | int size_index; /* Index giving number of cache lines */ |
---|
| 406 | long size; /* Number of cache lines */ |
---|
| 407 | int cache_level; /* Bin to start search in cache */ |
---|
| 408 | /* Cache control functions: */ |
---|
| 409 | long (*rehash_fn[8]) ARGS((cmu_bdd_manager, cache_entry)); |
---|
| 410 | /* Rehashes a cache entry */ |
---|
| 411 | int (*gc_fn[8]) ARGS((cmu_bdd_manager, cache_entry)); |
---|
| 412 | /* Checks to see if an entry needs flushing */ |
---|
| 413 | void (*purge_fn[8]) ARGS((cmu_bdd_manager, cache_entry)); |
---|
| 414 | /* Called when purging an entry */ |
---|
| 415 | void (*return_fn[8]) ARGS((cmu_bdd_manager, cache_entry)); |
---|
| 416 | /* Called before returning from cache hit */ |
---|
| 417 | int (*flush_fn[8]) ARGS((cmu_bdd_manager, cache_entry, pointer)); |
---|
| 418 | /* Called when freeing variable association */ |
---|
| 419 | int cache_ratio; /* Cache to unique table size ratio */ |
---|
| 420 | long entries; /* Number of cache entries */ |
---|
| 421 | long lookups; /* Number of cache lookups */ |
---|
| 422 | long hits; /* Number of cache hits */ |
---|
| 423 | long inserts; /* Number of cache inserts */ |
---|
| 424 | long collisions; /* Number of cache collisions */ |
---|
| 425 | }; |
---|
| 426 | |
---|
| 427 | typedef struct cache_ cache; |
---|
| 428 | |
---|
| 429 | |
---|
| 430 | /* One part of the node table */ |
---|
| 431 | |
---|
| 432 | struct var_table_ |
---|
| 433 | { |
---|
| 434 | bdd *table; /* Pointers to the start of each bucket */ |
---|
| 435 | int size_index; /* Index giving number of buckets */ |
---|
| 436 | long size; /* Number of buckets */ |
---|
| 437 | long entries; /* Number of BDD nodes in table */ |
---|
| 438 | }; |
---|
| 439 | |
---|
| 440 | typedef struct var_table_ *var_table; |
---|
| 441 | |
---|
| 442 | |
---|
| 443 | /* The BDD node table */ |
---|
| 444 | |
---|
| 445 | struct unique_ |
---|
| 446 | { |
---|
| 447 | var_table *tables; /* Individual variable tables */ |
---|
| 448 | void (*free_terminal_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)); |
---|
| 449 | /* Called when freeing MTBDD terminals */ |
---|
| 450 | pointer free_terminal_env; /* Environment for free terminal function */ |
---|
| 451 | long entries; /* Total number of BDD nodes */ |
---|
| 452 | long gc_limit; /* Try garbage collection at this point */ |
---|
| 453 | long node_limit; /* Maximum number of BDD nodes allowed */ |
---|
| 454 | long gcs; /* Number of garbage collections */ |
---|
| 455 | long freed; /* Number of nodes freed */ |
---|
| 456 | long finds; /* Number of find operations */ |
---|
| 457 | }; |
---|
| 458 | |
---|
| 459 | typedef struct unique_ unique; |
---|
| 460 | |
---|
| 461 | |
---|
| 462 | /* Record manager size range stuff */ |
---|
| 463 | |
---|
| 464 | #define MIN_REC_SIZE ALLOC_ALIGNMENT |
---|
| 465 | #define MAX_REC_SIZE 64 |
---|
| 466 | |
---|
| 467 | #define REC_MGRS (((MAX_REC_SIZE-MIN_REC_SIZE)/ALLOC_ALIGNMENT)+1) |
---|
| 468 | |
---|
| 469 | |
---|
| 470 | /* Wrapper for jmp_buf since we may need to copy it sometimes and */ |
---|
| 471 | /* we can't easily do it if it happens to be an array. */ |
---|
| 472 | |
---|
| 473 | struct jump_buf_ |
---|
| 474 | { |
---|
| 475 | jmp_buf context; |
---|
| 476 | }; |
---|
| 477 | |
---|
| 478 | typedef struct jump_buf_ jump_buf; |
---|
| 479 | |
---|
| 480 | |
---|
| 481 | /* A BDD manager */ |
---|
| 482 | |
---|
| 483 | struct bdd_manager_ |
---|
| 484 | { |
---|
| 485 | unique unique_table; /* BDD node table */ |
---|
| 486 | cache op_cache; /* System result cache */ |
---|
| 487 | int check; /* Number of find calls 'til size checks */ |
---|
| 488 | bdd one; /* BDD for one */ |
---|
| 489 | bdd zero; /* BDD for zero */ |
---|
| 490 | int overflow; /* Nonzero if node limit exceeded */ |
---|
| 491 | void (*overflow_fn) ARGS((cmu_bdd_manager, pointer)); |
---|
| 492 | /* Function to call on overflow */ |
---|
| 493 | pointer overflow_env; /* Environment for overflow function */ |
---|
| 494 | void (*transform_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *, pointer)); |
---|
| 495 | /* Function to transform terminal values */ |
---|
| 496 | pointer transform_env; /* Environment for transform_fn */ |
---|
| 497 | int (*canonical_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)); |
---|
| 498 | /* Function to check if a terminal value is */ |
---|
| 499 | /* canonical */ |
---|
| 500 | block super_block; /* Top-level variable block */ |
---|
| 501 | void (*reorder_fn) ARGS((cmu_bdd_manager)); |
---|
| 502 | /* Function to call to reorder variables */ |
---|
| 503 | pointer reorder_data; /* For saving information btwn reorderings */ |
---|
| 504 | int allow_reordering; /* Nonzero if reordering allowed */ |
---|
| 505 | long nodes_at_start; /* Nodes at start of operation */ |
---|
| 506 | long vars; /* Number of variables */ |
---|
| 507 | long maxvars; /* Maximum number of variables w/o resize */ |
---|
| 508 | bdd *variables; /* Array of variables, by indexindex */ |
---|
| 509 | bdd_index_type *indexes; /* indexindex -> index table */ |
---|
| 510 | bdd_indexindex_type *indexindexes; |
---|
| 511 | /* index -> indexindex table */ |
---|
| 512 | int curr_assoc_id; /* Current variable association number */ |
---|
| 513 | var_assoc curr_assoc; /* Current variable association */ |
---|
| 514 | assoc_list assocs; /* Variable associations */ |
---|
| 515 | struct var_assoc_ temp_assoc; /* Temporary variable association */ |
---|
| 516 | rec_mgr rms[REC_MGRS]; /* Record managers */ |
---|
| 517 | long temp_op; /* Current temporary operation number */ |
---|
| 518 | jump_buf abort; /* Jump for out-of-memory cleanup */ |
---|
| 519 | void (*bag_it_fn) ARGS((cmu_bdd_manager, pointer)); |
---|
| 520 | /* Non-null if going to abort at next find */ |
---|
| 521 | pointer bag_it_env; char *hooks; /* Environment for bag it function */ |
---|
| 522 | }; |
---|
| 523 | |
---|
| 524 | |
---|
| 525 | /* Abort stuff */ |
---|
| 526 | |
---|
| 527 | #define BDD_ABORTED 1 |
---|
| 528 | #define BDD_OVERFLOWED 2 |
---|
| 529 | #define BDD_REORDERED 3 |
---|
| 530 | |
---|
| 531 | |
---|
| 532 | #define FIREWALL(bddm)\ |
---|
| 533 | do\ |
---|
| 534 | {\ |
---|
| 535 | int retcode;\ |
---|
| 536 | (bddm)->allow_reordering=1;\ |
---|
| 537 | (bddm)->nodes_at_start=(bddm)->unique_table.entries;\ |
---|
| 538 | while ((retcode=(setjmp((bddm)->abort.context))))\ |
---|
| 539 | {\ |
---|
| 540 | bdd_cleanup(bddm, retcode);\ |
---|
| 541 | if (retcode == BDD_ABORTED || retcode == BDD_OVERFLOWED)\ |
---|
| 542 | return ((bdd)0);\ |
---|
| 543 | (bddm)->nodes_at_start=(bddm)->unique_table.entries;\ |
---|
| 544 | }\ |
---|
| 545 | }\ |
---|
| 546 | while (0) |
---|
| 547 | |
---|
| 548 | |
---|
| 549 | #define FIREWALL1(bddm, cleanupcode)\ |
---|
| 550 | do\ |
---|
| 551 | {\ |
---|
| 552 | int retcode;\ |
---|
| 553 | (bddm)->allow_reordering=1;\ |
---|
| 554 | (bddm)->nodes_at_start=(bddm)->unique_table.entries;\ |
---|
| 555 | while ((retcode=(setjmp((bddm)->abort.context))))\ |
---|
| 556 | {\ |
---|
| 557 | bdd_cleanup(bddm, retcode);\ |
---|
| 558 | cleanupcode\ |
---|
| 559 | (bddm)->nodes_at_start=(bddm)->unique_table.entries;\ |
---|
| 560 | }\ |
---|
| 561 | }\ |
---|
| 562 | while (0) |
---|
| 563 | |
---|
| 564 | |
---|
| 565 | /* Node hash function */ |
---|
| 566 | |
---|
| 567 | #define HASH_NODE(f, g) (((f) << 1)+(g)) |
---|
| 568 | |
---|
| 569 | |
---|
| 570 | /* Table size stuff */ |
---|
| 571 | |
---|
| 572 | #if defined(POWER_OF_2_SIZES) |
---|
| 573 | #define TABLE_SIZE(size_index) (1l << (size_index)) |
---|
| 574 | #define BDD_REDUCE(i, size) (i)&=(size)-1 |
---|
| 575 | #else |
---|
| 576 | #define TABLE_SIZE(size_index) (bdd_primes[size_index]) |
---|
| 577 | #define BDD_REDUCE(i, size)\ |
---|
| 578 | do\ |
---|
| 579 | {\ |
---|
| 580 | (i)%=(size);\ |
---|
| 581 | if ((i) < 0)\ |
---|
| 582 | (i)= -(i);\ |
---|
| 583 | }\ |
---|
| 584 | while (0) |
---|
| 585 | #endif |
---|
| 586 | |
---|
| 587 | |
---|
| 588 | /* Record management */ |
---|
| 589 | |
---|
| 590 | #define BDD_NEW_REC(bddm, size) mem_new_rec((bddm)->rms[(ROUNDUP(size)-MIN_REC_SIZE)/ALLOC_ALIGNMENT]) |
---|
| 591 | #define BDD_FREE_REC(bddm, rec, size) mem_free_rec((bddm)->rms[(ROUNDUP(size)-MIN_REC_SIZE)/ALLOC_ALIGNMENT], (rec)) |
---|
| 592 | |
---|
| 593 | |
---|
| 594 | /* >>> Declarations for random routines */ |
---|
| 595 | |
---|
| 596 | /* Internal BDD routines */ |
---|
| 597 | |
---|
| 598 | extern int bdd_check_arguments ARGS((int, ...)); |
---|
| 599 | extern void bdd_check_array ARGS((bdd *)); |
---|
| 600 | extern bdd bdd_make_external ARGS((bdd)); |
---|
| 601 | extern int cmu_bdd_type_aux ARGS((cmu_bdd_manager, bdd)); |
---|
| 602 | extern int cmu_bdd_is_cube ARGS((cmu_bdd_manager, bdd)); |
---|
| 603 | extern void bdd_rehash_var_table ARGS((var_table, int)); |
---|
| 604 | extern bdd bdd_find_aux ARGS((cmu_bdd_manager, bdd_indexindex_type, INT_PTR, INT_PTR)); |
---|
| 605 | extern bdd cmu_bdd_ite_step ARGS((cmu_bdd_manager, bdd, bdd, bdd)); |
---|
| 606 | extern bdd cmu_bdd_exists_temp ARGS((cmu_bdd_manager, bdd, long)); |
---|
| 607 | extern bdd cmu_bdd_compose_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd)); |
---|
| 608 | extern bdd cmu_bdd_substitute_step ARGS((cmu_bdd_manager, bdd, long, bdd (*) ARGS((cmu_bdd_manager, bdd, bdd, bdd)), var_assoc)); |
---|
| 609 | extern bdd cmu_bdd_swap_vars_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd)); |
---|
| 610 | extern int cmu_bdd_compare_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd)); |
---|
| 611 | extern double cmu_bdd_satisfying_fraction_step ARGS((cmu_bdd_manager, bdd)); |
---|
| 612 | extern void bdd_mark_shared_nodes ARGS((cmu_bdd_manager, bdd)); |
---|
| 613 | extern void bdd_number_shared_nodes ARGS((cmu_bdd_manager, bdd, hash_table, long *)); |
---|
| 614 | extern char *bdd_terminal_id ARGS((cmu_bdd_manager, bdd, char *(*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)), pointer)); |
---|
| 615 | extern char *bdd_var_name ARGS((cmu_bdd_manager, bdd, char *(*) ARGS((cmu_bdd_manager, bdd, pointer)), pointer)); |
---|
| 616 | extern long bdd_find_block ARGS((block, long)); |
---|
| 617 | extern void bdd_block_delta ARGS((block, long)); |
---|
| 618 | extern void cmu_bdd_reorder_aux ARGS((cmu_bdd_manager)); |
---|
| 619 | extern void cmu_mtbdd_terminal_value_aux ARGS((cmu_bdd_manager, bdd, INT_PTR *, INT_PTR *)); |
---|
| 620 | |
---|
| 621 | |
---|
| 622 | /* System cache routines */ |
---|
| 623 | |
---|
| 624 | extern void bdd_insert_in_cache31 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR)); |
---|
| 625 | extern int bdd_lookup_in_cache31 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR *)); |
---|
| 626 | extern void bdd_insert_in_cache22 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR)); |
---|
| 627 | extern int bdd_lookup_in_cache22 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *)); |
---|
| 628 | extern void bdd_insert_in_cache13 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR)); |
---|
| 629 | extern int bdd_lookup_in_cache13 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR *, INT_PTR *, INT_PTR *)); |
---|
| 630 | extern void bdd_flush_cache ARGS((cmu_bdd_manager, int (*) ARGS((cmu_bdd_manager, cache_entry, pointer)), pointer)); |
---|
| 631 | extern void bdd_purge_cache ARGS((cmu_bdd_manager)); |
---|
| 632 | extern void bdd_flush_all ARGS((cmu_bdd_manager)); |
---|
| 633 | extern int bdd_cache_functions ARGS((cmu_bdd_manager, |
---|
| 634 | int, |
---|
| 635 | int (*) ARGS((cmu_bdd_manager, cache_entry)), |
---|
| 636 | void (*) ARGS((cmu_bdd_manager, cache_entry)), |
---|
| 637 | void (*) ARGS((cmu_bdd_manager,cache_entry)), |
---|
| 638 | int (*) ARGS((cmu_bdd_manager, cache_entry, pointer)))); |
---|
| 639 | extern void cmu_bdd_free_cache_tag ARGS((cmu_bdd_manager, long)); |
---|
| 640 | extern void bdd_rehash_cache ARGS((cmu_bdd_manager, int)); |
---|
| 641 | extern void cmu_bdd_init_cache ARGS((cmu_bdd_manager)); |
---|
| 642 | extern void cmu_bdd_free_cache ARGS((cmu_bdd_manager)); |
---|
| 643 | |
---|
| 644 | #define bdd_insert_in_cache2(bddm, op, f, g, result)\ |
---|
| 645 | bdd_insert_in_cache31((bddm), CACHE_TYPE_TWO, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR)(result)) |
---|
| 646 | #define bdd_lookup_in_cache2(bddm, op, f, g, result)\ |
---|
| 647 | bdd_lookup_in_cache31((bddm), CACHE_TYPE_TWO, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR *)(result)) |
---|
| 648 | |
---|
| 649 | #define bdd_insert_in_cache1(bddm, op, f, result)\ |
---|
| 650 | bdd_insert_in_cache2((bddm), (op), (f), BDD_ONE(bddm), (result)) |
---|
| 651 | #define bdd_lookup_in_cache1(bddm, op, f, result)\ |
---|
| 652 | bdd_lookup_in_cache2((bddm), (op), (f), BDD_ONE(bddm), (result)) |
---|
| 653 | |
---|
| 654 | #define bdd_insert_in_cache2d(bddm, op, f, g, result)\ |
---|
| 655 | bdd_insert_in_cache31((bddm), CACHE_TYPE_TWODATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR)(result)) |
---|
| 656 | #define bdd_lookup_in_cache2d(bddm, op, f, g, result)\ |
---|
| 657 | bdd_lookup_in_cache31((bddm), CACHE_TYPE_TWODATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR *)(result)) |
---|
| 658 | |
---|
| 659 | #define bdd_insert_in_cache1d(bddm, op, f, result1, result2)\ |
---|
| 660 | bdd_insert_in_cache22((bddm), CACHE_TYPE_ONEDATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(result1), (INT_PTR)(result2)) |
---|
| 661 | #define bdd_lookup_in_cache1d(bddm, op, f, result1, result2)\ |
---|
| 662 | bdd_lookup_in_cache22((bddm), CACHE_TYPE_ONEDATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR *)(result1), (INT_PTR *)(result2)) |
---|
| 663 | |
---|
| 664 | #define cache_return_fn_none ((void (*)(cmu_bdd_manager, cache_entry))0) |
---|
| 665 | #define cache_purge_fn_none ((void (*)(cmu_bdd_manager, cache_entry))0) |
---|
| 666 | #define cache_reclaim_fn_none ((int (*)(cmu_bdd_manager, cache_entry, pointer))0) |
---|
| 667 | |
---|
| 668 | |
---|
| 669 | /* Unique table routines */ |
---|
| 670 | |
---|
| 671 | extern void bdd_clear_temps ARGS((cmu_bdd_manager)); |
---|
| 672 | extern void bdd_sweep_var_table ARGS((cmu_bdd_manager, long, int)); |
---|
| 673 | extern void bdd_sweep ARGS((cmu_bdd_manager)); |
---|
| 674 | extern void bdd_cleanup ARGS((cmu_bdd_manager, int)); |
---|
| 675 | extern bdd bdd_find ARGS((cmu_bdd_manager, bdd_indexindex_type, bdd, bdd)); |
---|
| 676 | extern bdd bdd_find_terminal ARGS((cmu_bdd_manager, INT_PTR, INT_PTR)); |
---|
| 677 | extern var_table bdd_new_var_table ARGS((cmu_bdd_manager)); |
---|
| 678 | extern void cmu_bdd_init_unique ARGS((cmu_bdd_manager)); |
---|
| 679 | extern void cmu_bdd_free_unique ARGS((cmu_bdd_manager)); |
---|
| 680 | |
---|
| 681 | |
---|
| 682 | /* Error routines */ |
---|
| 683 | |
---|
| 684 | extern void cmu_bdd_fatal ARGS((char *)); |
---|
| 685 | extern void cmu_bdd_warning ARGS((char *)); |
---|
| 686 | |
---|
| 687 | |
---|
| 688 | /* >>> Hash table declarations */ |
---|
| 689 | |
---|
| 690 | struct hash_rec_ |
---|
| 691 | { |
---|
| 692 | bdd key; |
---|
| 693 | struct hash_rec_ *next; |
---|
| 694 | }; |
---|
| 695 | |
---|
| 696 | typedef struct hash_rec_ *hash_rec; |
---|
| 697 | |
---|
| 698 | |
---|
| 699 | struct hash_table_ |
---|
| 700 | { |
---|
| 701 | hash_rec *table; |
---|
| 702 | int size_index; |
---|
| 703 | long size; |
---|
| 704 | long entries; |
---|
| 705 | int item_size; |
---|
| 706 | cmu_bdd_manager bddm; |
---|
| 707 | }; |
---|
| 708 | |
---|
| 709 | |
---|
| 710 | /* Hash table routines */ |
---|
| 711 | |
---|
| 712 | extern void bdd_insert_in_hash_table ARGS((hash_table, bdd, pointer)); |
---|
| 713 | extern pointer bdd_lookup_in_hash_table ARGS((hash_table, bdd)); |
---|
| 714 | extern hash_table bdd_new_hash_table ARGS((cmu_bdd_manager, int)); |
---|
| 715 | extern void cmu_bdd_free_hash_table ARGS((hash_table)); |
---|
| 716 | |
---|
| 717 | |
---|
| 718 | #undef ARGS |
---|
| 719 | |
---|
| 720 | #endif |
---|