/* NAME {* bdd\_extvarnum *} SECTION {* kernel *} SHORT {* add extra BDD variables *} PROTO {* int bdd_extvarnum(int num) *} DESCR {* Extends the current number of allocated BDD variables with {\tt num} extra variables. *} RETURN {* The old number of allocated variables or a negative error code. *} ALSO {* bdd\_setvarnum, bdd\_ithvar, bdd\_nithvar *} */ int bdd_extvarnum(int num) { int start = bddvarnum; BUDDY_PROLOGUE; ADD_ARG1(T_INT,num); if (num < 0 || num > 0x3FFFFFFF) RETURN(bdd_error(BDD_RANGE)); bdd_setvarnum(bddvarnum+num); RETURN(start); }
int bdd_load(FILE *ifile, BDD *root) { int n, vnum, tmproot; if (fscanf(ifile, "%d %d", &lh_nodenum, &vnum) != 2) return bdd_error(BDD_FORMAT); /* Check for constant true / false */ if (lh_nodenum==0 && vnum==0) { fscanf(ifile, "%d", root); return 0; } if ((loadvar2level=(int*)malloc(sizeof(int)*vnum)) == NULL) return bdd_error(BDD_MEMORY); for (n=0 ; n<vnum ; n++) fscanf(ifile, "%d", &loadvar2level[n]); if (vnum > bddvarnum) bdd_setvarnum(vnum); if ((lh_table=(LoadHash*)malloc(lh_nodenum*sizeof(LoadHash))) == NULL) return bdd_error(BDD_MEMORY); for (n=0 ; n<lh_nodenum ; n++) { lh_table[n].first = -1; lh_table[n].next = n+1; } lh_table[lh_nodenum-1].next = -1; lh_freepos = 0; tmproot = bdd_loaddata(ifile); for (n=0 ; n<lh_nodenum ; n++) bdd_delref(lh_table[n].data); free(lh_table); free(loadvar2level); *root = 0; if (tmproot < 0) return tmproot; else *root = tmproot; return 0; }
bool xo_equivalence_checker_bdd_programs_equivalent(const xo_program *prog1, const xo_program *prog2) { xo_register_set ro_set_1, ro_set_2; xo_program_analyze(prog1, NULL, &ro_set_1); xo_program_analyze(prog2, NULL, &ro_set_2); if(ro_set_1 != ro_set_2) return false; bdd_init(1000000, 100000); // TODO: good values? bdd_setvarnum(XO_NUM_REGISTERS*XO_NUM_BITS); bdd r[2][XO_NUM_REGISTERS][XO_NUM_BITS], f[2][XO_NUM_FLAGS]; int index = 0; for(int bi = 0; bi < XO_NUM_BITS; ++bi) for(int ri = 0; ri < XO_NUM_REGISTERS; ++ri) r[0][ri][bi] = r[1][ri][bi] = bdd_ithvar(index++); bdd_from_flag_set_(f[0], 0); bdd_from_flag_set_(f[1], 0); evaluate_program_(prog1, r[0], f[0]); evaluate_program_(prog2, r[1], f[1]); size_t ro_index = xo_register_set_first_live_index(ro_set_1); bool equiv = true; for(size_t i = 0; i < XO_NUM_BITS; ++i) { if(r[0][ro_index][i] != r[1][ro_index][i]) { equiv = false; break; } } bdd_done(); return equiv; }
/* ML type: int -> unit */ EXTERNML value mlbdd_bdd_setvarnum(value n) /* ML */ { bdd_setvarnum(Int_val(n)); return Val_unit; }
/* NAME {* fdd\_extdomain *} SECTION {* fdd *} SHORT {* adds another set of finite domain blocks *} PROTO {* int fdd_extdomain(int *dom, int num) *} DESCR {* Extends the set of finite domain blocks with the {\tt num} domains in {\tt dom}. Each entry in {\tt dom} defines the size of a new finite domain which later on can be used for finite state machine traversal and other operations on finte domains. Each domain allocates $\log_2(|dom[i]|)$ BDD variables to be used later. The ordering is interleaved for the domains defined in each call to {\tt bdd\_extdomain}. This means that assuming domain $D_0$ needs 2 BDD variables $x_1$ and $x_2$, and another domain $D_1$ needs 4 BDD variables $y_1,y_2,y_3$ and $y_4$, then the order will be $x_1,y_1,x_2,y_2,y_3,y_4$. The index of the first domain in {\tt dom} is returned. The index of the other domains are offset from this index with the same offset as in {\tt dom}. The BDD variables needed to encode the domain are created for the purpose and do not interfere with the BDD variables already in use. *} RETURN {* The index of the first domain or a negative error code. *} ALSO {* fdd\_ithvar, fdd\_equals, fdd\_overlapdomain *} */ int fdd_extdomain(int *dom, int num) { int offset = fdvarnum; int binoffset; int extravars = 0; int n, bn, more; if (!bddrunning) return bdd_error(BDD_RUNNING); /* Build domain table */ if (domain == NULL) /* First time */ { fdvaralloc = num; if ((domain=(Domain*)malloc(sizeof(Domain)*num)) == NULL) return bdd_error(BDD_MEMORY); } else /* Allocated before */ { if (fdvarnum + num > fdvaralloc) { fdvaralloc += (num > fdvaralloc) ? num : fdvaralloc; { Domain* tmp_ptr = (Domain*)realloc(domain, sizeof(Domain)*fdvaralloc); if (tmp_ptr == NULL) return bdd_error(BDD_MEMORY); domain = tmp_ptr; } } } /* Create bdd variable tables */ for (n=0 ; n<num ; n++) { Domain_allocate(&domain[n+fdvarnum], dom[n]); extravars += domain[n+fdvarnum].binsize; } binoffset = firstbddvar; if (firstbddvar + extravars > bddvarnum) bdd_setvarnum(firstbddvar + extravars); /* Set correct variable sequence (interleaved) */ for (bn=0,more=1 ; more ; bn++) { more = 0; for (n=0 ; n<num ; n++) if (bn < domain[n+fdvarnum].binsize) { more = 1; domain[n+fdvarnum].ivar[bn] = binoffset++; } } for (n=0 ; n<num ; n++) { domain[n+fdvarnum].var = bdd_makeset(domain[n+fdvarnum].ivar, domain[n+fdvarnum].binsize); bdd_addref(domain[n+fdvarnum].var); } fdvarnum += num; firstbddvar += extravars; return offset; }
int main(int argc, char** argv) { bdd *c, *cp, *h, *hp, *t, *tp; bdd I, T, R; int n; if(argc < 2) { printf("usage: %s N\n",argv[0]); printf("\tN number of cyclers\n"); exit(1); } N = atoi(argv[1]); if (N <= 0) { printf("The number of cyclers must more than zero\n"); exit(2); } bdd_init(100000, 10000); bdd_setvarnum(N*6); c = (bdd *)malloc(sizeof(bdd)*N); cp = (bdd *)malloc(sizeof(bdd)*N); t = (bdd *)malloc(sizeof(bdd)*N); tp = (bdd *)malloc(sizeof(bdd)*N); h = (bdd *)malloc(sizeof(bdd)*N); hp = (bdd *)malloc(sizeof(bdd)*N); normvar = (int *)malloc(sizeof(int)*N*3); primvar = (int *)malloc(sizeof(int)*N*3); for (n=0 ; n<N*3 ; n++) { normvar[n] = n*2; primvar[n] = n*2+1; } normvarset = bdd_addref( bdd_makeset(normvar, N*3) ); pairs = bdd_newpair(); bdd_setpairs(pairs, primvar, normvar, N*3); for (n=0 ; n<N ; n++) { c[n] = bdd_ithvar(n*6); cp[n] = bdd_ithvar(n*6+1); t[n] = bdd_ithvar(n*6+2); tp[n] = bdd_ithvar(n*6+3); h[n] = bdd_ithvar(n*6+4); hp[n] = bdd_ithvar(n*6+5); } I = bdd_addref( initial_state(t,h,c) ); T = bdd_addref( transitions(t,tp,h,hp,c,cp) ); R = bdd_addref( reachable_states(I,T) ); /*if(has_deadlocks(R,T)) printf("Milner's Scheduler has deadlocks!\n"); */ printf("SatCount R = %.0f\n", bdd_satcount(R)); printf("Calc = %.0f\n", (double)N*pow(2.0,1.0+N)*pow(2.0,3.0*N)); bdd_done(); return 0; }
void create_bdds(TransitionSystem *model) { // printf("%d\ttotal states before merge\n", initial_numstates); // merge_similar_parents(&PSEUDO_END); // merge_similar_children(model->pseudo_initial); //merging children spoiles the calculation of support model->states_size = assign_id_and_collect_labels(model, model->pseudo_initial); // printf("%d\ttotal states after merge\n", model->states_size); // printf("%d\tstates removed\n", initial_numstates - model->states_size); get_transitions(model, NULL, model->pseudo_initial); init_buddy(model->states_size); int state_vars = ceil_of_log2_of(model->states_size); int bdd_vars = state_vars * 2; bdd_setvarnum(bdd_vars); BDD unprimed2primed = bdd_addref(0); model->states_bdds = malloc(sizeof(int *) * model->states_size); model->states_primed_bdds = malloc(sizeof(int *) * model->states_size); model->all_states = bdd_addref(0); //encode states as binary functions for (int i = 1; i < model->states_size; i++) { BDD tmp = bdd_addref(1); BDD tmpp = bdd_addref(1); for (int j = 0; j < state_vars; j++) { int test = (i >> (state_vars - 1 - j)) & 1; if (test == 1) { tmp = f_bdd_and_with(tmp, bdd_ithvar(j)); tmpp = f_bdd_and_with(tmpp, bdd_ithvar(j + state_vars)); } else { tmp = f_bdd_and_with(tmp, bdd_nithvar(j)); tmpp = f_bdd_and_with(tmpp, bdd_nithvar(j + state_vars)); } } model->states_bdds[i] = bdd_addref(tmp); model->states_primed_bdds[i] = bdd_addref(tmpp); model->all_states = f_bdd_or_with(model->all_states, tmp); BDD tt = bdd_addref(bdd_and(tmp, tmpp)); unprimed2primed = f_bdd_or_with(unprimed2primed, tt); bdd_delref(tt); bdd_delref(tmp); bdd_delref(tmpp); } model->pseudo_end = model->states_bdds[PSEUDO_END.id]; //remove pseudo end BDD tmp = bdd_addref(model->all_states); bdd_delref(model->all_states); model->all_states = bdd_apply(tmp, model->pseudo_end, bddop_diff); bdd_delref(tmp); model->unprimed2primed = bdd_addref(unprimed2primed); bdd_delref(unprimed2primed); //create helper of unprimed and primed variables BDD unprimed_vars = bdd_addref(1); BDD primed_vars = bdd_addref(1); for (int i = 0; i < state_vars; i++) { unprimed_vars = f_bdd_and_with(unprimed_vars, bdd_ithvar(i)); primed_vars = f_bdd_and_with(primed_vars, bdd_ithvar(i + state_vars)); } model->unprimed_vars = unprimed_vars; model->primed_vars = primed_vars; //create function for transitions BDD transitions_bdd = bdd_addref(0); for (int i = 0; i < model->transition_size; i++) { // printf("(%d, %d), ", model->transitions[i]->src, model->transitions[i]->dest); BDD tt = bdd_addref(bdd_and(model->states_bdds[model->transitions[i]->src], model->states_primed_bdds[model->transitions[i]->dest])); transitions_bdd = f_bdd_or_with(transitions_bdd, tt); bdd_delref(tt); } //transition from end to end to complete Kripke structure // BDD tt = bdd_addref(bdd_and(model->states_bdds[PSEUDO_END.id], model->states_primed_bdds[PSEUDO_END.id])); // transitions_bdd = f_bdd_or_with(transitions_bdd, tt); // bdd_delref(tt); model->initial_states = 0; State *child; // printf("children %d\n", model->pseudo_initial->children_size); for (int i = 0; i < model->pseudo_initial->children_size; i++) { child = model->pseudo_initial->children[i]; if (child == NULL) continue; // removed model->initial_states = f_bdd_or_with(model->initial_states, model->states_bdds[child->id]); } model->transitions_bdd = transitions_bdd; for (int i = 0; i < model->activities_size; i++) { Labels *l = model->labels[i]; l->states_bdd = bdd_addref(0); for (int j = 0; j < l->states_size; j++) { l->states_bdd = f_bdd_or_with(l->states_bdd, model->states_bdds[l->states[j]]); } } }
int main(int argc,char **argv) { char ambiguous_treatment='A'; char linebuff[1024]; char *parseptr; PARSE_STATE ps; uint32_t low_code,high_code; int width,i,j,vi,vj; FILE *unicode_db; BDD x,y,child[8]; BDD *queue; int queue_low,queue_high,queue_max; puts("/*\n" " * GENERATED CODE - DO NOT EDIT!\n" " * Edit mkwcw.c, which generates this, or the input to that\n" " * program, instead. Distributions of IDSgrep will nonetheless\n" " * usually include a ready-made copy of this file because\n" " * compiling and running mkwcw.c requires a library and data\n" " * file that, although free, not everyone is expected to have.\n" " */\n\n" "#include \"_stdint.h\"\n" ); if (argc>1) ambiguous_treatment=argv[1][0]&~32; bdd_init(1000000,15625); bdd_setcacheratio(64); bdd_setvarnum(32); bdd_gbc_hook(NULL); defined_codes=bddfalse; zero_codes=bddfalse; wide_codes=bddfalse; /* yes, unfortunately UnicodeData.txt and EastAsianWidth.txt are just * different enough to need separate parsers, at least if the parsers * are as stupid as I'd like these ones to be */ if (argc>2) { unicode_db=fopen(argv[2],"rt"); while (1) { fgets(linebuff,sizeof(linebuff),unicode_db); if (feof(unicode_db)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr==';') ps=psSEMI; else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psSEMI: if (*parseptr==';') ps=psWIDTH; break; case psWIDTH: if (((parseptr[0]=='M') && ((parseptr[1]=='e') || (parseptr[1]=='n'))) || ((parseptr[0]=='C') && (parseptr[1]=='f'))) width=0; /* FALL THROUGH */ default: ps=psSTOP; break; } if (width==0) set_range_width(low_code,low_code,0); } fclose(unicode_db); } while (1) { fgets(linebuff,sizeof(linebuff),stdin); if (feof(stdin)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; high_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr=='.') ps=psHIGH; else if (*parseptr==';') { high_code=low_code; ps=psWIDTH; } else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psHIGH: if ((*parseptr>='0') && (*parseptr<='9')) high_code=(high_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) high_code=(high_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) high_code=(high_code<<4)+(*parseptr-'A'+10); else if ((*parseptr=='.') || (*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces, tabs, and dots */ } else if (*parseptr==';') ps=psWIDTH; else ps=psSTOP; break; case psWIDTH: if (*parseptr=='A') *parseptr=ambiguous_treatment; switch (*parseptr) { case 'F': /* full-width treated as wide */ case 'W': /* wide */ width=2; break; case 'H': /* half-width treated as narrow */ case 'N': /* narrow or neutral */ width=1; break; case '0': /* zero-width - should only appear in user database */ width=0; break; default: /* ignore all others */ break; } /* FALL THROUGH */ default: ps=psSTOP; break; } if (width>=0) set_range_width(low_code,high_code,width); } printf("/* node counts before simplification: %d %d %d */\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); x=bdd_addref(bdd_simplify(wide_codes,defined_codes)); bdd_delref(wide_codes); wide_codes=x; x=bdd_addref(bdd_apply(defined_codes,wide_codes,bddop_diff)); bdd_delref(defined_codes); defined_codes=x; x=bdd_addref(bdd_simplify(zero_codes,defined_codes)); bdd_delref(zero_codes); zero_codes=x; printf("/* node counts after simplification: %d %d %d */\n\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); bdd_varblockall(); bdd_intaddvarblock(0,7,0); bdd_intaddvarblock(8,15,0); bdd_intaddvarblock(16,23,0); bdd_intaddvarblock(24,31,0); bdd_intaddvarblock(0,31,1); bdd_reorder_probe(&reordering_size_callback); puts("typedef struct _WIDTH_BBD_ENT {\n" " int16_t child[8];\n" " char byte,shift;\n" "} WIDTH_BDD_ENT;\n\n" "static WIDTH_BDD_ENT width_bdd[]={"); queue=(BDD *)malloc(sizeof(BDD)*1000); queue_max=1000; queue_low=2; queue_high=4; queue[0]=bddfalse; queue[1]=bddtrue; queue[2]=wide_codes; queue[3]=zero_codes; while (queue_low<queue_high) { if (queue_high+8>queue_max) { queue_max/=3; queue_max*=4; queue=(BDD *)realloc(queue,sizeof(BDD)*queue_max); } reorder_focus=queue[queue_low]; bdd_reorder(BDD_REORDER_WIN2ITE); vj=bdd_var(queue[queue_low]); vi=(vj/8)*8; vj=((vj-vi+1)/3)*3-1; if (vj<0) vj=0; x=bdd_addref(bdd_restrict(queue[queue_low],bdd_nithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[0]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[1]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[2]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[3]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); x=bdd_addref(bdd_restrict(queue[queue_low],bdd_ithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[4]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[5]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[6]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[7]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); fputs(" {{",stdout); for (i=0;i<8;i++) { queue[queue_high]=child[i]; for (j=0;queue[j]!=child[i];j++); if (j==queue_high) queue_high++; else bdd_delref(child[i]); printf("%d",j-2); if (i<7) putchar(','); } printf("},%d,%d},\n",vi/8,5-vj); queue_low++; } puts("};\n\n" "int idsgrep_utf8cw(char *);\n" "\n" "#define WBS width_bdd[search]\n" "\n" "int idsgrep_utf8cw(char *cp) {\n" " int search;\n" "\n" " for (search=0;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " if (search==-1)\n" " return 2;\n" " for (search=1;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " return ((-1)-search);\n" "}\n"); bdd_done(); exit(0); }