CAESAR_TYPE_STRING CAESAR_GATE_LABEL(CAESAR_TYPE_LABEL l) { static char *s = NULL; /* start of string */ static char *b = NULL; /*beyond*/ char *p = NULL; /* current insertion point */ int u, n; /* used, needed */ unsigned int i; /*unsigned to avoid warning in comparsison to c.len*/ chunk c; if (edge_labels==1) { c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,0),l->label[0]); i = 0; while(i < c.len && strchr(" \t(),.:!?;[]{}",c.data[i])==0) i++; p = s; n = i; if (b-p < n) { u = p-s; s = RTrealloc(s, u+n); p = s+u; b = s + u+n; } strncpy(s, c.data, i); if (i > 0) s[i-1] = '\0'; else s[0] = '\0'; return s; } else return "gate"; }
lts_file_t aut_file_create(const char* name,lts_type_t ltstype,int segments,lts_file_t settings){ if (lts_type_get_state_length(ltstype)) { //Abort("cannot write state to AUT file"); Print(infoShort,"Ignoring state vector"); } if (lts_type_get_state_label_count(ltstype)) { Abort("cannot write state labels to AUT file"); } if (lts_type_get_edge_label_count(ltstype)!=1) { Abort("AUT files contain precisely one edge label"); } if (segments!=1) Abort("AUT files contain precisely 1 segment"); lts_file_t file=lts_file_bare(name,ltstype,1,settings,sizeof(struct lts_file_s)); file->f=fopen(name,"w"); if(file->f==NULL){ AbortCall("while opening %s",name); } file->root--; // set to -1 denoting undefined. file->states++; // set to 1, denoting one state. file->type_no=lts_type_get_edge_label_typeno(ltstype,0); lts_file_set_write_init(file,aut_write_init); lts_file_set_write_state(file,write_state); lts_file_set_write_edge(file,aut_write_edge); lts_file_set_close(file,aut_write_close); fprintf(file->f,"des(?,?,?) \n"); lts_file_complete(file); return file; }
void lts_type_serialize(lts_type_t t,stream_t ds){ DSwriteS(ds,"lts signature 1.1"); uint32_t N=lts_type_get_state_length(t); Warning(debug,"state length is %d",N); DSwriteU32(ds,N); for(uint32_t i=0;i<N;i++){ char*x=lts_type_get_state_name(t,i); if (x) DSwriteS(ds,x); else DSwriteS(ds,""); DSwriteU32(ds,lts_type_get_state_typeno(t,i)); } N=lts_type_get_state_label_count(t); Warning(debug,"%d state labels",N); DSwriteU32(ds,N); for(uint32_t i=0;i<N;i++){ char*x=lts_type_get_state_label_name(t,i); if (x) DSwriteS(ds,x); else DSwriteS(ds,""); DSwriteU32(ds,lts_type_get_state_label_typeno(t,i)); } N=lts_type_get_edge_label_count(t); Warning(debug,"%d edge labels",N); DSwriteU32(ds,N); for(uint32_t i=0;i<N;i++){ char*x=lts_type_get_edge_label_name(t,i); if (x) DSwriteS(ds,x); else DSwriteS(ds,""); DSwriteU32(ds,lts_type_get_edge_label_typeno(t,i)); Warning(debug,"edge label %d is %s : %s",i,x,lts_type_get_edge_label_type(t,i)); } N=lts_type_get_type_count(t); Warning(debug,"%d types",N); DSwriteU32(ds,N); for(uint32_t i=0;i<N;i++){ DSwriteS(ds,lts_type_get_type(t,i)); DSwriteS(ds,(char*)data_format_string(t,i)); } }
CAESAR_TYPE_BOOLEAN CAESAR_VISIBLE_LABEL(CAESAR_TYPE_LABEL x) { CAESAR_TYPE_BOOLEAN vis = CAESAR_TRUE; if (edge_labels==1) { chunk c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,0),x->label[0]); if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0) vis =CAESAR_FALSE; } return vis; }
static char * str_group (check_ctx_t *ctx, int group) { model_t model = ctx->parent; lts_type_t ltstype = GBgetLTStype (model); int label = lts_type_find_edge_label (ltstype, LTSMIN_EDGE_TYPE_STATEMENT); if (label) return "NULL"; int type = lts_type_get_edge_label_typeno (ltstype, label); int count = pins_chunk_count (model, type); if (count < ctx->K) return "NULL"; chunk c = pins_chunk_get (model, type, group); return c.data; }
static void torx_transition(void*arg,int*lbl,int*dst){ torx_struct_t *context=(torx_struct_t*)arg; int tmp=TreeFold(dbs,dst); chunk c=GBchunkGet(context->model,lts_type_get_edge_label_typeno(context->ltstype,0),lbl[0]); int vis = 1; if (c.len==3 && strncmp(c.data, "tau", c.len)==0) vis =0; /* tab-separated fields: edge vis sat lbl pred vars state */ fprintf(stdout, "Ee\t\t%d\t1\t%*s\t\t\t%d\n", vis, c.len, c.data, tmp); }
lts_file_t aut_file_open(const char* name){ lts_type_t ltstype=single_action_type(); lts_file_t file=lts_file_bare(name,ltstype,1,NULL,sizeof(struct lts_file_s)); file->type_no=lts_type_get_edge_label_typeno(ltstype,0); lts_file_set_read_init(file,aut_read_init); lts_file_set_read_edge(file,aut_read_edge); lts_file_set_close(file,aut_read_close); lts_file_complete(file); file->f=fopen(name,"r"); if(file->f==NULL){ AbortCall("while opening %s",name); } int matches; matches = fscanf(file->f,"des%*[^(]s"); if (matches != 0) Abort("while parsing %s",name); matches = fscanf(file->f,"(%llu,%llu,%llu)\n",&file->root,&file->trans,&file->states); if (matches != 3) Abort("while parsing %s",name); Print(infoLong,"file %s contains %llu states and %llu transitions", name,file->states,file->trans); return file; }
static inline void print_ti (check_ctx_t *ctx, transition_info_t *ti) { if (ti == NULL || ti->labels == NULL) return; model_t model = ctx->parent; lts_type_t ltstype = GBgetLTStype (model); int Max = 4096; char *tmp = RTmalloc (Max); int l; for (int i = 0; i < ctx->L; i++) { char *name = lts_type_get_edge_label_name (ltstype, i); char *type = lts_type_get_edge_label_type (ltstype, i); int typeno = lts_type_get_edge_label_typeno (ltstype, i); char *res = tmp; l = snprintf (res, Max, " --> %s : %s = ", name, type); l += print_chunk (model, res+l, Max-l, typeno, ti->labels[i]); Printf (lerror, "%s\n", res); } RTfree (tmp); }
static void lts_write_dir(archive_t archive,string_map_t map,lts_t lts,int segments){ if (map) arch_set_write_policy(archive,map); dir_info_t info=DIRinfoCreate(segments); int i,j; uint32_t k; char filename[1024]; stream_t output; stream_t *src_out; stream_t *lbl_out; stream_t *dst_out; if (lts->root_count !=1) Abort("LTS has %u initial states DIR requires 1",lts->root_count); lts_set_type(lts,LTS_BLOCK); info->label_tau=lts->tau; int type_no=lts_type_get_edge_label_typeno(lts->ltstype,0); switch(lts_type_get_format(lts->ltstype,type_no)){ case LTStypeChunk: case LTStypeEnum: break; default: Abort("DIR is limited to Chunk/Enum edge labels."); } info->label_count=VTgetCount(lts->values[type_no]); info->initial_seg=lts->root_list[0]%segments; info->initial_ofs=lts->root_list[0]/segments; output=arch_write(archive,"TermDB"); int last_idx = 0; table_iterator_t it = VTiterator (lts->values[type_no]); while (IThasNext(it)) { chunk label_c = ITnext (it); int idx = VTputChunk (lts->values[type_no], label_c); while (last_idx < idx) { // fill non-dense indices write_chunk (output, (chunk){0, ""}); last_idx++; } write_chunk (output, label_c); } DSclose(&output); src_out=(stream_t*)RTmalloc(segments*sizeof(stream_t)); lbl_out=(stream_t*)RTmalloc(segments*sizeof(stream_t)); dst_out=(stream_t*)RTmalloc(segments*sizeof(stream_t)); for(i=0;i<segments;i++) { for(j=0;j<segments;j++) { sprintf(filename,"src-%d-%d",i,j); src_out[j]=arch_write(archive,filename); sprintf(filename,"label-%d-%d",i,j); lbl_out[j]=arch_write(archive,filename); sprintf(filename,"dest-%d-%d",i,j); dst_out[j]=arch_write(archive,filename); } for(j=i;j<(int)lts->states;j+=segments){ for(k=lts->begin[j];k<lts->begin[j+1];k++){ int dseg=(lts->dest[k])%segments; info->transition_count[i][dseg]++; DSwriteU32(src_out[dseg],info->state_count[i]); DSwriteU32(lbl_out[dseg],lts->label[k]); DSwriteU32(dst_out[dseg],(lts->dest[k])/segments); } info->state_count[i]++; } for(j=0;j<segments;j++) { DSclose(&src_out[j]); DSclose(&lbl_out[j]); DSclose(&dst_out[j]); } } info->info="bsim2 output"; output=arch_write(archive,"info"); DIRinfoWrite(output,info); DSclose(&output); info->info=NULL; DIRinfoDestroy(info); }
static void lts_read_dir(archive_t archive,lts_t lts){ Print(infoShort,"opening info"); stream_t input=arch_read(archive,"info"); dir_info_t info=DIRinfoRead(input,1); DSclose(&input); int segments=info->segment_count; Print(infoShort,"got info for %d segments",segments); int offset[segments]; offset[0]=0; for(int i=1;i<segments;i++){ offset[i]=info->state_count[i-1]+offset[i-1]; } int s_count=0; int t_count=0; for(int i=0;i<segments;i++){ s_count+=info->state_count[i]; for(int j=0;j<segments;j++){ t_count+=info->transition_count[i][j]; } } Print(infoShort,"counted %u states and %u transitions",s_count,t_count); lts_set_sig(lts,single_action_type()); lts_set_type(lts,LTS_LIST); lts_set_size(lts,1,s_count,t_count); lts->root_list[0]=offset[info->initial_seg]+info->initial_ofs; lts->tau=info->label_tau; Print(infoShort,"getting %d labels from TermDB",info->label_count); input=arch_read(archive,"TermDB"); int type_no=lts_type_get_edge_label_typeno(lts->ltstype,0); for(int i=0;i<info->label_count;i++){ char *line=DSreadLN(input); int len=strlen(line); char data[len]; chunk tmp_chunk=chunk_ld(len,data); string2chunk(line,&tmp_chunk); VTputAtChunk(lts->values[type_no], tmp_chunk, i); } DSclose(&input); Print(infoShort,"got labels"); int t_offset=0; char filename[1024]; for(int i=0;i<segments;i++){ for(int j=0;j<segments;j++){ sprintf(filename,"src-%d-%d",i,j); stream_t src=arch_read(archive,filename); sprintf(filename,"label-%d-%d",i,j); stream_t lbl=arch_read(archive,filename); sprintf(filename,"dest-%d-%d",i,j); stream_t dst=arch_read(archive,filename); for(int k=0;k<info->transition_count[i][j];k++){ lts->src[t_offset]=offset[i]+DSreadU32(src); lts->label[t_offset]=DSreadU32(lbl); lts->dest[t_offset]=offset[j]+DSreadU32(dst); t_offset++; } DSclose(&src); DSclose(&lbl); DSclose(&dst); } } DIRinfoDestroy(info); }
CAESAR_TYPE_STRING CAESAR_STRING_LABEL(CAESAR_TYPE_LABEL l) { static char *s = NULL; /* start of string */ static char *b = NULL; /*beyond*/ static char *tau = "i"; char *p = NULL; /* current insertion point */ int u, n; /* used, needed */ int i; chunk c; size_t clen; p = s; n = 5; if (b-p < n) { u = p-s; s = RTrealloc(s, u+n);/* TODO: check s!=0 */ p = s+u; b = s + u+n; } if (edge_labels > 0 && l->label[0]<0){ n = 6; if (b-p < n) { u = p-s; s = RTrealloc(s, u+n); /* TODO: check s!=0 */ p = s+u; b = s + u+n; } sprintf(p, "delta"); p+=strlen(p); } else { if (edge_labels > 1 || edge_encode) { sprintf(p, "|"); p += strlen(p); } for(i=0; i < edge_labels; i++) { char *name=lts_type_get_edge_label_name(ltstype,i); c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,i),l->label[i]); if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0) clen=strlen(tau); else clen=c.len*2+6; n = strlen(name)+ 1 + clen+1+1+1; /* for name , '=' , c, ';', '>', '\0' */ if (b-p < n) { u = p-s; s = RTrealloc(s, u+n); /* TODO: check s!=0 */ p = s+u; b = s + u+n; } if (i>0) { sprintf(p, "|"); p += strlen(p); } if (edge_labels > 1 || edge_encode ) { sprintf(p, "%s=",name); p += strlen(p); } if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0) sprintf(p, "%s", tau); else chunk2string(c,b-p,p); p += strlen(p); } } if (edge_labels > 1 || edge_encode ) { sprintf(p, "|"); p += strlen(p); } if (edge_encode){ int ofs=edge_labels; /* for(i=0;i<N;i++){ char*name=lts_type_get_state_name(ltstype,i); c=GBchunkGet(model,lts_type_get_state_typeno(ltstype,i),l->label[ofs+i]); n=strlen(name)+c.len*2+7; if (b-p < n) { u = p-s; s = realloc(s, u+n); // TODO: check s!=0 p = s+u; b = s + u+n; } sprintf(p, "%s=",name); p+=strlen(p); chunk2string(c,b-p,p); p+=strlen(p); sprintf(p, "|"); p +=strlen(p); } */ ofs+=N; for(i=0;i<state_labels;i++){ char*name=lts_type_get_state_label_name(ltstype,i); c=GBchunkGet(model,lts_type_get_state_label_typeno(ltstype,i),l->label[ofs+i]); n=strlen(name)+c.len*2+7; if (b-p < n) { u = p-s; s = RTrealloc(s, u+n); /* TODO: check s!=0 */ p = s+u; b = s + u+n; } sprintf(p, "%s=",name); p+=strlen(p); chunk2string(c,b-p,p); p+=strlen(p); sprintf(p, "|"); p +=strlen(p); } } return s; }
static void write_close(lts_file_t file){ //if (file->init_count!=1) Abort("missing initial state"); in some cases no initial states makes sense! uint32_t pre_sum=0; for(int i=0;i<file->segments;i++) pre_sum+=file->state_perseg[i]; uint32_t tmp; for (int i=0;i<file->segments;i++){ tmp=lts_get_max_src_p1(file,i); if (tmp>file->state_perseg[i]) file->state_perseg[i]=tmp; tmp=lts_get_max_dst_p1(file,i); if (tmp>file->state_perseg[i]) file->state_perseg[i]=tmp; } file->state_count=0; for(int i=0;i<file->segments;i++) file->state_count+=file->state_perseg[i]; if (pre_sum && pre_sum!=file->state_count) { Abort("edges use unwritten states"); } uint32_t offset[file->segments]; offset[0]=0; for(int i=1;i<file->segments;i++) offset[i]=offset[i-1]+file->state_perseg[i-1]; uint32_t seg,ofs; for(uint32_t i=0;i<file->lts->root_count;i++){ seg=file->lts->root_list[i]%file->segments; ofs=file->lts->root_list[i]/file->segments; file->lts->root_list[i]=offset[seg]+ofs; } for(uint32_t i=0;i<file->edge_count;i++){ seg=file->lts->src[i]%file->segments; ofs=file->lts->src[i]/file->segments; file->lts->src[i]=offset[seg]+ofs; seg=file->lts->dest[i]%file->segments; ofs=file->lts->dest[i]/file->segments; file->lts->dest[i]=offset[seg]+ofs; } if (file->lts->properties){ uint32_t* temp=file->lts->properties; file->lts->properties=(uint32_t*)RTmalloc(file->state_count*sizeof(uint32_t)); for(int i=0;i<file->segments;i++){ for(uint32_t j=0;j<file->state_perseg[i];j++){ file->lts->properties[offset[i]+j]=temp[j*file->segments+i]; } } RTfree(temp); } lts_set_size(file->lts,file->init_count,file->state_count,file->edge_count); file->lts->tau=-1; if (lts_type_get_edge_label_count(file->lts->ltstype)==1 && strncmp(lts_type_get_edge_label_name(file->lts->ltstype,0),LTSMIN_EDGE_TYPE_ACTION_PREFIX,6)==0) { Print(infoShort,"action labeled, detecting silent step"); int tableno=lts_type_get_edge_label_typeno(file->lts->ltstype,0); value_table_t vt=file->lts->values[tableno]; int N=VTgetCount(vt); for(int i=0;i<N;i++){ chunk c=VTgetChunk(vt,i); if ( (c.len==strlen(LTSMIN_EDGE_VALUE_TAU) && strcmp(c.data,LTSMIN_EDGE_VALUE_TAU)==0) || (c.len==1 && strcmp(c.data,"i")==0) ) { Print(infoShort,"invisible label is %s",c.data); if (file->lts->tau>=0) Abort("two silent labels"); file->lts->tau=i; } } if (file->lts->tau<0) { Print(infoShort,"no silent label"); } } }
static void actual_main(void *arg) #endif { int argc = ((struct args_t*)arg)->argc; char **argv = ((struct args_t*)arg)->argv; /* initialize HRE */ HREinitBegin(argv[0]); HREaddOptions(options,"Perform a symbolic reachability analysis of <model>\n" "The optional output of this analysis is an ETF " "representation of the input\n\nOptions"); lts_lib_setup(); // add options for LTS library HREinitStart(&argc,&argv,1,2,files,"<model> [<etf>]"); /* initialize HRE on other workers */ init_hre(HREglobal()); /* check for unsupported options */ if (PINS_POR != PINS_POR_NONE) Abort("Partial-order reduction and symbolic model checking are not compatible."); if (inhibit_matrix != NULL && sat_strategy != NO_SAT) Abort("Maximal progress is incompatibale with saturation."); if (files[1] != NULL) { char *ext = strrchr(files[1], '.'); if (ext == NULL || ext == files[1]) { Abort("Output filename has no extension!"); } if (strcasecmp(ext, ".etf") != 0) { // not ETF if (!(vset_default_domain == VSET_Sylvan && strcasecmp(ext, ".bdd") == 0) && !(vset_default_domain == VSET_LDDmc && strcasecmp(ext, ".ldd") == 0)) { Abort("Only supported output formats are ETF, BDD (with --vset=sylvan) and LDD (with --vset=lddmc)"); } if (PINS_USE_GUARDS) { Abort("Exporting symbolic state space not comptabile with " "guard-splitting"); } } } #ifdef HAVE_SYLVAN if (!USE_PARALLELISM) { if (strategy == PAR_P) { strategy = BFS_P; Print(info, "Front-end not thread-safe; using --order=bfs-prev instead of --order=par-prev."); } else if (strategy == PAR) { strategy = BFS; Print(info, "Front-end not thread-safe; using --order=bfs instead of --order=par."); } } #endif /* turn off Lace for now to speed up while not using parallelism */ lace_suspend(); /* initialize the model and PINS wrappers */ init_model(files[0]); /* initialize action detection */ act_label = lts_type_find_edge_label_prefix (ltstype, LTSMIN_EDGE_TYPE_ACTION_PREFIX); if (act_label != -1) action_typeno = lts_type_get_edge_label_typeno(ltstype, act_label); if (act_detect != NULL) init_action_detection(); bitvector_create(&state_label_used, sLbls); if (inv_detect != NULL) init_invariant_detection(); else if (PINS_USE_GUARDS) { for (int i = 0; i < nGuards; i++) { bitvector_set(&state_label_used, i); } } init_maxsum(ltstype); /* turn on Lace again (for Sylvan) */ if (vset_default_domain==VSET_Sylvan || vset_default_domain==VSET_LDDmc) { lace_resume(); } if (next_union) vset_next_fn = vset_next_union_src; init_domain(VSET_IMPL_AUTOSELECT); vset_t initial = vset_create(domain, -1, NULL); int *src = RTmalloc (sizeof(int[N])); GBgetInitialState(model, src); vset_add(initial, src); Print(infoShort, "got initial state"); /* if writing .dot files, open directory first */ if (dot_dir != NULL) { DIR* dir = opendir(dot_dir); if (dir) { closedir(dir); } else if (ENOENT == errno) { Abort("Option 'dot-dir': directory '%s' does not exist", dot_dir); } else { Abort("Option 'dot-dir': failed opening directory '%s'", dot_dir); } } if (vset_dir != NULL) { DIR *dir = opendir(vset_dir); if (dir) { closedir(dir); } else if (errno == ENOENT) { Abort("Option 'save-levels': directory '%s' does not exist", vset_dir); } else { Abort("Option 'save-levels': failed opening directory '%s'", vset_dir); } } init_mu_calculus(); /* determine if we need to generate a symbolic parity game */ #ifdef LTSMIN_PBES bool spg = true; #else bool spg = GBhaveMucalc() ? true : false; #endif /* if spg, then initialize labeling stuff before reachability */ if (spg) { Print(infoShort, "Generating a Symbolic Parity Game (SPG)."); init_spg(model); } /* create timer */ reach_timer = RTcreateTimer(); /* fix level 0 */ visited = vset_create(domain, -1, NULL); vset_copy(visited, initial); /* check the invariants at level 0 */ check_invariants(visited, 0); /* run reachability */ run_reachability(visited, files[1]); /* report states */ final_stat_reporting(visited); /* save LTS */ if (files[1] != NULL) { char *ext = strrchr(files[1], '.'); if (strcasecmp(ext, ".etf") == 0) { do_output(files[1], visited); } else { // if not .etf, then the filename ends with .bdd or .ldd, symbolic LTS do_dd_output (initial, visited, files[1]); } } compute_maxsum(visited, domain); CHECK_MU(visited, src); if (max_mu_count > 0) { Print(info, "Mu-calculus peak nodes: %ld", max_mu_count); } /* optionally print counts of all group_next and group_explored sets */ final_final_stats_reporting (); if (spg) { // converting the LTS to a symbolic parity game, save and solve. lts_to_pg_solve (visited, src); } #ifdef HAVE_SYLVAN /* in case other Lace threads were still suspended... */ if (vset_default_domain!=VSET_Sylvan && vset_default_domain!=VSET_LDDmc) { lace_resume(); } else if (SYLVAN_STATS) { sylvan_stats_report(stderr); } #endif RTfree (src); GBExit(model); }