/* Copyright (c) 1992, 1993 Regents of the University of California All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. However, any distribution of this software or derivative works must include the above copyright notice. This software is made available AS IS, and neither the Electronics Research Laboratory or the Universify of California make any warranty about the software, its performance or its conformity to any specification. Author: Szu-Tsung Cheng, stcheng@ic.Berkeley.EDU 10/92 10/93 $Header: /projects/development/hsv/CVSRepository/vl2mv/src/parser/vl_flowgraph.c,v 1.2 2009/03/09 20:25:58 fabio Exp $ */ #include "util.h" #include "st.h" #include "list.h" #include "array.h" #include "set.h" #include "stack.h" #include "graph.h" #include "vl_defs.h" #include "vl_types.h" #include "vlr_int.h" #include "vl_fg_defs.h" #include "vl_fg_types.h" #include "vl_flowgraph.h" #include "vl_create.h" #include "vl_write.h" #include "vl_write_util.h" #include "vl_edgedetector.h" #include "verilog.h" #define IABS(x) (((x)>=0)?(x):(-(x))) extern double vl_expr_aux1_val, vl_expr_aux2_val, vl_expr_aux3_val; extern int vl_expr_aux1_flag, vl_expr_aux2_flag, vl_expr_aux3_flag; extern graph_t *vl_writeFlowGraph; extern int encodeTimer; extern int vl_preDeclare; extern int vl_noTimers; int RQautomata=1; static graph_t *vl_currentFlowGraph=NIL(graph_t); static graph_t *vl_currentCMPFlowGraph=NIL(graph_t); static graph_t *workingFlowGraph=NIL(graph_t); static vertex_t *fg_Srce, *fg_Sink; static vertex_t *fg_CMPSrce, *fg_CMPSink; static int pause_counter=1; static FILE *fg_out_file = NIL(FILE); static char *new_pausename() { static char retval[MAXSTRLEN]; sprintf(retval, "%s%d%s", FG_LLOC, pause_counter++, FG_RLOC); return retval; } graph_t *fg_new_graph() { vl_currentFlowGraph = g_alloc(); vl_currentCMPFlowGraph = g_alloc(); vl_currentFlowGraph->user_data = (char*)fg_new_graph_info(); return vl_currentFlowGraph; } void fg_clean_fg() { if (vl_currentFlowGraph->user_data) { ((fg_graph_info*)vl_currentFlowGraph->user_data)->pause_hi = pause_counter; } vl_currentCMPFlowGraph = vl_currentFlowGraph = NIL(graph_t); } int fg_not_empty() { return (vl_currentFlowGraph != NIL(graph_t)); } void fg_set_fg(graph_t *graph) { workingFlowGraph = graph; } void fg_record_SrcSink(vertex_t **src, vertex_t **sink, vertex_t **cmp_src, vertex_t **cmp_sink) { *src = fg_Srce; *sink = fg_Sink; *cmp_src = fg_CMPSrce; *cmp_sink = fg_CMPSink; } void fg_restore_SrcSink(vertex_t *src, vertex_t *sink, vertex_t *cmp_src, vertex_t *cmp_sink) { fg_Srce = src; fg_Sink = sink; fg_CMPSrce = cmp_src; fg_CMPSink = cmp_sink; } edge_t *fg_new_always_block() { edge_t *retval; fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Sink = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); fg_Sink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); retval = g_add_edge(fg_Sink, fg_Srce); ((fg_graph_info*)vl_currentFlowGraph->user_data)->init_node = fg_Srce; fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSink = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); fg_CMPSink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(fg_CMPSink, fg_CMPSrce); return retval; } void fg_new_seq_block() { fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Sink = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); fg_Sink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSink = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); fg_CMPSink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); } vertex_t *fg_new_loop_block(vertex_t **old_srce, vertex_t **old_sink, vertex_t **new_src, vertex_t **new_sink, vertex_t **old_cmpsrc, vertex_t **old_cmpsink, vertex_t **new_cmpsrc, vertex_t **new_cmpsink) { vertex_t *retval; *old_srce = fg_Srce; *old_sink = fg_Sink; fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Sink = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_FORBRANCH); fg_Sink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_srce, fg_Srce); retval = fg_Srce; *new_src = fg_Srce; *new_sink = fg_Sink; *old_cmpsrc = fg_CMPSrce; *old_cmpsink = fg_CMPSink; fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSink = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_FORBRANCH); fg_CMPSink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_cmpsrc, fg_CMPSrce); *new_cmpsrc = fg_CMPSrce; *new_cmpsink = fg_CMPSink; return retval; } vertex_t *fg_new_ifelse_block(old_srce, old_sink, new_src, new_sink, old_cmpsrc, old_cmpsink, new_cmpsrc, new_cmpsink) vertex_t **old_srce; vertex_t **old_sink; vertex_t **new_src; vertex_t **new_sink; vertex_t **old_cmpsrc; vertex_t **old_cmpsink; vertex_t **new_cmpsrc; vertex_t **new_cmpsink; { vertex_t *retval; *old_srce = fg_Srce; *old_sink = fg_Sink; fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Sink = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_IFBRANCH); fg_Sink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_srce, fg_Srce); retval = fg_Srce; *new_src = fg_Srce; *new_sink = fg_Sink; *old_cmpsrc = fg_CMPSrce; *old_cmpsink = fg_CMPSink; fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSink = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_IFBRANCH); fg_CMPSink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_cmpsrc, fg_CMPSrce); *new_cmpsrc = fg_CMPSrce; *new_cmpsink = fg_CMPSink; return retval; } vertex_t *fg_new_case_block(old_srce, old_sink, new_src, new_sink, old_CMPsrce, old_CMPsink, new_CMPsrc, new_CMPsink) vertex_t **old_srce; vertex_t **old_sink; vertex_t **new_src; vertex_t **new_sink; vertex_t **old_CMPsrce; vertex_t **old_CMPsink; vertex_t **new_CMPsrc; vertex_t **new_CMPsink; { vertex_t *retval; *old_srce = fg_Srce; *old_sink = fg_Sink; fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Sink = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_CASEBRANCH); fg_Sink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_srce, fg_Srce); retval = fg_Srce; *new_src = fg_Srce; *new_sink = fg_Sink; *old_CMPsrce = fg_CMPSrce; *old_CMPsink = fg_CMPSink; fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSink = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_CASEBRANCH); fg_CMPSink->user_data = (char*)fg_new_node_info(FG_ND_DUMMY); g_add_edge(*old_CMPsrce, fg_CMPSrce); *new_CMPsrc = fg_CMPSrce; *new_CMPsink = fg_CMPSink; return retval; } edge_t *fg_new_case_tag_block(cur_srce, cur_sink, cur_CMPsrce, cur_CMPsink) vertex_t *cur_srce; vertex_t *cur_sink; vertex_t *cur_CMPsrce; vertex_t *cur_CMPsink; { edge_t *new_edge; fg_Srce = g_add_vertex(vl_currentFlowGraph); fg_Srce->user_data = (char*)fg_new_node_info(FG_ND_CASETAG); new_edge = g_add_edge(cur_srce, fg_Srce); new_edge->user_data = (char*)fg_new_arc_info(FG_ARC_CASETAG); fg_CMPSrce = g_add_vertex(vl_currentCMPFlowGraph); fg_CMPSrce->user_data = (char*)fg_new_node_info(FG_ND_CASETAG); g_add_edge(cur_CMPsrce, fg_CMPSrce); return new_edge; } vertex_t *fg_new_pause_node() { vertex_t *retval, *new_vtx; retval = g_add_vertex(vl_currentFlowGraph); retval->user_data = (char*)fg_new_node_info(FG_ND_PAUSE); ((fg_node_info*)retval->user_data)->loc = vlStrdup(new_pausename()); g_add_edge(fg_Srce, retval); fg_Srce = retval; lsNewEnd(((fg_graph_info*)vl_currentFlowGraph->user_data)->pause_list, (lsGeneric)retval, 0); new_vtx = g_add_vertex(vl_currentCMPFlowGraph); new_vtx->user_data = retval->user_data; g_add_edge(fg_CMPSrce, new_vtx); fg_CMPSrce = new_vtx; return retval; } vertex_t *fg_new_assign_node() { vertex_t *retval; retval = g_add_vertex(vl_currentCMPFlowGraph); retval->user_data = (char*)fg_new_node_info(FG_ND_ASSIGN); g_add_edge(fg_CMPSrce, retval); fg_CMPSrce = retval; return retval; } int fg_reduce_simple_branches_back_block( vertex_t *old_src, vertex_t *old_sink, vertex_t *old_CMPsrc, vertex_t *old_CMPsink ) { lsList out_edges; lsGen gen; lsHandle handle; edge_t *edge; int contain_pause; out_edges = g_get_out_edges(fg_Srce); for (gen=lsStart(out_edges), contain_pause=0; lsNext(gen, (lsGeneric*)&edge, &handle) != LS_NOMORE; ) { if (((fg_node_info*)(fg_Srce->user_data))->type != FG_ND_CASEBRANCH) { if (g_e_dest(edge) != fg_Sink) contain_pause = 1; } else { vertex_t *dest; lsList inner_edges; lsGen inner_gen; lsHandle inner_handle; edge_t *inner_edge; dest = g_e_dest(edge); inner_edges = g_get_out_edges(dest); for (inner_gen=lsStart(inner_edges); lsNext(inner_gen, (lsGeneric*)&inner_edge, &inner_handle) != LS_NOMORE; ) { if (g_e_dest(inner_edge) != fg_Sink) contain_pause = 1; } lsFinish(inner_gen); } } lsFinish(gen); if (contain_pause) { fg_Srce = fg_Sink; fg_Sink = old_sink; } else { if (((fg_node_info*)(fg_Srce->user_data))->type == FG_ND_CASEBRANCH) { out_edges = g_get_out_edges(fg_Srce); for (gen=lsStart(out_edges); lsNext(gen, (lsGeneric*)&edge, &handle) != LS_NOMORE; ) { vertex_t *dest; dest = g_e_dest(edge); g_delete_vertex(dest, fg_clean_vertex_data, fg_clean_edge_data); } lsFinish(gen); } g_delete_vertex(fg_Srce, fg_clean_vertex_data, fg_clean_edge_data); g_delete_vertex(fg_Sink, fg_clean_vertex_data, fg_clean_edge_data); fg_Srce = old_src; fg_Sink = old_sink; } fg_CMPSrce = fg_CMPSink; fg_CMPSink = old_CMPsink; return contain_pause; } fg_graph_info *fg_new_graph_info() { fg_graph_info *retval; retval = (fg_graph_info*)chk_malloc(sizeof(fg_graph_info)); retval->type = 0; retval->fg_id = -1; retval->init_node = NIL(vertex_t); retval->pause_lo = retval->pause_hi = pause_counter; retval->pause_list = lsCreate(); return retval; } fg_node_info *fg_new_node_info(type) int type; { fg_node_info *retval; retval = (fg_node_info*)chk_malloc(sizeof(fg_node_info)); retval->type = type; retval->data = NIL(char); retval->loc = NIL(char); retval->SRFSMnode = NIL(ctrlNetNode); return retval; } fg_arc_info *fg_new_arc_info(type) int type; { fg_arc_info *retval; retval = (fg_arc_info*)chk_malloc(sizeof(fg_arc_info)); retval->type = type; retval->data = NIL(char); return retval; } edge_t *fg_force_edge(src, sink, CMPsrc, CMPsink) vertex_t *src; vertex_t *sink; vertex_t *CMPsrc; vertex_t *CMPsink; { edge_t *retval; retval = g_add_edge(src, sink); g_add_edge(CMPsrc, CMPsink); return retval; } edge_t *fg_closeloop() { edge_t *retval; if (fg_Srce == NIL(vertex_t) && fg_Sink == NIL(vertex_t)) return NIL(edge_t); retval = g_add_edge(fg_Srce, fg_Sink); g_add_edge(fg_CMPSrce, fg_CMPSink); return retval; } vertex_t *fg_pseudo_sink() { vertex_t *retval; vertex_t *pseudo_sink, *pseudo_CMPsink; if (fg_Srce == NIL(vertex_t) && fg_Sink == NIL(vertex_t)) return NIL(vertex_t); pseudo_sink = g_add_vertex(vl_currentFlowGraph); pseudo_CMPsink = g_add_vertex(vl_currentCMPFlowGraph); pseudo_sink->user_data = (char*)fg_new_node_info(FG_ND_PAUSE); pseudo_CMPsink->user_data = (char*)fg_new_node_info(FG_ND_PAUSE); ((fg_node_info*)pseudo_sink->user_data)->loc = vlStrdup(new_pausename()); lsNewEnd(((fg_graph_info*)vl_currentFlowGraph->user_data)->pause_list, (lsGeneric)pseudo_sink, 0); g_add_edge(fg_Srce, pseudo_sink); g_add_edge(fg_CMPSrce, pseudo_CMPsink); retval = pseudo_sink; return retval; } int fg_check_cyclic() { if (fg_Srce == NIL(vertex_t) && fg_Sink == NIL(vertex_t)) return 1; return !g_is_acyclic(vl_currentFlowGraph); } void fg_clean_vertex_data(user_data) gGeneric user_data; { if (!user_data) return; if (!((fg_node_info*)user_data)->data) return; ((vl_expr*)(((fg_node_info*)user_data)->data))->fg_info1 = NIL(char); ((vl_expr*)(((fg_node_info*)user_data)->data))->fg_info2 = NIL(char); ((vl_expr*)(((fg_node_info*)user_data)->data))->fg_aux1 = NIL(char); ((vl_expr*)(((fg_node_info*)user_data)->data))->fg_aux2 = NIL(char); free((fg_node_info*)user_data); } void fg_clean_edge_data(user_data) gGeneric user_data; { if (!user_data) return; if (!((fg_arc_info*)user_data)->data) return; ((vl_case_item*)(((fg_arc_info*)user_data)->data))->fg_info = NIL(char); free((fg_node_info*)user_data); } void fg_update_node_info(vertex_t *vtx, char *data) { ((fg_node_info*)vtx->user_data)->data = data; } void fg_update_arc_info(edge_t *arc, char *data) { ((fg_arc_info*)arc->user_data)->data = data; } static void fg_dfs_int(src, sink, vtx_massager, arc_massager, visit_st) vertex_t *src; vertex_t *sink; void (*vtx_massager)(); void (*arc_massager)(); st_table *visit_st; { edge_t *e; vertex_t *v; int val; lsList visit_list; lsGen gen; lsHandle handle; if (src==sink) { if (!st_lookup(visit_st, (char*)sink, (char**)&val)) { if (vtx_massager) (*vtx_massager)(sink->user_data); st_insert(visit_st, (char*)sink, (char*)0); } return; } if (vtx_massager) (*vtx_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); visit_list = g_get_out_edges(src); for (gen=lsStart(visit_list); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { if (arc_massager) (*arc_massager)(e->user_data); v = g_e_dest(e); if (!st_lookup(visit_st, (char*)v, (char**)&val)) { fg_dfs_int(v, sink, vtx_massager, arc_massager, visit_st); } } lsFinish(gen); } int fg_dfs(src, sink, vtx_massager, arc_massager) vertex_t *src; vertex_t *sink; void (*vtx_massager)(); void (*arc_massager)(); { st_table *visit_st; if (sink) if (g_vertex_graph(src) != g_vertex_graph(sink)) return 0; visit_st = st_init_table(st_ptrcmp, st_ptrhash); fg_dfs_int(src, sink, vtx_massager, arc_massager, visit_st); st_free_table(visit_st); return 1; } static void fg_back_dfs_int(src, leaf_criterion, vtx_massager, arc_massager, visit_st) vertex_t *src; int (*leaf_criterion)(); void (*vtx_massager)(); void (*arc_massager)(); st_table *visit_st; { edge_t *e; vertex_t *v; int val; lsList visit_list; lsGen gen; lsHandle handle; if ((*leaf_criterion)(src->user_data)) { if (!st_lookup(visit_st, (char*)src, (char**)&val)) { if (vtx_massager) (*vtx_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); } return; } if (vtx_massager) (*vtx_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); visit_list = g_get_in_edges(src); for (gen=lsStart(visit_list); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { if (arc_massager) (*arc_massager)(e->user_data); v = g_e_source(e); if (!st_lookup(visit_st, (char*)v, (char**)&val)) { fg_back_dfs_int(v, leaf_criterion, vtx_massager, arc_massager, visit_st); } } lsFinish(gen); } int fg_back_dfs(src, leaf_criterion, vtx_massager, arc_massager) vertex_t *src; int (*leaf_criterion)(); void (*vtx_massager)(); void (*arc_massager)(); { st_table *visit_st; if (!src) return 0; visit_st = st_init_table(st_ptrcmp, st_ptrhash); fg_back_dfs_int(src, leaf_criterion, vtx_massager, arc_massager, visit_st); st_free_table(visit_st); return 1; } static void fg_fore_dfs_int(src, leaf_criterion, vtx_massager, arc_massager, visit_st) vertex_t *src; int (*leaf_criterion)(); void (*vtx_massager)(); void (*arc_massager)(); st_table *visit_st; { edge_t *e; vertex_t *v; int val; lsList visit_list; lsGen gen; lsHandle handle; if ((*leaf_criterion)(src->user_data)) { if (!st_lookup(visit_st, (char*)src, (char**)&val)) { if (vtx_massager) (*vtx_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); } return; } if (vtx_massager) (*vtx_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); visit_list = g_get_out_edges(src); for (gen=lsStart(visit_list); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { if (arc_massager) (*arc_massager)(e->user_data); v = g_e_dest(e); if (!st_lookup(visit_st, (char*)v, (char**)&val)) { fg_fore_dfs_int(v, leaf_criterion, vtx_massager, arc_massager, visit_st); } } lsFinish(gen); } int fg_fore_dfs(src, leaf_criterion, vtx_massager, arc_massager) vertex_t *src; int (*leaf_criterion)(); void (*vtx_massager)(); void (*arc_massager)(); { st_table *visit_st; if (!src) return 0; visit_st = st_init_table(st_ptrcmp, st_ptrhash); fg_fore_dfs_int(src, leaf_criterion, vtx_massager, arc_massager, visit_st); st_free_table(visit_st); return 1; } static void fg_gen_fore_dfs_int(src, leaf_criterion, leaf_massager, vtx_pre_massager, vtx_in_massager, vtx_post_massager, arc_pre_massager, arc_post_massager, visit_st, all_paths) vertex_t *src; int (*leaf_criterion)(); void (*leaf_massager)(); void (*vtx_pre_massager)(); void (*vtx_in_massager)(); void (*vtx_post_massager)(); void (*arc_pre_massager)(); void (*arc_post_massager)(); st_table *visit_st; int all_paths; { int i; edge_t *e; vertex_t *v; int val; lsList visit_list; lsGen gen; lsHandle handle; if ((*leaf_criterion)(src->user_data)) { if (!st_lookup(visit_st, (char*)src, (char**)&val) || all_paths) { if (vtx_pre_massager) (*vtx_pre_massager)(src->user_data); if (leaf_massager) (*leaf_massager)(src->user_data); if (vtx_post_massager) (*vtx_post_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); } return; } if (vtx_pre_massager) (*vtx_pre_massager)(src->user_data); st_insert(visit_st, (char*)src, (char*)0); visit_list = g_get_out_edges(src); for (gen=lsStart(visit_list), i=0; lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; i++) { if (arc_pre_massager) (*arc_pre_massager)(e->user_data); v = g_e_dest(e); if (!st_lookup(visit_st, (char*)v, (char**)&val) || all_paths) { fg_gen_fore_dfs_int(v, leaf_criterion, leaf_massager, vtx_pre_massager, vtx_in_massager, vtx_post_massager, arc_pre_massager, arc_post_massager, visit_st, all_paths); } if (vtx_in_massager) (*vtx_in_massager)(src->user_data, e->user_data); if (arc_post_massager) (*arc_post_massager)(e->user_data); } lsFinish(gen); if (vtx_post_massager) (*vtx_post_massager)(src->user_data, src); } int fg_gen_fore_dfs(src, leaf_criterion, leaf_massager, vtx_pre_massager, vtx_in_massager, vtx_post_massager, arc_pre_massager, arc_post_massager, all_paths) vertex_t *src; int (*leaf_criterion)(); void (*leaf_massager)(); void (*vtx_pre_massager)(); void (*vtx_in_massager)(); void (*vtx_post_massager)(); void (*arc_pre_massager)(); void (*arc_post_massager)(); int all_paths; { st_table *visit_st; if (!src) return 0; visit_st = st_init_table(st_ptrcmp, st_ptrhash); fg_gen_fore_dfs_int(src, leaf_criterion, leaf_massager, vtx_pre_massager, vtx_in_massager, vtx_post_massager, arc_pre_massager, arc_post_massager, visit_st, all_paths); st_free_table(visit_st); return 1; } static st_table *pause_set=NIL(st_table); static void remember_pause(user_data) gGeneric user_data; { char *loc; if (((fg_node_info*)user_data)->type == FG_ND_PAUSE) { if (((fg_node_info*)user_data)->loc) loc = ((fg_node_info*)user_data)->loc; else loc = ((fg_node_info*)user_data)->loc = vlStrdup(new_pausename()); st_insert(pause_set, loc, (char*)0); } } static st_table *terminal_set=NIL(st_table); static st_table *full_terminal_set=NIL(st_table); static int terminal_set_count=1; static void remember_node_terminal(user_data) gGeneric user_data; { vl_term *key; int val; vl_event_control_stmt *pause_stmt; if (!user_data) return; key = (vl_term*)((fg_node_info*)user_data)->data; if (((fg_node_info*)user_data)->type == FG_ND_IFBRANCH || ((fg_node_info*)user_data)->type == FG_ND_FORBRANCH) { if (!st_lookup(terminal_set, (char*)key, (char**)&val)) { if (full_terminal_set) { int retval = st_lookup(full_terminal_set, (char*)key, (char**)&val); assert(retval); st_insert(terminal_set, (char*)key, (char*)val); } else { st_insert(terminal_set, (char*)key, (char*)terminal_set_count); terminal_set_count++; } } } else if (((fg_node_info*)user_data)->type == FG_ND_PAUSE) { vl_term *edge_ctrl = NIL(vl_term); pause_stmt = (vl_event_control_stmt*)((fg_node_info*)user_data)->data; if (pause_stmt->type == EventControlStmt) { if (!full_terminal_set) { if (!st_lookup(terminal_set, pause_stmt->fg_info, (char**)&val)) { if (!vl_preDeclare) { if (pause_stmt->event->type == OrEventExpr) { edge_ctrl = write_ored_edge_detector(fg_out_file, pause_stmt->event); } else { edge_ctrl = write_edge_detector(fg_out_file, pause_stmt->event->expr, (pause_stmt->event->type==PosedgeEventExpr)?1: (pause_stmt->event->type==NegedgeEventExpr)?-1: 0); edge_ctrl->flag |= EdgeSignal; } } pause_stmt->fg_info = (char*)edge_ctrl; st_insert(terminal_set, (char*)edge_ctrl, (char*)(FG_MAGIC_UB_EDGE+terminal_set_count)); terminal_set_count++; } } else { int retval = st_lookup(full_terminal_set, pause_stmt->fg_info, (char**)&val); assert(retval); st_insert(terminal_set, pause_stmt->fg_info, (char*)val); } } } } static void switch_node_branch(user_data, edge_data) gGeneric user_data; gGeneric edge_data; { vl_term *key; int val; if (!user_data) return; key = (vl_term*)((fg_node_info*)user_data)->data; if (((fg_node_info*)user_data)->type == FG_ND_IFBRANCH || ((fg_node_info*)user_data)->type == FG_ND_FORBRANCH) { int retval = st_lookup(terminal_set, (char*)key, (char**)&val); assert(retval); st_delete(terminal_set, (char**)&key, (char**)&val); st_insert(terminal_set, (char*)key, (char*)-val); } else if (((fg_node_info*)user_data)->type == FG_ND_CASEBRANCH) { int retval; key = (vl_term*)((fg_arc_info*)edge_data)->data; retval = st_lookup(terminal_set, (char*)key, (char**)&val); assert(retval); st_delete(terminal_set, (char**)&key, (char**)&val); st_insert(terminal_set, (char*)key, (char*)-val); } } static void forget_node_terminal(user_data, v) gGeneric user_data; vertex_t *v; { vl_term *key; int val; if (!user_data) return; key = (vl_term*)((fg_node_info*)user_data)->data; if (((fg_node_info*)user_data)->type == FG_ND_IFBRANCH || ((fg_node_info*)user_data)->type == FG_ND_FORBRANCH) { key = (vl_term*)((fg_node_info*)user_data)->data; if (st_lookup(terminal_set, (char*)key, (char**)&val)) st_delete(terminal_set, (char**)&key, (char**)&val); } else if (((fg_node_info*)user_data)->type == FG_ND_CASEBRANCH) { lsList e_list; lsGen gen; lsHandle handle; edge_t *e; e_list = g_get_out_edges(v); for (gen=lsStart(e_list); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { if (!e->user_data) continue; if (((fg_arc_info*)e->user_data)->type == FG_ND_CASETAG) { key = (vl_term*)((fg_arc_info*)e->user_data)->data; if (st_lookup(terminal_set, (char*)key, (char**)&val)) st_delete(terminal_set, (char**)&key, (char**)&val); } } lsFinish(gen); } else if (((fg_node_info*)user_data)->type ==FG_ND_PAUSE) { vl_event_control_stmt *pause_stmt; pause_stmt = (vl_event_control_stmt*)((fg_node_info*)user_data)->data; if (pause_stmt->type == EventControlStmt) { key = (vl_term*)pause_stmt->fg_info; if (st_lookup(terminal_set, (char*)key, (char**)&val)) st_delete(terminal_set, (char**)&key, (char**)&val); } } } static void remember_arc_terminal(user_data) gGeneric user_data; { vl_term *key; int val; if (!user_data) return; key = (vl_term*)((fg_arc_info*)user_data)->data; if (((fg_arc_info*)user_data)->type == FG_ND_CASETAG) { if (!st_lookup(terminal_set, (char*)key, (char**)&val)) { if (full_terminal_set) { int retval = st_lookup(full_terminal_set, (char*)key, (char**)&val); assert(retval); st_insert(terminal_set, (char*)key, (char*)val); } else { st_insert(terminal_set, (char*)key, (char*)terminal_set_count); terminal_set_count++; } } } } static void forget_arc_terminal(user_data) gGeneric user_data; { if (!user_data) return; if (((fg_arc_info*)user_data)->type == FG_ND_CASETAG) { /* nothing */ } } void fg_if_collect_pause_rewrite_ctrl(file, src, sink, spacial_ctrl) FILE *file; vertex_t *src; vertex_t *sink; vl_term **spacial_ctrl; { vl_term *t_lc_control=NIL(vl_term), *f_lc_control=NIL(vl_term); vl_term *new_lc_ctrl; vertex_t *branch_src; edge_t *branch_edge; int i; lsList out_edges; lsGen gen; lsHandle handle; out_edges = g_get_out_edges(src); for (gen=lsStart(out_edges), i=0; lsNext(gen, (lsGeneric*)&branch_edge, &handle)!=LS_NOMORE; i++) { int retval; pause_set = st_init_table(strcmp, st_strhash); branch_src = g_e_dest(branch_edge); retval = fg_dfs(branch_src, sink, remember_pause, 0); assert(retval); if (i==0) t_lc_control = fg_write_lc_in_LabelSet(file, pause_set, 0); else f_lc_control = fg_write_lc_in_LabelSet(file, pause_set, 0); st_free_table(pause_set); pause_set = NIL(st_table); } lsFinish(gen); new_lc_ctrl = fg_write_if_priority_decoder(file, t_lc_control, f_lc_control, *spacial_ctrl); *spacial_ctrl = new_lc_ctrl; } void fg_case_collect_pause_rewrite_ctrl(FILE *file, vertex_t *src, vertex_t *sink, vl_term **spacial_ctrl, vl_term **temporal_ctrl) { vl_term *ripple_in; vl_term *lc_control; vl_term *new_lc_ctrl; pause_set = st_init_table(strcmp, st_strhash); fg_dfs(src, sink, remember_pause, 0); ripple_in = new_term(NIL(vl_range), 0, -1); lc_control = fg_write_lc_in_LabelSet(file, pause_set, 0); new_lc_ctrl = fg_write_case_priority_decoder(file, ripple_in, *temporal_ctrl, lc_control, *spacial_ctrl); *spacial_ctrl = new_lc_ctrl; *temporal_ctrl = ripple_in; st_free_table(pause_set); pause_set = NIL(st_table); } void fg_loop_collect_pause(FILE *file, vertex_t *src, vertex_t *sink, vl_term **dom_sel) { vl_term *t_lc_control=NIL(vl_term); vertex_t *branch_src; edge_t *branch_edge; int i; lsList out_edges; lsGen gen; lsHandle handle; out_edges = g_get_out_edges(src); for (gen=lsStart(out_edges), i=0; lsNext(gen, (lsGeneric*)&branch_edge, &handle)!=LS_NOMORE; i++) { int retval; pause_set = st_init_table(strcmp, st_strhash); branch_src = g_e_dest(branch_edge); retval = fg_dfs(branch_src, sink, remember_pause, 0); assert(retval); if (i==0) t_lc_control = fg_write_lc_in_LabelSet(file, pause_set, -1); st_free_table(pause_set); pause_set = NIL(st_table); } lsFinish(gen); *dom_sel = t_lc_control; } vl_term *fg_write_lc_in_LabelSet(file, pause_set, ns) FILE *file; st_table* pause_set; int ns; { vl_term *retval; st_generator *gen; int *val; char *key; char *timer_st; retval = new_term(NIL(vl_range), 0, -1); timer_st = (ns==-1) ? FG_TIMER_PS : ((ns) ? FG_LC_NS : FG_LC_PS); if (st_count(pause_set)==0) { fprintf(file, ".names %s\n0\n", retval->name->name); } else { fprintf(file, ".names %s%06x %s\n", timer_st, ((fg_graph_info*)vl_writeFlowGraph->user_data)->fg_id, retval->name->name); fprintf(file, "%s 0\n", HSIS_DEFAULT); gen = st_init_gen(pause_set); while (st_gen(gen, &key, (char**)&val)) { if (RQautomata) fprintf(file, "%s 1\n%s%s 1\n", key, key, FG_TIMER_PRIME); else fprintf(file, "%s 1\n", key); } st_free_gen(gen); } return retval; } vl_term * fg_write_if_priority_decoder(file, t_local_lc, f_local_lc, spacial_ctrl) FILE *file; vl_term *t_local_lc; vl_term *f_local_lc; vl_term *spacial_ctrl; { vl_term *retval; retval = new_term(NIL(vl_range), 0, -1); if (f_local_lc) { fprintf(file, ".names %s %s %s %s\n", t_local_lc->name->name, f_local_lc->name->name, spacial_ctrl->name->name, retval->name->name); fprintf(file, "1 - - 1\n"); fprintf(file, "0 1 - 0\n"); fprintf(file, "0 0 - %s%s\n", HSIS_EQUAL,spacial_ctrl->name->name); } else { fprintf(file, ".names %s %s %s\n", t_local_lc->name->name, spacial_ctrl->name->name, retval->name->name); fprintf(file, "1 - 1\n"); fprintf(file, "0 - %s%s\n", HSIS_EQUAL, spacial_ctrl->name->name); } return retval; } vl_term * fg_write_case_priority_decoder(file, ripple_in, ripple_out, local_lc, spacial_ctrl) FILE *file; vl_term *ripple_in; vl_term *ripple_out; vl_term *local_lc; vl_term *spacial_ctrl; { vl_term *retval; retval = new_term(NIL(vl_range), 0, -1); if (spacial_ctrl) { fprintf(file, ".names %s %s %s %s\n", local_lc->name->name, ripple_in->name->name, spacial_ctrl->name->name, retval->name->name); fprintf(file, "1 - - 1\n"); fprintf(file, "0 1 - 0\n"); fprintf(file, "0 0 - %s%s\n", HSIS_EQUAL, spacial_ctrl->name->name); } else { fprintf(file, ".names %s %s %s\n", local_lc->name->name, ripple_in->name->name, retval->name->name); fprintf(file, "1 - 1\n"); fprintf(file, "0 1 0\n"); fprintf(file, "0 0 1\n"); } if (ripple_out) { fprintf(file, ".names %s %s %s\n", ripple_in->name->name, local_lc->name->name, ripple_out->name->name); fprintf(file, "%s 1\n", HSIS_DEFAULT); fprintf(file, "0 0 0\n"); } return retval; } static int fg_node_is_pause(void *user_data) { return (((fg_node_info*)user_data)->type == FG_ND_PAUSE); } st_table *fg_assign_temporal_context(src) vertex_t *src; { st_table *retval; retval = pause_set = st_init_table(st_ptrcmp, st_ptrhash); fg_back_dfs(src, fg_node_is_pause, remember_pause, 0); pause_set = NIL(st_table); return retval; } void fg_put_loc_context(FILE *file, st_table *pre_cond, char *lc_name) { st_generator *gen; char *loc, *val; int i; char buf[MAXSTRLEN]; fg_graph_info *graph_info; if (st_count(pre_cond)==0) { fprintf(file, "%d", 1); return; } fprintf(file, "%s", HSIS_SET_BEGIN); i = 1; gen = st_init_gen(pre_cond); while (st_gen(gen, &loc, &val)) { graph_info = (fg_graph_info*)get_assoc_lc_name(loc, buf); if (i==st_count(pre_cond)) if (RQautomata) fprintf(file, "%s%s%s%s", loc, HSIS_SET_SEP, loc, FG_TIMER_PRIME); else fprintf(file, "%s", loc); else if (RQautomata) fprintf(file, "%s%s%s%s%s", loc, HSIS_SET_SEP, loc, FG_TIMER_PRIME, HSIS_SET_SEP); else fprintf(file, "%s%s", loc, HSIS_SET_SEP); i++; } st_free_gen(gen); fprintf(file, "%s", HSIS_SET_END); } void fg_declare_timer(file, terminal_set, graph) FILE *file; st_table *terminal_set; graph_t *graph; { fg_graph_info *gdata; int i; gdata = ((fg_graph_info*)graph->user_data); if (vl_preDeclare) { fprintf(file, ".mv %s%06x, %s%06x %d %s%d%s ", FG_LC_PS, gdata->fg_id, FG_LC_NS, gdata->fg_id, (gdata->pause_hi-gdata->pause_lo)*2+2, FG_LLOC, 0, FG_RLOC); for (i=gdata->pause_lo; ipause_hi; i++) fprintf(file, "%s%d%s %s%d%s%s ", FG_LLOC, i, FG_RLOC, FG_LLOC, i, FG_RLOC, FG_TIMER_PRIME); fprintf(file, "%s%s\n", FG_LLOC, FG_RLOC); } fprintf(file, ".mv %s%06x %d %s%d%s ", FG_TIMER_PS, gdata->fg_id, (gdata->pause_hi-gdata->pause_lo)*2+1, FG_LLOC, 0, FG_RLOC); for (i=gdata->pause_lo; ipause_hi; i++) fprintf(file, "%s%d%s %s%d%s%s ", FG_LLOC, i, FG_RLOC, FG_LLOC, i, FG_RLOC, FG_TIMER_PRIME); fprintf(file, "\n"); fprintf(file, ".mv %s%06x %d %s%d%s ", FG_TIMER_NS, gdata->fg_id, (gdata->pause_hi-gdata->pause_lo)*2+1, FG_LLOC, 0, FG_RLOC); for (i=gdata->pause_lo; ipause_hi; i++) fprintf(file, "%s%d%s %s%d%s%s ", FG_LLOC, i, FG_RLOC, FG_LLOC, i, FG_RLOC, FG_TIMER_PRIME); fprintf(file, "\n"); if (!vl_noTimers) { fprintf(file, ".timers "); for (i=((fg_graph_info*)graph->user_data)->pause_lo; i<((fg_graph_info*)graph->user_data)->pause_hi; i++) if (i<((fg_graph_info*)graph->user_data)->pause_hi-1) fprintf(file, "T%d,", i); else fprintf(file, "T%d ", i); fprintf(file, "\n"); } fprintf(file, ".latch %s%06x %s%06x\n", FG_TIMER_NS, gdata->fg_id, FG_TIMER_PS, gdata->fg_id); fprintf(file, ".r %s%06x\n%s%d%s\n", FG_TIMER_PS, gdata->fg_id, FG_LLOC, (vl_noTimers)?gdata->pause_lo:0, FG_RLOC); } void fg_put_timer_header(file, terminal_set, graph) FILE *file; st_table *terminal_set; graph_t *graph; { st_generator *gen; vl_term *key; int val; int i; fprintf(file, ".names "); for (i=1; i<=st_count(terminal_set); i++) { gen = st_init_gen(terminal_set); while (st_gen(gen, (char**)&key, (char**)&val)) { if (val == i) { fprintf(file, "%s ", key->name->name); break; } else if ((val-FG_MAGIC_UB_EDGE) == i) { fprintf(file, "%s ", key->name->name); break; } } st_free_gen(gen); } fprintf(file, "%s%06x %s %s%06x %s%06x %s%06x\n", FG_TIMER_PS, ((fg_graph_info*)graph->user_data)->fg_id, HSIS_ARROW, FG_LC_PS, ((fg_graph_info*)graph->user_data)->fg_id, FG_LC_NS, ((fg_graph_info*)graph->user_data)->fg_id, FG_TIMER_NS, ((fg_graph_info*)graph->user_data)->fg_id); fprintf(file, "%s %s%s %s%s %s%s%06x\n", HSIS_DEFAULT, FG_LLOC, FG_RLOC, FG_LLOC, FG_RLOC, HSIS_EQUAL, FG_TIMER_PS, ((fg_graph_info*)graph->user_data)->fg_id); } static vertex_t *current_source_vtx=NIL(vertex_t); static void fg_put_timer_transition(int user_data) { int i; st_generator *gen; vl_term *key; int val, ival; int control_entry=0; int src_timer, dest_timer, delay1; vl_delay_control_stmt *pausing_stmt; int primed_transition = 0; char buf[MAXSTRLEN]; char str[MAXSTRLEN]; if (((fg_node_info*)user_data)->type != FG_ND_PAUSE) return; pausing_stmt = (vl_delay_control_stmt*) ((fg_node_info*)current_source_vtx->user_data)->data; if (pausing_stmt->type != DelayControlStmt && pausing_stmt->type != EventControlStmt) return; buf[0]='\0'; if (pausing_stmt->type == EventControlStmt) { if (!st_lookup(full_terminal_set, ((vl_event_control_stmt*)pausing_stmt)->fg_info, (char**)&ival)) ival = 0; else ival -= FG_MAGIC_UB_EDGE; } if (!strcmp(((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc) && RQautomata) primed_transition = 1; for (i=1; i<=st_count(full_terminal_set); i++) { control_entry = 0; gen = st_init_gen(terminal_set); while (st_gen(gen, (char**)&key, (char**)&val)) { if (IABS(val) == i) { sprintf(str, "%c ", (val>0)?'1':'0'); control_entry=1; strcat(buf, str); break; } else if (pausing_stmt->type == EventControlStmt) { if (i==ival) { sprintf(str, "1 "); strcat(buf, str); control_entry=1; break; } } } if (i==ival && !control_entry && pausing_stmt->type == EventControlStmt) { sprintf(str, "1 "); strcat(buf, str); control_entry=1; } st_free_gen(gen); if (!control_entry) { sprintf(str, "- "); strcat(buf, str); } } if (pausing_stmt->type != DelayControlStmt) { if (!primed_transition) { if (!vl_noTimers) { fprintf(fg_out_file, "%s %s %s %s %s %s %s%d=0\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, atoi(((fg_node_info*)user_data)->loc+1)); } else { fprintf(fg_out_file, "%s %s %s %s %s\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc); } if (RQautomata) { if (!vl_noTimers) { fprintf(fg_out_file, "%s %s%s %s%s %s %s %s %s%d=0\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, atoi(((fg_node_info*)user_data)->loc+1)); } else { fprintf(fg_out_file, "%s %s%s %s%s %s %s\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc); } } } else { if (!vl_noTimers) { fprintf(fg_out_file, "%s %s %s %s%s %s%s %s %s%d=0\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, atoi(((fg_node_info*)user_data)->loc+1)); fprintf(fg_out_file, "%s %s%s %s%s %s %s %s %s%d=0\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, atoi(((fg_node_info*)user_data)->loc+1)); } else { fprintf(fg_out_file, "%s %s %s %s%s %s%s\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME); fprintf(fg_out_file, "%s %s%s %s%s %s %s\n", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc); } } } else { int idx; src_timer = atoi(((fg_node_info*)current_source_vtx->user_data)->loc+1); dest_timer = atoi(((fg_node_info*)user_data)->loc+1); vl_expr_aux1_flag = vl_expr_aux2_flag = vl_expr_aux3_flag = 0; vl_expr_aux1_val = vl_expr_aux2_val = vl_expr_aux3_val = (double)0; if (!(pausing_stmt->delay->delay3 && !pausing_stmt->delay->delay2)) delay1 = vl_eval_expr(pausing_stmt->delay->delay1); else { vl_expr *expr; lsFirstItem((lsList)pausing_stmt->delay->delay1, (lsGeneric*)&expr, 0); delay1 = vl_eval_expr(expr); } for (idx=0; idx<2; idx++) { if (idx==0) { if (!primed_transition) { fprintf(fg_out_file, "%s %s %s %s %s ", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc); } else { fprintf(fg_out_file, "%s %s %s %s%s %s%s ", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)current_source_vtx->user_data)->loc, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, FG_TIMER_PRIME); } } else if (idx==1 && RQautomata) { fprintf(fg_out_file, "%s %s%s %s%s %s %s ", buf, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)current_source_vtx->user_data)->loc, FG_TIMER_PRIME, ((fg_node_info*)user_data)->loc, ((fg_node_info*)user_data)->loc); } if (idx == 0 || RQautomata) { if (!vl_noTimers) { if (!vl_expr_aux3_flag) { if (vl_expr_aux1_flag) fprintf(fg_out_file, "%s %s%d==%.3f %s %s%d=0\n", HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER,src_timer,vl_expr_aux1_val, HSIS_TIMER_SEP,HSIS_BLIF_MVT_TIMER,dest_timer); else fprintf(fg_out_file, "%s %s%d==%d %s %s%d=0\n", HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, src_timer, delay1, HSIS_TIMER_SEP,HSIS_BLIF_MVT_TIMER,dest_timer); } else { fprintf(fg_out_file, "%s %s%d>=%.3f %s %s%d<=%.3f %s %s%d=0\n", HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, src_timer, vl_expr_aux1_val, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, src_timer, vl_expr_aux3_val, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, dest_timer); } } else { fprintf(fg_out_file, "\n"); } } } } } static void fg_put_init_timer_trans_int(void *user_data) { int i; st_generator *gen; vl_term *key; int val; int control_entry=0; int dest_timer; if (((fg_node_info*)user_data)->type != FG_ND_PAUSE) return; for (i=1; i<=st_count(full_terminal_set); i++) { control_entry = 0; gen = st_init_gen(terminal_set); while (st_gen(gen, (char**)&key, (char**)&val)) { if (IABS(val) == i) { fprintf(fg_out_file, "%c ", (val>0)?'1':'0'); control_entry=1; break; } } st_free_gen(gen); if (!control_entry) { fprintf(fg_out_file, "- "); } } dest_timer = atoi(((fg_node_info*)user_data)->loc+1); fprintf(fg_out_file, "%s%d%s ", FG_LLOC, 0, FG_RLOC); fprintf(fg_out_file, "%s%d%s ", FG_LLOC, 0, FG_RLOC); fprintf(fg_out_file, "%s ", ((fg_node_info*)user_data)->loc); fprintf(fg_out_file, "%s ", ((fg_node_info*)user_data)->loc); if (!vl_noTimers) { fprintf(fg_out_file, "%s %s%d=0\n", HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, dest_timer); } else { fprintf(fg_out_file, "\n"); } } void fg_put_init_transition(file, graph) FILE *file; graph_t *graph; { terminal_set = st_init_table(st_ptrcmp, st_ptrhash); fg_gen_fore_dfs(((fg_graph_info*)graph->user_data)->init_node, fg_node_is_pause, fg_put_init_timer_trans_int, remember_node_terminal, switch_node_branch, forget_node_terminal, remember_arc_terminal, forget_arc_terminal, 1); st_free_table(terminal_set); terminal_set = NIL(st_table); } void fg_put_stay_pause(file, pause) FILE *file; vertex_t *pause; { int i, val; int src_timer; int delay1; double delay; vl_delay_control_stmt *pausing_stmt; char buf[MAXSTRLEN]; char str[MAXSTRLEN]; if (((fg_node_info*)pause->user_data)->type != FG_ND_PAUSE) return; pausing_stmt = (vl_delay_control_stmt*) ((fg_node_info*)current_source_vtx->user_data)->data; if (pausing_stmt->type != DelayControlStmt && pausing_stmt->type != EventControlStmt) return; if (pausing_stmt->type == EventControlStmt) { if (!st_lookup(full_terminal_set, ((vl_event_control_stmt*)pausing_stmt)->fg_info, (char**)&val)) val = 0; else val -= FG_MAGIC_UB_EDGE; } buf[0]='\0'; for (i=1; i<=st_count(full_terminal_set); i++) if (i == val) { sprintf(str, "0 "); strcat(buf, str); } else { sprintf(str, "- "); strcat(buf, str); } if (pausing_stmt->type != DelayControlStmt) { fprintf(file, "%s %s %s%s %s%s %s%s%06x\n", buf, ((fg_node_info*)pause->user_data)->loc, FG_LLOC, FG_RLOC, FG_LLOC, FG_RLOC, HSIS_EQUAL, FG_TIMER_PS, ((fg_graph_info*)g_vertex_graph(pause)->user_data)->fg_id); if (RQautomata) { fprintf(file, "%s %s%s %s%s %s%s %s%s%06x\n", buf, ((fg_node_info*)pause->user_data)->loc, FG_TIMER_PRIME, FG_LLOC, FG_RLOC, FG_LLOC, FG_RLOC, HSIS_EQUAL, FG_TIMER_PS, ((fg_graph_info*)g_vertex_graph(pause)->user_data)->fg_id); } return; } src_timer = atoi(((fg_node_info*)pause->user_data)->loc+1); vl_expr_aux1_flag = vl_expr_aux2_flag = vl_expr_aux3_flag = 0; vl_expr_aux1_val = vl_expr_aux2_val = vl_expr_aux3_val = (double)0; if (!(pausing_stmt->delay->delay3 && !pausing_stmt->delay->delay2)) delay1 = vl_eval_expr(pausing_stmt->delay->delay1); else { vl_expr *expr; lsFirstItem((lsList)pausing_stmt->delay->delay1, (lsGeneric*)&expr, 0); delay1 = vl_eval_expr(expr); } if (!vl_expr_aux3_flag) if (vl_expr_aux1_flag) delay = vl_expr_aux1_val; else delay = delay1; else delay = vl_expr_aux3_val; if (!vl_noTimers) { fprintf(file, "%s %s %s%s %s%s %s%s%06x %s %s%d<%.3f\n", buf, ((fg_node_info*)pause->user_data)->loc, FG_LLOC, FG_RLOC, FG_LLOC,FG_RLOC, HSIS_EQUAL, FG_TIMER_PS, ((fg_graph_info*)g_vertex_graph(pause)->user_data)->fg_id, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, src_timer, delay); } if (RQautomata) { if (!vl_noTimers) { fprintf(file, "%s %s%s %s%s %s%s %s%s%06x %s %s%d<%.3f\n", buf, ((fg_node_info*)pause->user_data)->loc, FG_TIMER_PRIME, FG_LLOC, FG_RLOC, FG_LLOC, FG_RLOC, HSIS_EQUAL, FG_TIMER_PS, ((fg_graph_info*)g_vertex_graph(pause)->user_data) ->fg_id, HSIS_TIMER_SEP, HSIS_BLIF_MVT_TIMER, src_timer, delay); } } } static vertex_t *next_node_in_string(u) vertex_t *u; { vertex_t *v; lsList out_edges; edge_t *edge; out_edges = g_get_out_edges(u); if (lsLength(out_edges) == 0) return NIL(vertex_t); lsFirstItem(out_edges, (lsGeneric*)&edge, 0); v = g_e_dest(edge); return v; } void fg_write_timer(FILE *file, graph_t *graph) { vertex_t *pause; vertex_t *v; lsGen gen; lsHandle handle; int pass; fg_out_file = file; fprintf(file, "%s timing automatan: time flies\n", HSIS_COMMENT); for (pass=1; pass<=2; pass++) { if (pass == 1) { terminal_set = st_init_table(st_ptrcmp, st_ptrhash); } for (gen=lsStart(((fg_graph_info*)graph->user_data)->pause_list); lsNext(gen, (lsGeneric*)&pause, &handle) != LS_NOMORE; ) { current_source_vtx = pause; if (!(v = next_node_in_string(pause))) continue; if (pass == 1) { fg_fore_dfs(v, fg_node_is_pause, remember_node_terminal, remember_arc_terminal); } else if (pass == 2) { fg_put_stay_pause(file, pause); terminal_set = st_init_table(st_ptrcmp, st_ptrhash); fg_gen_fore_dfs(v, fg_node_is_pause, fg_put_timer_transition, remember_node_terminal, switch_node_branch, forget_node_terminal, remember_arc_terminal, forget_arc_terminal, 1); st_free_table(terminal_set); terminal_set = NIL(st_table); terminal_set_count = 1; } current_source_vtx = NIL(vertex_t); } lsFinish(gen); if (pass == 1) { fg_declare_timer(file, terminal_set, graph); fg_put_timer_header(file, terminal_set, graph); full_terminal_set = terminal_set; terminal_set = NIL(st_table); terminal_set_count = 1; } } fg_put_init_transition(file, graph); st_free_table(full_terminal_set); full_terminal_set = NIL(st_table); fg_out_file = NIL(FILE); } static st_table *fg_node_set=NIL(st_table); static int fg_consistency = 1; static void fg_check_duplicate(vertex_t *src) { int val; vertex_t *v; edge_t *e; lsList visit_list; lsGen gen; lsHandle handle; if (!fg_consistency) return; if (!src) return; if (((fg_node_info*)src->user_data)->type == FG_ND_PAUSE) return; if (st_lookup(fg_node_set, (char*)src, (char**)&val)) { fg_consistency = 0; } else { st_insert(fg_node_set, (char*)src, 0); visit_list = g_get_out_edges(src); for (gen=lsStart(visit_list); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { v = g_e_dest(e); fg_check_duplicate(v); } lsFinish(gen); } } int fg_check_timer_consistency(FILE *file, graph_t *graph) { fg_consistency = 1; fg_node_set = st_init_table(st_ptrcmp, st_ptrhash); fg_check_duplicate(((fg_graph_info*)graph->user_data)->init_node); st_free_table(fg_node_set); fg_node_set = NIL(st_table); return fg_consistency; } static int fg_id = 0; static int fg_current_id = 0; int fg_new_fg_id() { fg_current_id = ++fg_id; return fg_current_id; } void fg_set_fg_id(int id) { fg_current_id = id; } int fg_fg_id() { return fg_current_id; } void fg_associate_id_vars(int id, st_table *vars) { st_insert(vl_description->fg_vars_st, (char*)id, (char*)vars); } static int data_pause_count=0; st_table *fg_graph_has_one_data_detector(graph) graph_t *graph; { vl_event_control_stmt *pstmt; vl_event_expr *e; lsGen gen, ggen; vertex_t *v; lsHandle handle; int non_data_pause; int check_failed; st_table *new_sensitiveList; if (!graph) return NIL(st_table); non_data_pause = 0; check_failed = 0; data_pause_count=0; new_sensitiveList = st_init_table(strcmp, st_strhash); foreach_vertex(graph, ggen, v) { if (((fg_node_info*)v->user_data)->type == FG_ND_PAUSE && !check_failed) { pstmt = (vl_event_control_stmt*)((fg_node_info*)v->user_data)->data; if (pstmt->type == EventControlStmt) { if (pstmt->event->type == OrEventExpr) { for (gen=lsStart(pstmt->event->list); lsNext(gen,(lsGeneric*)&e,&handle)!=LS_NOMORE; ) { if (e->type == NegedgeEventExpr || e->type == PosedgeEventExpr) { non_data_pause = 1; break; } if (e->expr->type == IDExpr) st_insert(new_sensitiveList, e->expr->u.name->name,0); else if (e->expr->type == MinTypMaxExpr) { if (e->expr->u.exprs.e1->type == IDExpr) st_insert(new_sensitiveList, e->expr->u.exprs.e1->u.name->name,0); } } lsFinish(gen); } else { if (pstmt->event->type == NegedgeEventExpr || pstmt->event->type == PosedgeEventExpr) { non_data_pause = 1; } if (pstmt->event->expr->type == IDExpr) st_insert(new_sensitiveList, pstmt->event->expr->u.name->name,0); } if (!non_data_pause) data_pause_count++; else check_failed = 1; } } } if (data_pause_count==1 && !check_failed) { } else { st_free_table(new_sensitiveList); new_sensitiveList = NIL(st_table); } return new_sensitiveList; }