/* Only call this when removing r from unique table */ void shadow_deref(shadow_mgr mgr, ref_t r) { if (!mgr->do_cudd) return; DdNode *n = get_ddnode(mgr, r); dd_type_t dtype = find_type(mgr, r); #if RPT >= 5 char buf[24]; shadow_show(mgr, r, buf); report(5, "Deleting reference %s for node %p", buf, n); #endif unreference_dd(mgr, n, dtype); if (!do_ref(mgr)) return; keyvalue_remove(mgr->c2r_table, (word_t ) n, NULL, NULL); keyvalue_remove(mgr->r2c_table, (word_t ) r, NULL, NULL); if (dtype == IS_BDD) { ref_t nr = shadow_negate(mgr, r); DdNode *nn = get_ddnode(mgr, nr); #if RPT >= 5 shadow_show(mgr, nr, buf); report(5, "Deleting reference %s for node %p", buf, nn); #endif keyvalue_remove(mgr->c2r_table, (word_t ) nn, NULL, NULL); keyvalue_remove(mgr->r2c_table, (word_t ) nr, NULL, NULL); unreference_dd(mgr, nn, IS_BDD); } }
ref_t shadow_new_variable(shadow_mgr mgr) { ref_t r = REF_INVALID; DdNode *n = NULL; if (mgr->do_cudd) { n = Cudd_bddNewVar(mgr->bdd_manager); reference_dd(mgr, n); } if (mgr->do_local) { r = ref_new_variable(mgr->ref_mgr); } if (mgr->do_dist) { ref_t rdist = dist_var(mgr->ref_mgr); if (mgr->do_local) { if (!check_refs(mgr, r, rdist)) return REF_INVALID; } else r = rdist; } if (!mgr->do_cudd) n = ref2dd(mgr, r); if (!do_ref(mgr)) r = dd2ref(n, IS_BDD); add_ref(mgr, r, n); mgr->nvars++; return r; }
ref_t shadow_one(shadow_mgr mgr) { if (do_ref(mgr)) return REF_ONE; else { DdNode *n = Cudd_ReadOne(mgr->bdd_manager); reference_dd(mgr, n); return dd2ref(n, IS_BDD); } }
void shadow_show(shadow_mgr mgr, ref_t r, char *buf) { if (do_ref(mgr)) { ref_show(r, buf); } else { dd_type_t dtype = find_type(mgr, r); DdNode *n = ref2dd(mgr, r); sprintf(buf, "%c%p", dtype == IS_ZDD ? 'Z' : dtype == IS_ADD ? 'A' : 'B', n); } }
ref_t shadow_zero(shadow_mgr mgr) { if (do_ref(mgr)) return REF_ZERO; else { DdNode * n = Cudd_ReadLogicZero(mgr->bdd_manager); reference_dd(mgr, n); return dd2ref(n, IS_BDD); } }
void free_shadow_mgr(shadow_mgr mgr) { if (mgr->do_cudd) { Cudd_Quit(mgr->bdd_manager); } if (do_ref(mgr)) free_ref_mgr(mgr->ref_mgr); keyvalue_free(mgr->c2r_table); keyvalue_free(mgr->r2c_table); free_block((void *) mgr, sizeof(shadow_ele)); }
ref_t shadow_absval(shadow_mgr mgr, ref_t r) { if (do_ref(mgr)) return REF_ABSVAL(r); else { dd_type_t dtype = find_type(mgr, r); DdNode *n = ref2dd(mgr, r); DdNode *an = Cudd_Regular(n); return dd2ref(an, dtype); } }
static dd_type_t find_type(shadow_mgr mgr, ref_t r) { if (do_ref(mgr)) return IS_BDD; int suffix = r & 0x3; switch (suffix) { case 0: case 1: return IS_BDD; case 2: return IS_ZDD; case 3: return IS_ADD; } return IS_BDD; }
/* ADD conversion for external command */ ref_t shadow_aconvert(shadow_mgr mgr, ref_t r) { if (do_ref(mgr)) /* Only applies when in pure CUDD mode */ return r; DdNode *n = get_ddnode(mgr, r); if (is_add(mgr, r)) { return r; } if (is_zdd(mgr, r)) { err(false, "Can't convert ADD to ZDD"); return REF_INVALID; } DdNode *an = aconvert(mgr, n); ref_t ar = dd2ref(an, IS_ADD); add_ref(mgr, ar, an); return ar; }
/* ZDD conversion for external command */ ref_t shadow_zconvert(shadow_mgr mgr, ref_t r) { if (do_ref(mgr)) /* Only applies when in pure CUDD mode */ return r; DdNode *n = get_ddnode(mgr, r); if (is_zdd(mgr, r)) { return r; } if (is_add(mgr, r)) { err(false, "Can't convert ADD to ZDD"); return REF_INVALID; } DdNode *zn = zconvert(mgr, n); ref_t zr = dd2ref(zn, IS_ZDD); add_ref(mgr, zr, zn); return zr; }
/* General conversion from ref to dd */ static DdNode *get_ddnode(shadow_mgr mgr, ref_t r) { DdNode *n; if (!do_ref(mgr)) { n = ref2dd(mgr, r); } else if (REF_IS_INVALID(r)) { err(fatal, "No node associated with invalid ref"); n = Cudd_ReadLogicZero(mgr->bdd_manager); reference_dd(mgr, n); } else if (!keyvalue_find(mgr->r2c_table, (word_t ) r, (word_t *) &n)) { char buf[24]; shadow_show(mgr, r, buf); err(fatal, "No node associated with ref %s (0x%llx)", buf, r); n = mgr->do_cudd ? Cudd_ReadLogicZero(mgr->bdd_manager) : (DdNode *) REF_ZERO; reference_dd(mgr, n); } return n; }
ref_t shadow_get_variable(shadow_mgr mgr, size_t index) { if (index >= mgr->nvars) { err(fatal, "Invalid variable index %lu", index); index = 0; } ref_t r = 0; DdNode *n = NULL; if (mgr->do_cudd) { n = Cudd_bddIthVar(mgr->bdd_manager, index); reference_dd(mgr, n); } if (do_ref(mgr)) { r = REF_VAR(index); if (!mgr->do_cudd) n = ref2dd(mgr, r); } else { r = dd2ref(n, IS_BDD); } add_ref(mgr, r, n); return r; }
/* Compute negation. Creates CUDD reference. For ZDDs, records as reference */ ref_t shadow_negate(shadow_mgr mgr, ref_t a) { ref_t r = REF_INVALID; if (REF_IS_INVALID(a)) return a; if (do_ref(mgr)) r = REF_NEGATE(a); else { DdNode *an = get_ddnode(mgr, a); if (is_zdd(mgr, a)) { DdNode *zone = Cudd_ReadZddOne(mgr->bdd_manager, 0); reference_dd(mgr, zone); DdNode *ann = Cudd_zddDiff(mgr->bdd_manager, zone, an); reference_dd(mgr, ann); unreference_dd(mgr, zone, IS_ZDD); r = dd2ref(ann, IS_ZDD); // For ZDDs, don't already have negated values recorded add_ref(mgr, r, ann); } else if (is_add(mgr, a)) { DdNode *ann = Cudd_addCmpl(mgr->bdd_manager, an); reference_dd(mgr, ann); r = dd2ref(ann, IS_ADD); // For ADDs, don't already have negated values recorded add_ref(mgr, r, ann); } else { DdNode *ann = Cudd_Not(an); reference_dd(mgr, ann); r = dd2ref(ann, IS_BDD); } } #if RPT >= 5 char buf[24], nbuf[24]; shadow_show(mgr, a, buf); shadow_show(mgr, r, nbuf); report(5, "Negated %s to get %s", buf, nbuf); #endif return r; }
void do_oop(objectRef* p) { assert0(objectRef::is_null_or_heap(p)); do_ref((heapRef*)p); }
/* Associate n with reference r. For non-Zdd/Add's, also cross reference complements. Incoming n has recorded reference count. Create single reference to node. For non-ZDD/ADD, create single reference to its complement */ static void add_ref(shadow_mgr mgr, ref_t r, DdNode *n) { ref_t rother; DdNode *nother; if (do_ref(mgr) && REF_IS_INVALID(r)) { /* Don't record matches with invalid refs */ return; } if (!do_ref(mgr)) return; dd_type_t dtype = find_type(mgr, r); bool rother_found = keyvalue_find(mgr->c2r_table, (word_t ) n, (word_t *) &rother); bool nother_found = keyvalue_find(mgr->r2c_table, (word_t ) r, (word_t *) ¬her); char buf1[24]; char buf2[24]; /* See if already found entry */ if (rother_found) { if (nother_found) { /* Already exists. Check if match */ if (nother == n && rother == r) { // Remove reference unreference_dd(mgr, n, dtype); } else { shadow_show(mgr, r, buf1); shadow_show(mgr, rother, buf2); err(fatal, "Inconsistency. New node 0x%p. Old node 0x%p. New ref %s. Old ref %s", n, nother, buf1, buf2); } } else { if (find_type(mgr, rother) == dtype) { shadow_show(mgr, r, buf1); shadow_show(mgr, rother, buf2); err(fatal, "Ref Collision. Refs %s and %s map to BDD node %p", buf1, buf2, n); } } } else { if (nother_found) { shadow_show(mgr, r, buf1); err(fatal, "Node collision. Nodes 0x%p and 0x%p map to ref %s\n", n, nother, buf1); } else { /* Normal case. Create both entries */ #if RPT >= 5 char buf[24]; shadow_show(mgr, r, buf); report(5, "Added ref %s for node %p", buf, n); #endif keyvalue_insert(mgr->c2r_table, (word_t ) n, (word_t ) r); keyvalue_insert(mgr->r2c_table, (word_t ) r, (word_t ) n); if (dtype == IS_BDD) { /* Create entries for negations */ ref_t rn = shadow_negate(mgr, r); // Creates reference DdNode *nn; if (mgr->do_cudd) { nn = Cudd_Not(n); } else { nn = ref2dd(mgr, rn); } #if RPT >= 5 shadow_show(mgr, rn, buf); report(5, "Added ref %s for node %p", buf, nn); #endif keyvalue_insert(mgr->c2r_table, (word_t ) nn, (word_t ) rn); keyvalue_insert(mgr->r2c_table, (word_t ) rn, (word_t ) nn); } } } }
shadow_mgr new_shadow_mgr(bool do_cudd, bool do_local, bool do_dist, chaining_t chaining) { if (!(do_cudd || do_local || do_dist)) { err(true, "Must have at least one active evaluation mode"); } shadow_mgr mgr = (shadow_mgr) malloc_or_fail(sizeof(shadow_ele), "new_shadow_mgr"); mgr->do_cudd = do_cudd; mgr->do_local = do_local; mgr->do_dist = do_dist; mgr->c2r_table = word_keyvalue_new(); mgr->r2c_table = word_keyvalue_new(); mgr->nvars = 0; mgr->nzvars = 0; ref_t r = REF_ZERO; DdNode *n = NULL; if (do_cudd) { /* Modified CUDD Parameters */ unsigned int numVars = 0; /* Default 0 */ unsigned int numVarsZ = 0; /* Default 0 */ unsigned int numSlots = 1u<<18; /* Default 256 */ unsigned int cacheSize = 1u<<22; /* Default 262144 */ /* Default 67,108,864 */ unsigned long int maxMemory = (1u<<31) + 32UL * 1024 * 1024 * 1024; #if 0 // Use defaults numSlots = 256; cacheSize = 262144; maxMemory = 67108864; #endif mgr->bdd_manager = Cudd_Init(numVars, numVarsZ, numSlots, cacheSize, maxMemory); Cudd_AutodynDisable(mgr->bdd_manager); Cudd_AutodynDisableZdd(mgr->bdd_manager); #ifndef NO_CHAINING Cudd_ChainingType ct = CUDD_CHAIN_NONE; switch (chaining) { case CHAIN_NONE: ct = CUDD_CHAIN_NONE; report(0, "No chaining enabled"); break; case CHAIN_CONSTANT: ct = CUDD_CHAIN_CONSTANT; report(0, "Constant chaining enabled"); break; case CHAIN_ALL: ct = CUDD_CHAIN_ALL; report(0, "Or chaining enabled"); break; default: err(true, "Invalid chaining mode %d\n", chaining); } Cudd_SetChaining(mgr->bdd_manager, ct); #endif n = Cudd_ReadLogicZero(mgr->bdd_manager); report(0, "Using CUDD Version %s", CUDD_VERSION); } if (do_ref(mgr)) { mgr->ref_mgr = new_ref_mgr(); if (!do_cudd) { n = ref2dd(mgr, r); } } else { r = dd2ref(n, IS_BDD); } reference_dd(mgr, n); add_ref(mgr, r, n); return mgr; }
ref_t shadow_ite(shadow_mgr mgr, ref_t iref, ref_t tref, ref_t eref) { DdNode *in = get_ddnode(mgr, iref); DdNode *tn = get_ddnode(mgr, tref); DdNode *en = get_ddnode(mgr, eref); DdNode *n = NULL; ref_t r = REF_INVALID; dd_type_t dtype = IS_BDD; if (mgr->do_local) { r = ref_ite(mgr->ref_mgr, iref, tref, eref); } if (mgr->do_dist) { ref_t rdist = dist_ite(mgr->ref_mgr, iref, tref, eref); if (mgr->do_local) { if (!check_refs(mgr, r, rdist)) { return REF_INVALID; } } else { r = rdist; } } if (mgr->do_cudd) { if (mgr->nzvars > 0) { bool zi = is_zdd(mgr, iref); bool zt = is_zdd(mgr, tref); bool ze = is_zdd(mgr, eref); if (zi || zt || ze) { dtype = IS_ZDD; if (is_add(mgr, iref) || is_add(mgr, tref) || is_add(mgr, eref)) { err(false, "Can't mix ADDs with ZDDs"); } if (!zi) { in = zconvert(mgr, in); } if (!zt) { tn = zconvert(mgr, tn); } if (!ze) { en = zconvert(mgr, en); } n = Cudd_zddIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); if (!zi) unreference_dd(mgr, in, IS_ZDD); if (!zt) unreference_dd(mgr, tn, IS_ZDD); if (!ze) unreference_dd(mgr, en, IS_ZDD); } } { bool ai = is_add(mgr, iref); bool at = is_add(mgr, tref); bool ae = is_add(mgr, eref); if (ai || at || ae) { dtype = IS_ADD; if (!ai) { in = aconvert(mgr, in); } if (!at) { tn = aconvert(mgr, tn); } if (!ae) { en = aconvert(mgr, en); } n = Cudd_addIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); if (!ai) unreference_dd(mgr, in, IS_ADD); if (!at) unreference_dd(mgr, tn, IS_ADD); if (!ae) unreference_dd(mgr, en, IS_ADD); } } if (dtype == IS_BDD) { n = Cudd_bddIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); } } else { n = ref2dd(mgr, r); } if (!do_ref(mgr)) r = dd2ref(n, dtype); add_ref(mgr, r, n); return r; }