static int etf_short(model_t self,int group,int*src,TransitionCB cb,void*user_context){ gb_context_t ctx=(gb_context_t)GBgetContext(self); int len=dm_ones_in_row(GBgetDMInfo(self), group); uint32_t src_no=(uint32_t)SIlookupC(ctx->trans_key_idx[group],(char*)src,len<<2); matrix_table_t mt=ctx->trans_table[group]; if ((src_no)>=MTclusterCount(mt)) return 0; int K=MTclusterSize(mt,src_no); for(int i=0;i<K;i++){ uint32_t row[3]; MTclusterGetRow(mt,src_no,i,row); int *dst=(int*)SIgetC(ctx->trans_key_idx[group],(int)row[1],NULL); switch(ctx->edge_labels){ case 0: { transition_info_t ti = GB_TI(NULL, group); cb(user_context,&ti,dst,NULL); break; } case 1: { int lbl=(int)row[2]; transition_info_t ti = GB_TI(&lbl, group); cb(user_context,&ti,dst,NULL); break; } default: { transition_info_t ti = GB_TI((int*)SIgetC(ctx->label_idx,(int)row[2],NULL), group); cb(user_context,&ti,dst,NULL); break; } } } return K; }
static void init_model(char *file) { Warning(info, "opening %s", file); model = GBcreateBase(); GBsetChunkMap (model, HREgreyboxTableFactory()); HREbarrier(HREglobal()); GBloadFile(model, file, &model); HREbarrier(HREglobal()); if (HREme(HREglobal())==0 && !PINS_USE_GUARDS && no_soundness_check) { Abort("Option --no-soundness-check is incompatible with --pins-guards=false"); } if (HREme(HREglobal())==0 && log_active(infoLong) && !no_matrix) { fprintf(stderr, "Dependency Matrix:\n"); GBprintDependencyMatrixCombined(stderr, model); } ltstype = GBgetLTStype(model); N = lts_type_get_state_length(ltstype); eLbls = lts_type_get_edge_label_count(ltstype); sLbls = GBgetStateLabelInfo(model) == NULL ? 0 : dm_nrows(GBgetStateLabelInfo(model)); nGrps = dm_nrows(GBgetDMInfo(model)); max_sat_levels = (N / sat_granularity) + 1; if (PINS_USE_GUARDS) { nGuards = GBgetStateLabelGroupInfo(model, GB_SL_GUARDS)->count; if (HREme(HREglobal())==0) { Warning(info, "state vector length is %d; there are %d groups and %d guards", N, nGrps, nGuards); } } else { if (HREme(HREglobal())==0) { Warning(info, "state vector length is %d; there are %d groups", N, nGrps); } } int id=GBgetMatrixID(model,"inhibit"); if (id>=0){ inhibit_matrix=GBgetMatrix(model,id); if (HREme(HREglobal())==0) { Warning(infoLong,"inhibit matrix is:"); if (log_active(infoLong)) dm_print(stderr,inhibit_matrix); } } id = GBgetMatrixID(model,LTSMIN_EDGE_TYPE_ACTION_CLASS); if (id>=0){ class_matrix=GBgetMatrix(model,id); if (HREme(HREglobal())==0) { Warning(infoLong,"inhibit class matrix is:"); if (log_active(infoLong)) dm_print(stderr,class_matrix); } } HREbarrier(HREglobal()); }
void do_output(char *etf_output, vset_t visited) { FILE *tbl_file; rt_timer_t timer = RTcreateTimer(); RTstartTimer(timer); Warning(info, "writing output"); tbl_file = fopen(etf_output, "w"); if (tbl_file == NULL) AbortCall("could not open %s", etf_output); if (vdom_separates_rw(domain)) { /* * This part is necessary because the ETF format does not yet support * read, write and copy. This part should thus be removed when ETF is * extended. */ Warning(info, "Note: ETF format does not yet support read, write and copy."); transitions_short = GBgetTransitionsShort; RTfree (r_projs); RTfree (w_projs); w_projs = r_projs = (ci_list **) dm_rows_to_idx_table (GBgetDMInfo(model)); for (int i = 0; i < nGrps; i++) { vset_destroy(group_explored[i]); group_explored[i] = vset_create(domain, r_projs[i]->count, r_projs[i]->data); vset_project(group_explored[i], visited); } } output_init(tbl_file); output_trans(tbl_file); output_lbls(tbl_file, visited); output_types(tbl_file); fclose(tbl_file); RTstopTimer(timer); RTprintTimer(info, timer, "writing output took"); }
static void etf_edge(void *context, transition_info_t *ti, int *dst, int *cpy) { output_context* ctx = (output_context*)context; ctx->tbl_count++; for(int i = 0, k = 0 ; i < N; i++) { if (dm_is_set(GBgetDMInfo(ctx->model), ctx->group, i)) { fprintf(ctx->tbl_file, " %d/%d", ctx->src[k], dst[k]); k++; } else { fprintf(ctx->tbl_file," *"); } } for(int i = 0; i < eLbls; i++) fprintf(ctx->tbl_file, " %d", ti->labels[i]); fprintf(ctx->tbl_file,"\n"); (void)cpy; }
void CAESAR_INIT_GRAPH(void) { char *opencaesar_args, *opencaesar_prog,*ltsmin_options; int argc; char **argv; opencaesar_prog = getenv ("OPEN_CAESAR_PROG"); if (opencaesar_prog == NULL) CAESAR_ERROR ("undefined environment variable $OPEN_CAESAR_PROG"); opencaesar_args = getenv ("OPEN_CAESAR_FILE"); if (opencaesar_args == NULL) CAESAR_ERROR ("undefined environment variable $OPEN_CAESAR_FILE"); ltsmin_options = getenv ("LTSMIN_OPTIONS"); if (ltsmin_options == NULL) CAESAR_ERROR ("undefined environment variable $LTSMIN_OPTIONS"); int len=strlen(opencaesar_prog)+strlen(ltsmin_options)+strlen(opencaesar_args); char cmdline[len+6]; sprintf(cmdline,"%s %s %s",opencaesar_prog,ltsmin_options,opencaesar_args); int res=poptParseArgvString(cmdline,&argc,(void*)(&argv)); if (res){ Abort("could not parse %s: %s",opencaesar_args,poptStrerror(res)); } char *files[2]; HREinitBegin(argv[0]); HREaddOptions(options,"Options"); HREinitStart(&argc,&argv,1,1,(char**)files,"<model>"); Warning(info,"loading model from %s",files[0]); model=GBcreateBase(); GBsetChunkMethods(model,new_string_index,NULL, (int2chunk_t)SIgetC, (chunk2int_t)SIputC, (chunkatint_t)SIputCAt, (get_count_t)SIgetCount); GBloadFile(model,files[0],&model); ltstype=GBgetLTStype(model); N = lts_type_get_state_length(ltstype); K = dm_nrows(GBgetDMInfo(model)); Warning(info,"length is %d, there are %d groups",N,K); state_labels=lts_type_get_state_label_count(ltstype); edge_labels=lts_type_get_edge_label_count(ltstype); Warning(info,"There are %d state labels and %d edge labels",state_labels,edge_labels); if (edge_encode){ edge_size=edge_labels+N+state_labels; Warning(info,"encoding state information on edges"); } else { edge_size=edge_labels; Warning(info,"state information is hidden"); } CAESAR_HINT_SIZE_STATE = N*sizeof(int); CAESAR_HINT_HASH_SIZE_STATE = CAESAR_HINT_SIZE_STATE; CAESAR_HINT_SIZE_LABEL = edge_size*sizeof(int); CAESAR_HINT_HASH_SIZE_LABEL = CAESAR_HINT_SIZE_LABEL; Warning(info,"CAESAR_HINT_SIZE_STATE=%lu CAESAR_HINT_SIZE_LABEL=%lu", (unsigned long)CAESAR_HINT_SIZE_STATE,(unsigned long)CAESAR_HINT_SIZE_LABEL); }
static void initialize_levels(bitvector_t *groups, int *empty_groups, int *back, bitvector_t *reach_groups) { int level[nGrps]; // groups: i = 0 .. nGrps - 1 // vars : j = 0 .. N - 1 // level[i] = first '+' in row (highest in BDD) of group i // recast 0 .. N - 1 down to equal groups 0 .. (N - 1) / sat_granularity for (int i = 0; i < nGrps; i++) { level[i] = -1; for (int j = 0; j < N; j++) { if (dm_is_set(GBgetDMInfo(model), i, j)) { level[i] = (N - j - 1) / sat_granularity; break; } } if (level[i] == -1) level[i] = 0; } for (int i = 0; i < nGrps; i++) bitvector_set(&groups[level[i]], i); // Limit the bit vectors to the groups we are interested in and establish // which saturation levels are not used. for (int k = 0; k < max_sat_levels; k++) { bitvector_intersect(&groups[k], reach_groups); empty_groups[k] = bitvector_is_empty(&groups[k]); } if (back == NULL) return; // back[k] = last + in any group of level k bitvector_t level_matrix[max_sat_levels]; for (int k = 0; k < max_sat_levels; k++) { bitvector_create(&level_matrix[k], N); back[k] = max_sat_levels; } for (int i = 0; i < nGrps; i++) { dm_row_union(&level_matrix[level[i]], GBgetDMInfo(model), i); } for (int k = 0; k < max_sat_levels; k++) { for (int j = 0; j < k; j++) { bitvector_t temp; int empty; bitvector_copy(&temp, &level_matrix[j]); bitvector_intersect(&temp, &level_matrix[k]); empty = bitvector_is_empty(&temp); bitvector_free(&temp); if (!empty) if (j < back[k]) back[k] = j; } if (back[k] == max_sat_levels && !bitvector_is_empty(&level_matrix[k])) back[k] = k + 1; } for (int k = 0; k < max_sat_levels; k++) bitvector_free(&level_matrix[k]); }
static void init_domain(vset_implementation_t impl) { domain = vdom_create_domain(N, impl); for (int i = 0; i < dm_ncols(GBgetDMInfo(model)); i++) { vdom_set_name(domain, i, lts_type_get_state_name(ltstype, i)); } group_next = (vrel_t*)RTmalloc(nGrps * sizeof(vrel_t)); group_explored = (vset_t*)RTmalloc(nGrps * sizeof(vset_t)); group_tmp = (vset_t*)RTmalloc(nGrps * sizeof(vset_t)); r_projs = (ci_list **)RTmalloc(sizeof(ci_list *[nGrps])); w_projs = (ci_list **)RTmalloc(sizeof(ci_list *[nGrps])); l_projs = (ci_list **)RTmalloc(sizeof(ci_list *[sLbls])); label_false = (vset_t*)RTmalloc(sLbls * sizeof(vset_t)); label_true = (vset_t*)RTmalloc(sLbls * sizeof(vset_t)); label_tmp = (vset_t*)RTmalloc(sLbls * sizeof(vset_t)); if (!vdom_separates_rw(domain) && !PINS_USE_GUARDS) { read_matrix = GBgetDMInfo(model); write_matrix = GBgetDMInfo(model); Warning(info, "Using GBgetTransitionsShort as next-state function"); transitions_short = GBgetTransitionsShort; } else if (!vdom_separates_rw(domain) && PINS_USE_GUARDS) { read_matrix = GBgetMatrix(model, GBgetMatrixID(model, LTSMIN_MATRIX_ACTIONS_READS)); write_matrix = GBgetDMInfo(model); Warning(info, "Using GBgetActionsShort as next-state function"); transitions_short = GBgetActionsShort; } else if (vdom_separates_rw(domain) && !PINS_USE_GUARDS) { read_matrix = GBgetDMInfoRead(model); write_matrix = GBgetDMInfoMayWrite(model); Warning(info, "Using GBgetTransitionsShortR2W as next-state function"); transitions_short = GBgetTransitionsShortR2W; } else { // vdom_separates_rw(domain) && PINS_USE_GUARDS read_matrix = GBgetMatrix(model, GBgetMatrixID(model, LTSMIN_MATRIX_ACTIONS_READS)); write_matrix = GBgetDMInfoMayWrite(model); Warning(info, "Using GBgetActionsShortR2W as next-state function"); transitions_short = GBgetActionsShortR2W; } if (PINS_USE_GUARDS) { if (no_soundness_check) { Warning(info, "Guard-splitting: not checking soundness of the specification, this may result in an incorrect state space!"); } else { Warning(info, "Guard-splitting: checking soundness of specification, this may be slow!"); } } r_projs = (ci_list **) dm_rows_to_idx_table (read_matrix); w_projs = (ci_list **) dm_rows_to_idx_table (write_matrix); for(int i = 0; i < nGrps; i++) { if (HREme(HREglobal())==0) { if (vdom_separates_rw(domain)) { group_next[i] = vrel_create_rw (domain, r_projs[i]->count, r_projs[i]->data, w_projs[i]->count, w_projs[i]->data); } else { group_next[i] = vrel_create (domain, r_projs[i]->count, r_projs[i]->data); } group_explored[i] = vset_create (domain, r_projs[i]->count, r_projs[i]->data); group_tmp[i] = vset_create (domain, r_projs[i]->count, r_projs[i]->data); if (inhibit_matrix != NULL) { inhibit_class_count = dm_nrows(inhibit_matrix); class_enabled = (vset_t*)RTmalloc(inhibit_class_count * sizeof(vset_t)); for(int i=0; i<inhibit_class_count; i++) { class_enabled[i] = vset_create(domain, -1, NULL); } } } } l_projs = (ci_list **) dm_rows_to_idx_table (GBgetStateLabelInfo(model)); for (int i = 0; i < sLbls; i++) { /* Indeed, we skip unused state labels, but allocate memory for pointers * (to vset_t's). Is this bad? Maybe a hashmap is worse. */ if (bitvector_is_set(&state_label_used, i)) { if (HREme(HREglobal()) == 0) { label_false[i] = vset_create(domain, l_projs[i]->count, l_projs[i]->data); label_true[i] = vset_create(domain, l_projs[i]->count, l_projs[i]->data); label_tmp[i] = vset_create(domain, l_projs[i]->count, l_projs[i]->data); } } else { label_false[i] = NULL; label_true[i] = NULL; label_tmp[i] = NULL; } } inv_set = (vset_t *) RTmalloc(sizeof(vset_t[num_inv])); for (int i = 0; i < num_inv; i++) { inv_set[i] = vset_create (domain, inv_proj[i]->count, inv_proj[i]->data); inv_info_prepare (inv_expr[i], inv_parse_env[i], i); } }