static int type_max (check_ctx_t *ctx, int idx) { model_t model = ctx->parent; lts_type_t ltstype = GBgetLTStype (model); int typeno = lts_type_get_state_typeno (ltstype, idx); int c; switch (lts_type_get_format (ltstype, typeno)) { case LTStypeDirect: GBgetInitialState (model, ctx->src2); c = ctx->src2[idx]; return c == 0 ? 1 : c; case LTStypeRange: return lts_type_get_min (ltstype, typeno); case LTStypeEnum: c = pins_chunk_count (model, typeno); HREassert (c > 0, "Empty enum table for slot: %d -- %s", idx, str_slot(ctx, NULL, idx)); return c; case LTStypeChunk: c = pins_chunk_count (model, typeno); return c == 0 ? 1 : c; case LTStypeBool: return 1; case LTStypeTrilean: return 2; case LTStypeSInt32: return (1ULL<<31) - 1; default: { HREassert(false); return -1; } } }
static void ltsmin_expr_lookup_value(ltsmin_expr_t top, ltsmin_expr_t e, int typeno, ltsmin_parse_env_t env, model_t model) { switch(e->node_type) { case VAR: case CHUNK: case INT: break; default: return; } chunk c; data_format_t format = lts_type_get_format(GBgetLTStype(model), typeno); switch (format) { case LTStypeDirect: case LTStypeRange: if (INT != e->node_type) Abort ("Expected an integer value for comparison: %s", LTSminPrintExpr(top, env)); break; case LTStypeEnum: case LTStypeChunk: c.data = env->buffer; c.len = LTSminSPrintExpr(c.data, e, env); HREassert (c.len < ENV_BUFFER_SIZE, "Buffer overflow in print expression"); lookup_type_value (e, typeno, c, model, format==LTStypeEnum); Debug ("Bound '%s' to %d in table for type '%s'", c.data, e->num, lts_type_get_state_type(GBgetLTStype(model),typeno)); break; } }
static const char* data_format_string(lts_type_t t,int typeno){ int f=lts_type_get_format(t,typeno); switch(f){ case LTStypeDirect: return "direct"; case LTStypeRange: { char tmp[256]; sprintf(tmp,"[%d,%d]",lts_type_get_min(t,typeno),lts_type_get_max(t,typeno)); return strdup(tmp); } case LTStypeChunk: return "chunk"; case LTStypeEnum: return "enum"; } Abort("illegal format value: %d",f); }
int print_chunk (model_t model, char *res, int max, int typeno, int val) { chunk c; switch (lts_type_get_format (GBgetLTStype(model), typeno)) { case LTStypeDirect: case LTStypeRange: return snprintf (res, max, "%d", val); case LTStypeEnum: case LTStypeChunk: c = pins_chunk_get (model, typeno, val); return snprintf (res, max, "%s", c.data); default: { HREassert(false); return -1; } } }
static int type_min (check_ctx_t *ctx, int idx) { model_t model = ctx->parent; lts_type_t ltstype = GBgetLTStype (model); int typeno = lts_type_get_state_typeno (ltstype, idx); switch (lts_type_get_format (ltstype, typeno)) { case LTStypeRange: return lts_type_get_min (ltstype, typeno); case LTStypeDirect: case LTStypeEnum: case LTStypeChunk: case LTStypeBool: case LTStypeTrilean: case LTStypeSInt32: return 0; default: { HREassert(false); return -1; } } }
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); }
int main(int argc, char *argv[]){ char* files[2]; HREinitBegin(argv[0]); HREaddOptions(options,"Tool for transforming labeled transition systems\n\nOptions"); lts_lib_setup(); HREinitStart(&argc,&argv,1,2,files,"<input> [<output>]"); int me=HREme(HREglobal()); int peers=HREpeers(HREglobal()); if (peers>1) Abort("parallelizing this tool is future work");(void)me; string_set_t label_set=NULL; if (label_filter!=NULL){ label_set=SSMcreateSWPset(label_filter); } switch(task){ case Undefined: Abort("task unspecified"); case LTScopy: if (files[1]==NULL) Abort("second argument required for copy."); Print(infoShort,"streaming copy from %s to %s",files[0],files[1]); lts_file_t in=lts_file_open(files[0]); lts_type_t ltstype=lts_file_get_type(in); rd_seg=lts_file_get_segments(in); if (wr_seg==0) { wr_seg=rd_seg; } else { Abort("on-the-fly changing the number of segments is future work"); } lts_file_t out; if (label_set==NULL){ out=lts_file_create(files[1],ltstype,wr_seg,in); } else { out=lts_file_create_filter(files[1],ltstype,label_set,wr_seg,in); } int N=lts_type_get_type_count(ltstype); for(int i=0;i<N;i++){ char*name=lts_type_get_type(ltstype,i); switch(lts_type_get_format(ltstype,i)){ case LTStypeDirect: case LTStypeRange: Debug("integer type %s does not use tables",name); break; case LTStypeChunk: case LTStypeEnum: Debug("creating table for type %s",name); value_table_t tmp=chunk_table_create(NULL,name); Debug("set in %s",name); lts_file_set_table(in,i,tmp); Debug("set out %s",name); lts_file_set_table(out,i,tmp); break; } } lts_file_copy(in,out); lts_file_close(out); lts_file_close(in); break; case LTSrdwr: if (files[1]==NULL) Abort("second argument required for rdwr."); Print(infoShort,"loading from %s",files[0]); lts_t lts=lts_create(); lts_read(files[0],lts); if (encode) { Print(infoShort,"single edge label encoding"); lts=lts_encode_edge(lts); } if (bfs_reorder) { Print(infoShort,"reindexing LTS in BFS order"); lts_bfs_reorder(lts); } Print(infoShort,"storing in %s",files[1]); if(wr_seg==0) wr_seg=1; lts_write(files[1],lts,label_set,wr_seg); break; case LTSindex:{ if (peers>1) Abort("parallelizing this tool is future work"); if (files[1]==NULL) Abort("second argument required for index."); Print(infoShort,"opening %s",files[0]); lts_file_t in=lts_file_open(files[0]); lts_type_t ltstype=lts_file_get_type(in); int segments=lts_file_get_segments(in); lts_file_t settings=lts_get_template(in); if (lts_file_get_edge_owner(settings)!=SourceOwned) Abort("bad edge owner"); lts_file_set_dest_mode(settings,Index); lts_file_set_init_mode(settings,Index); Print(infoShort,"creating %s",files[1]); lts_file_t out=lts_file_create(files[1],ltstype,segments,settings); int N=lts_type_get_type_count(ltstype); for(int i=0;i<N;i++){ char*name=lts_type_get_type(ltstype,i); switch(lts_type_get_format(ltstype,i)){ case LTStypeDirect: case LTStypeRange: Debug("integer type %s does not use tables",name); break; case LTStypeChunk: case LTStypeEnum: Debug("creating table for type %s",name); value_table_t tmp=chunk_table_create(NULL,name); Debug("set in %s",name); lts_file_set_table(in,i,tmp); Debug("set out %s",name); lts_file_set_table(out,i,tmp); break; } } treedbs_t db[segments]; int SV=lts_type_get_state_length(ltstype); int SL=lts_type_get_state_label_count(ltstype); int K=lts_type_get_edge_label_count(ltstype); for(int i=0;i<segments;i++){ Print(info,"loading and copying states of segment %d",i); uint32_t state[SV]; uint32_t label[SL]; db[i]=TreeDBScreate(SV); int idx=0; while(lts_read_state(in,&i,state,label)){ int tmp=TreeFold(db[i],(int*)state); if (idx!=tmp){ Abort("unexpected index %u != %u",tmp,idx); } idx++; lts_write_state(out,i,(int*)state,label); } } Print(info,"converting initial states"); { uint32_t seg; uint32_t state[SV]; while(lts_read_init(in,(int*)&seg,state)){ int idx=TreeFold(db[seg],(int*)state); lts_write_init(out,seg,&idx); } } for(int i=0;i<segments;i++){ Print(info,"converting edges of segment %d",i); uint32_t src_state[1]; uint32_t dst_seg; uint32_t dst_state[SV]; uint32_t label[K]; while(lts_read_edge(in,&i,src_state,(int*)&dst_seg,dst_state,label)){ int idx=TreeFold(db[dst_seg],(int*)dst_state); lts_write_edge(out,i,src_state,dst_seg,&idx,label); } } lts_file_close(out); lts_file_close(in); } } Print(infoShort,"done"); HREexit(LTSMIN_EXIT_SUCCESS); }
void DVE2loadGreyboxModel(model_t model, const char *filename) { lts_type_t ltstype; matrix_t *dm_info = RTmalloc(sizeof(matrix_t)); matrix_t *dm_read_info = RTmalloc(sizeof(matrix_t)); matrix_t *dm_actions_read_info = RTmalloc(sizeof(matrix_t)); matrix_t *dm_may_write_info = RTmalloc(sizeof(matrix_t)); matrix_t *dm_must_write_info = RTmalloc(sizeof(matrix_t)); matrix_t *sl_info = RTmalloc(sizeof(matrix_t)); //assume sequential use: if (NULL == dlHandle) { char *extension = strrchr (filename, '.'); HREassert (extension != NULL, "No filename extension %s", filename); ++extension; if (0==strcmp (extension, "dve2C") || 0==strcmp (extension, "so")) { DVE2loadDynamicLib(model, filename); } else { DVE2compileGreyboxModel(model, filename); } } gb_context_t ctx=(gb_context_t)RTmalloc(sizeof(struct grey_box_context)); GBsetContext(model,ctx); // get ltstypes int state_length = get_state_variable_count(); ltstype=lts_type_create(); // adding types int ntypes = get_state_variable_type_count(); for(int i = 0; i < ntypes; i++) { const char* type_name = get_state_variable_type_name(i); HREassert (type_name != NULL, "invalid type name"); if (lts_type_add_type(ltstype, type_name, NULL) != i) { Abort("wrong type number"); } int type_value_count = get_state_variable_type_value_count(i); if (0 == type_value_count) { lts_type_set_format (ltstype, i, LTStypeDirect); } else { lts_type_set_format (ltstype, i, LTStypeEnum); } } int guard_type = lts_type_add_type (ltstype, "guard", NULL); lts_type_set_format (ltstype, guard_type, LTStypeTrilean); lts_type_set_state_length(ltstype, state_length); // set state name & type for(int i=0; i < state_length; ++i) { const char* name = get_state_variable_name(i); const int type = get_state_variable_type(i); lts_type_set_state_name(ltstype,i,name); lts_type_set_state_typeno(ltstype,i,type); } // compute state label names int nguards = get_guard_count(); // TODO: should be in model has guards block..? int sl_size = 0 + nguards + (have_property() ? 1 : 0); // assumption on state labels: // state labels (idx): 0 - nguards-1 = guard state labels // state label (idx): nguards = property state label lts_type_set_state_label_count (ltstype, sl_size); char buf[256]; for(int i=0; i < nguards; i++) { snprintf(buf, 256, "%s_%d", LTSMIN_LABEL_TYPE_GUARD_PREFIX, i); lts_type_set_state_label_name (ltstype, i, buf); lts_type_set_state_label_typeno (ltstype, i, guard_type); } if (have_property()) { lts_type_set_state_label_name (ltstype, nguards, LTSMIN_STATE_LABEL_ACCEPTING); lts_type_set_state_label_typeno (ltstype, nguards, guard_type); ctx->accepting_state_label_idx = nguards; } else { ctx->accepting_state_label_idx = -1; } GBsetLTStype(model, ltstype); // setting values for types for(int i=0; i < ntypes; i++) { int type_value_count = get_state_variable_type_value_count(i); if (lts_type_get_format(ltstype, i) != LTStypeChunk && lts_type_get_format(ltstype, i) != LTStypeEnum) { Debug ("Skipping type values for non-chunk type %s", lts_type_get_type(ltstype, i)); continue; } for(int j=0; j < type_value_count; ++j) { const char* type_value = get_state_variable_type_value(i, j); pins_chunk_put_at (model, i, chunk_str((char*)type_value), j); } } lts_type_validate(ltstype); int ngroups = get_transition_count(); dm_create(dm_info, ngroups, state_length); dm_create(dm_read_info, ngroups, state_length); dm_create(dm_actions_read_info, ngroups, state_length); dm_create(dm_may_write_info, ngroups, state_length); dm_create(dm_must_write_info, ngroups, state_length); for(int i=0; i < dm_nrows(dm_info); i++) { int* proj = (int*)get_transition_read_dependencies(i); for(int j=0; j<state_length; j++) { if (proj[j]) { dm_set(dm_info, i, j); dm_set(dm_read_info, i, j); } } proj = (int*)get_transition_actions_read_dependencies(i); for(int j=0; j<state_length; j++) { if (proj[j]) { dm_set(dm_actions_read_info, i, j); } } proj = (int*)get_transition_may_write_dependencies(i); for(int j=0; j<state_length; j++) { if (proj[j]) { dm_set(dm_info, i, j); dm_set(dm_may_write_info, i, j); } } proj = (int*)get_transition_must_write_dependencies(i); for(int j=0; j<state_length; j++) { if (proj[j]) { dm_set(dm_must_write_info, i, j); } } } GBsetDMInfo(model, dm_info); GBsetDMInfoRead(model, dm_read_info); GBsetMatrix(model, LTSMIN_MATRIX_ACTIONS_READS, dm_actions_read_info, PINS_MAY_SET, PINS_INDEX_GROUP, PINS_INDEX_STATE_VECTOR); GBsetDMInfoMayWrite(model, dm_may_write_info); GBsetDMInfoMustWrite(model, dm_must_write_info); // set state label matrix (accepting label and guards) get_label_method_t sl_long = NULL; get_label_all_method_t sl_all = NULL; dm_create(sl_info, sl_size, state_length); // if the model exports a property, reserve first for accepting label if (have_property()) { for (int i=0; i<state_length; ++i) { if (strcmp ("LTL_property", lts_type_get_state_name(ltstype, i)) == 0) { dm_set(sl_info, ctx->accepting_state_label_idx, i); } } } // if the model has guards, add guards as state labels if (have_property()) { // filter the property sl_long = sl_long_p_g; sl_all = sl_all_p_g; } else { // pass request directly to dynamic lib sl_long = (get_label_method_t) get_guard; sl_all = (get_label_all_method_t) get_guard_all; } // set the guards per transition group GBsetGuardsInfo(model, (guard_t**) get_all_guards()); // initialize state label matrix // assumption, guards come first (0-nguards) for(int i=0; i < nguards; i++) { int* guards = (int*)get_guard_matrix(i); for(int j=0; j<state_length; j++) { if (guards[j]) dm_set(sl_info, i, j); } } // set guard may be co-enabled relation if (get_guard_may_be_coenabled_matrix) { matrix_t *gce_info = RTmalloc(sizeof(matrix_t)); dm_create(gce_info, nguards, nguards); for(int i=0; i < nguards; i++) { int* guardce = (int*)get_guard_may_be_coenabled_matrix(i); for(int j=0; j<nguards; j++) { if (guardce[j]) dm_set(gce_info, i, j); } } GBsetGuardCoEnabledInfo(model, gce_info); } // set guard necessary enabling set info if (get_guard_nes_matrix) { matrix_t *gnes_info = RTmalloc(sizeof(matrix_t)); dm_create(gnes_info, nguards, ngroups); for(int i=0; i < nguards; i++) { int* guardnes = (int*)get_guard_nes_matrix(i); for(int j=0; j<ngroups; j++) { if (guardnes[j]) dm_set(gnes_info, i, j); } } GBsetGuardNESInfo(model, gnes_info); } // set guard necessary disabling set info if (get_guard_nds_matrix) { matrix_t *gnds_info = RTmalloc(sizeof(matrix_t)); dm_create(gnds_info, nguards, ngroups); for(int i=0; i < nguards; i++) { int* guardnds = (int*)get_guard_nds_matrix(i); for(int j=0; j<ngroups; j++) { if (guardnds[j]) dm_set(gnds_info, i, j); } } GBsetGuardNDSInfo(model, gnds_info); } if (!get_dna_matrix) { Warning (info, "*** Warning ***"); Warning (info, "You are using an old version of our patched DiVinE compiler."); Warning (info, "This might influence the performance of partial order reduction negatively."); Warning (info, "Please download the latest from: http://fmt.cs.utwente.nl/tools/ltsmin/"); Warning (info, "*** Warning ***"); } else { matrix_t *dna_info = RTmalloc(sizeof(matrix_t)); dm_create(dna_info, ngroups, ngroups); for(int i=0; i < ngroups; i++) { int* dna = (int*)get_dna_matrix(i); for(int j=0; j<ngroups; j++) { if (dna[j]) dm_set(dna_info, i, j); } } GBsetDoNotAccordInfo(model, dna_info); } // set the group implementation sl_group_t* sl_group_all = RTmallocZero(sizeof(sl_group_t) + sl_size * sizeof(int)); sl_group_all->count = sl_size; for(int i=0; i < sl_group_all->count; i++) sl_group_all->sl_idx[i] = i; sl_group_t* sl_group_guards = RTmallocZero(sizeof(sl_group_t) + nguards * sizeof(int)); sl_group_guards->count = nguards; for(int i=0; i < sl_group_guards->count; i++) sl_group_guards->sl_idx[i] = i; GBsetStateLabelGroupInfo(model, GB_SL_ALL, sl_group_all); GBsetStateLabelGroupInfo(model, GB_SL_GUARDS, sl_group_guards); GBsetStateLabelsGroup(model, sl_group); GBsetStateLabelInfo(model, sl_info); if (sl_long != NULL) GBsetStateLabelLong(model, sl_long); if (sl_all != NULL) GBsetStateLabelsAll(model, sl_all); // get initial state int state[state_length]; get_initial_state((char*)state); GBsetInitialState(model,state); GBsetNextStateAll (model, (next_method_black_t) get_successors); GBsetNextStateLong (model, (next_method_grey_t) get_successor); GBsetActionsLong (model, (next_method_grey_t) get_action); }