/** * Calculate dst = dst + src */ static void set_union(vset_t dst, vset_t src) { LACE_ME; BDD old = dst->bdd; dst->bdd = sylvan_ref(sylvan_or(dst->bdd, src->bdd)); sylvan_deref(old); }
/** * Add all elements of src to dst and remove all elements that were in dst already from src * in other words: newDst = dst + src * newSrc = src - dst */ static void set_zip(vset_t dst, vset_t src) { LACE_ME; BDD tmp1 = dst->bdd; BDD tmp2 = src->bdd; dst->bdd = sylvan_ref(sylvan_or(tmp1, tmp2)); src->bdd = sylvan_ref(sylvan_diff(tmp2, tmp1)); sylvan_deref(tmp1); sylvan_deref(tmp2); }
/** * Adds e to set */ static void set_add(vset_t set, const int* e) { LACE_ME; // For some reason, we never get projected e, we get full e. BDD bdd = state_to_bdd(e, set->dom->shared.size, set->dom->vec_to_bddvar, set->projection); BDD prev = set->bdd; set->bdd = sylvan_ref(sylvan_or(prev, bdd)); sylvan_deref(bdd); sylvan_deref(prev); }
/** * Add (src, dst) to the relation * Note that src and dst are PROJECTED (small) vectors! */ static void rel_add(vrel_t rel, const int *src, const int *dst) { LACE_ME; BDD bdd_src = state_to_bdd(src, rel->vector_size, rel->vec_to_bddvar, sylvan_false); BDD bdd_dst = state_to_bdd(dst, rel->vector_size, rel->prime_vec_to_bddvar, sylvan_false); BDD part = sylvan_ref(sylvan_and(bdd_src, bdd_dst)); sylvan_deref(bdd_src); sylvan_deref(bdd_dst); BDD old = rel->bdd; rel->bdd = sylvan_ref(sylvan_or(rel->bdd, part)); sylvan_deref(old); sylvan_deref(part); }
TASK_3(MTBDD, bdd_from_ldd, MDD, dd, MDD, bits_dd, uint32_t, firstvar) { /* simple for leaves */ if (dd == lddmc_false) return mtbdd_false; if (dd == lddmc_true) return mtbdd_true; MTBDD result; /* get from cache */ /* note: some assumptions about the encoding... */ if (cache_get3(bdd_from_ldd_id, dd, bits_dd, firstvar, &result)) return result; mddnode_t n = LDD_GETNODE(dd); mddnode_t nbits = LDD_GETNODE(bits_dd); int bits = (int)mddnode_getvalue(nbits); /* spawn right, same bits_dd and firstvar */ mtbdd_refs_spawn(SPAWN(bdd_from_ldd, mddnode_getright(n), bits_dd, firstvar)); /* call down, with next bits_dd and firstvar */ MTBDD down = CALL(bdd_from_ldd, mddnode_getdown(n), mddnode_getdown(nbits), firstvar + 2*bits); /* encode current value */ uint32_t val = mddnode_getvalue(n); for (int i=0; i<bits; i++) { /* encode with high bit first */ int bit = bits-i-1; if (val & (1LL<<i)) down = mtbdd_makenode(firstvar + 2*bit, mtbdd_false, down); else down = mtbdd_makenode(firstvar + 2*bit, down, mtbdd_false); } /* sync right */ mtbdd_refs_push(down); MTBDD right = mtbdd_refs_sync(SYNC(bdd_from_ldd)); /* take union of current and right */ mtbdd_refs_push(right); result = sylvan_or(down, right); mtbdd_refs_pop(2); /* put in cache */ cache_put3(bdd_from_ldd_id, dd, bits_dd, firstvar, result); return result; }
JNIEXPORT jlong JNICALL Java_jsylvan_JSylvan_makeOr(JNIEnv *env, jclass cl, jlong a, jlong b) { LACE_ME; return sylvan_or(a, b); }
TASK_4(MTBDD, bdd_from_ldd_rel, MDD, dd, MDD, bits_dd, uint32_t, firstvar, MDD, meta) { if (dd == lddmc_false) return mtbdd_false; if (dd == lddmc_true) return mtbdd_true; assert(meta != lddmc_false && meta != lddmc_true); /* meta: * -1 is end * 0 is skip * 1 is read * 2 is write * 3 is only-read * 4 is only-write */ MTBDD result; /* note: assumptions */ if (cache_get4(bdd_from_ldd_rel_id, dd, bits_dd, firstvar, meta, &result)) return result; const mddnode_t n = LDD_GETNODE(dd); const mddnode_t nmeta = LDD_GETNODE(meta); const mddnode_t nbits = LDD_GETNODE(bits_dd); const int bits = (int)mddnode_getvalue(nbits); const uint32_t vmeta = mddnode_getvalue(nmeta); assert(vmeta != (uint32_t)-1); if (vmeta == 0) { /* skip level */ result = bdd_from_ldd_rel(dd, mddnode_getdown(nbits), firstvar + 2*bits, mddnode_getdown(nmeta)); } else if (vmeta == 1) { /* read level */ assert(!mddnode_getcopy(n)); // do not process read copy nodes for now assert(mddnode_getright(n) != mtbdd_true); /* spawn right */ mtbdd_refs_spawn(SPAWN(bdd_from_ldd_rel, mddnode_getright(n), bits_dd, firstvar, meta)); /* compute down with same bits / firstvar */ MTBDD down = bdd_from_ldd_rel(mddnode_getdown(n), bits_dd, firstvar, mddnode_getdown(nmeta)); mtbdd_refs_push(down); /* encode read value */ uint32_t val = mddnode_getvalue(n); MTBDD part = mtbdd_true; for (int i=0; i<bits; i++) { /* encode with high bit first */ int bit = bits-i-1; if (val & (1LL<<i)) part = mtbdd_makenode(firstvar + 2*bit, mtbdd_false, part); else part = mtbdd_makenode(firstvar + 2*bit, part, mtbdd_false); } /* intersect read value with down result */ mtbdd_refs_push(part); down = sylvan_and(part, down); mtbdd_refs_pop(2); /* sync right */ mtbdd_refs_push(down); MTBDD right = mtbdd_refs_sync(SYNC(bdd_from_ldd_rel)); /* take union of current and right */ mtbdd_refs_push(right); result = sylvan_or(down, right); mtbdd_refs_pop(2); } else if (vmeta == 2 || vmeta == 4) { /* write or only-write level */ /* spawn right */ assert(mddnode_getright(n) != mtbdd_true); mtbdd_refs_spawn(SPAWN(bdd_from_ldd_rel, mddnode_getright(n), bits_dd, firstvar, meta)); /* get recursive result */ MTBDD down = CALL(bdd_from_ldd_rel, mddnode_getdown(n), mddnode_getdown(nbits), firstvar + 2*bits, mddnode_getdown(nmeta)); if (mddnode_getcopy(n)) { /* encode a copy node */ for (int i=0; i<bits; i++) { int bit = bits-i-1; MTBDD low = mtbdd_makenode(firstvar + 2*bit + 1, down, mtbdd_false); mtbdd_refs_push(low); MTBDD high = mtbdd_makenode(firstvar + 2*bit + 1, mtbdd_false, down); mtbdd_refs_pop(1); down = mtbdd_makenode(firstvar + 2*bit, low, high); } } else { /* encode written value */ uint32_t val = mddnode_getvalue(n); for (int i=0; i<bits; i++) { /* encode with high bit first */ int bit = bits-i-1; if (val & (1LL<<i)) down = mtbdd_makenode(firstvar + 2*bit + 1, mtbdd_false, down); else down = mtbdd_makenode(firstvar + 2*bit + 1, down, mtbdd_false); } } /* sync right */ mtbdd_refs_push(down); MTBDD right = mtbdd_refs_sync(SYNC(bdd_from_ldd_rel)); /* take union of current and right */ mtbdd_refs_push(right); result = sylvan_or(down, right); mtbdd_refs_pop(2); } else if (vmeta == 3) { /* only-read level */ assert(!mddnode_getcopy(n)); // do not process read copy nodes /* spawn right */ mtbdd_refs_spawn(SPAWN(bdd_from_ldd_rel, mddnode_getright(n), bits_dd, firstvar, meta)); /* get recursive result */ MTBDD down = CALL(bdd_from_ldd_rel, mddnode_getdown(n), mddnode_getdown(nbits), firstvar + 2*bits, mddnode_getdown(nmeta)); /* encode read value */ uint32_t val = mddnode_getvalue(n); for (int i=0; i<bits; i++) { /* encode with high bit first */ int bit = bits-i-1; /* only-read, so write same value */ if (val & (1LL<<i)) down = mtbdd_makenode(firstvar + 2*bit + 1, mtbdd_false, down); else down = mtbdd_makenode(firstvar + 2*bit + 1, down, mtbdd_false); if (val & (1LL<<i)) down = mtbdd_makenode(firstvar + 2*bit, mtbdd_false, down); else down = mtbdd_makenode(firstvar + 2*bit, down, mtbdd_false); } /* sync right */ mtbdd_refs_push(down); MTBDD right = mtbdd_refs_sync(SYNC(bdd_from_ldd_rel)); /* take union of current and right */ mtbdd_refs_push(right); result = sylvan_or(down, right); mtbdd_refs_pop(2); } else if (vmeta == 5) { assert(!mddnode_getcopy(n)); // not allowed! /* we assume this is the last value */ result = mtbdd_true; /* encode action value */ uint32_t val = mddnode_getvalue(n); for (int i=0; i<actionbits; i++) { /* encode with high bit first */ int bit = actionbits-i-1; /* only-read, so write same value */ if (val & (1LL<<i)) result = mtbdd_makenode(1000000 + bit, mtbdd_false, result); else result = mtbdd_makenode(1000000 + bit, result, mtbdd_false); } } else { assert(vmeta <= 5); } cache_put4(bdd_from_ldd_rel_id, dd, bits_dd, firstvar, meta, result); return result; }