static void set_copy_match(vset_t dst, vset_t src, int p_len, int* proj, int*match) { LACE_ME; // Create bdd of "match" // Assumption: proj is ordered (if not, you get bad performance) sylvan_deref(dst->bdd); sylvan_gc_disable(); BDD match_bdd = sylvan_true; for (int i=p_len;i-->0;) { uint32_t b = match[i]; for (int j=fddbits;j-->0;) { BDD val = sylvan_ithvar(src->dom->vec_to_bddvar[proj[i]*fddbits+j]); if (!(b&1)) val = sylvan_not(val); match_bdd = sylvan_and(val, match_bdd); b >>= 1; } } sylvan_ref(match_bdd); sylvan_gc_enable(); dst->bdd = sylvan_ref(sylvan_and(match_bdd, src->bdd)); sylvan_deref(match_bdd); }
/** * Enumerate all states that match partial state <match> * <match> is p_len long * <proj> is a list of integers, containing indices of each match integer */ static void set_enum_match(vset_t set, int p_len, int* proj, int* match, vset_element_cb cb, void* context) { LACE_ME; // Create bdd of "match" // Assumption: proj is ordered (if not, you get bad performance) sylvan_gc_disable(); BDD match_bdd = sylvan_true; for (int i=p_len;i-->0;) { uint32_t b = match[i]; for (int j=fddbits;j-->0;) { BDD val = sylvan_ithvar(set->dom->vec_to_bddvar[proj[i]*fddbits+j]); if (!(b&1)) val = sylvan_not(val); match_bdd = sylvan_and(val, match_bdd); b >>= 1; } } sylvan_ref(match_bdd); sylvan_gc_enable(); BDD old = match_bdd; match_bdd = sylvan_ref(sylvan_and(match_bdd, set->bdd)); sylvan_deref(old); int vec[set->vector_size]; memset(vec, 0, sizeof(int)*set->vector_size); set_enum_do(match_bdd, set->variables, vec, 0, cb, context); sylvan_deref(match_bdd); }
/** * Calculate dst = dst /\ src */ static void set_intersect(vset_t dst, vset_t src) { LACE_ME; BDD old = dst->bdd; dst->bdd = sylvan_ref(sylvan_and(dst->bdd, src->bdd)); sylvan_deref(old); }
/** * Returns 1 if e is a member of set, 0 otherwise */ static int set_member(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); int res = sylvan_and(set->bdd, bdd) != sylvan_false ? 1 : 0; sylvan_deref(bdd); return res; }
/** * 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); }
JNIEXPORT jlong JNICALL Java_jsylvan_JSylvan_makeAnd(JNIEnv *env, jclass cl, jlong a, jlong b) { LACE_ME; return sylvan_and(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; }