/* 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 $Id: vl_traverse.c,v 1.4 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 "vl_types.h" #include "vl_defs.h" #include "vlr_int.h" #include "graph.h" #include "vl_fg_defs.h" #include "vl_fg_types.h" #include "vl_flowgraph.h" #include "vl_traverse.h" #include "vl_copy.h" #include "vl_create.h" #include "vl_write_util.h" #include "dataflow.h" #include "vl_write.h" #include "verilog.h" #include int vlTimedSystem = 0; extern vl_desc *mod_list; extern int dflow_analysis; extern int dflow_context; extern int vlPhase; extern int implicitClocking; extern int WarningLevel; extern vl_module *vl_encloseModule; int use_libraryGate; int Loop_Unrolling=1; int Repeat_Unrolling=1; int PrtEnable=0; int indexAssignment=0; int aliasSP=0; st_table *aliasStack[20]; vl_procstmt *vl_currentProcStmt; int in_reset_stmt=0; static int lhs_id=0; static int StpTrace=0; static void assoc_formal_actual ARGS((vl_task *task_dfn, lsList formal, lsList actual)); static void vl_expand_Q ARGS((FILE *file, lsList tags)); static void record_program_location ARGS((vl_procstmt *procstmt)); static void register_clock ARGS((FILE *file, vl_event_expr *event)); static void check_task_arg ARGS((int ok, vl_task *task_dfn)); static void rec_expand_Q ARGS((int num_Q, array_t *q_array, char *bit_str, lsList tags, lsGen gen, lsHandle *phandle)); void vl_fprintf_stmt(FILE* file, ...) { char *fmt; va_list args; va_start(args, file); fmt = va_arg(args, char*); if (PrtEnable) (void)vfprintf(file, fmt, args); va_end(args); } enum st_retval vl_step_desc(char *name, char *value, char *arg) { if (((typestructPtr)value)->type == ModDecl) { vl_step_module(stdout, (vl_module*)value); } else if (((typestructPtr)value)->type == CombPrimDecl || ((typestructPtr)value)->type == SeqPrimDecl) { vl_step_primitive(stdout, (vl_primitive*)value); } name = name; arg = arg; return ST_CONTINUE; } void vl_step_module(FILE *file, vl_module *mod) { if (mod == NULL) return; ASSERT(mod->type==ModDecl, "Expecting ModDecl"); if (mod->visited) return; vl_currentModule = mod; StpTRACE("printing module\n"); vl_fprintf_stmt(file, "module "); vl_step_id_range(file, mod->name); vl_step_ports(file, mod->ports); vl_fprintf_stmt(file, ";\n"); vl_step_mod_item_list(file, mod->mod_items); vl_fprintf_stmt(file, "endmodule\n\n"); vl_currentModule = NIL(vl_module); mod->visited = 1; } void vl_step_primitive(FILE *file, vl_primitive *prim) { if (prim == NULL) return; ASSERT((prim->type==CombPrimDecl || prim->type==SeqPrimDecl), "Expecting PrimDecl"); StpTRACE("Printing primitive\n"); vl_fprintf_stmt(file, "primitive "); vl_step_id_range(file, prim->name); vl_step_ports(file, prim->ports); vl_fprintf_stmt(file, ";\n"); vl_step_mod_item_list(file, prim->decls); vl_step_prim_table(file, prim->type, prim->entries); vl_fprintf_stmt(file, "endprimitive\n\n"); } void vl_step_prim_table(FILE *file, short type, lsList entries) { vl_prim_entry *e; int i; lsHandle handle; lsGen gen; if (entries == NULL) return; StpTRACE("Printing primitive table\n"); vl_fprintf_stmt(file, "table\n"); for(gen = lsStart(entries); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { for (i=0; i<10; i++) { if (e->inputs[i] == PrimNone) break; else vl_fprintf_stmt(file, "%s ", vl_get_prim_symbol(e->inputs[i])); } if (type == SeqPrimDecl) vl_fprintf_stmt(file, ": %s", vl_get_prim_symbol(e->state)); vl_fprintf_stmt(file, ": %s\n", vl_get_prim_symbol(e->next_state)); } (void) lsFinish(gen); vl_fprintf_stmt(file, "endtable\n"); } void vl_step_basicdecl(FILE *file, vl_decl *decl) { StpTRACE("Printing Basic decl\n"); switch(decl->type) { case RealDecl: vl_fprintf_stmt(file, "real "); vl_step_id_list(file, decl->ids); break; case EventDecl: vl_fprintf_stmt(file, "event "); vl_step_id_list(file, decl->ids); break; case IntDecl: vl_fprintf_stmt(file, "integer "); vl_step_id_range_list(file, decl->ids); break; case TimeDecl: vl_fprintf_stmt(file, "time "); vl_step_id_range_list(file, decl->ids); break; default: internal_error("Unexpected Basic Decl type"); break; } vl_fprintf_stmt(file, ";\n"); } void vl_step_rangedecl(FILE *file, vl_rangedecl *decl) { StpTRACE("Printing Range decl\n"); switch(decl->type) { case InputDecl: vl_fprintf_stmt(file, "input "); break; case OutputDecl: vl_fprintf_stmt(file, "output "); break; case InoutDecl: vl_fprintf_stmt(file, "inout "); break; case RegDecl: vl_fprintf_stmt(file, "reg "); break; default: internal_error("Unexpected Range Decl"); break; } vl_step_range(file, decl->range); if (decl->type == RegDecl) vl_step_id_range_list(file, decl->ids); else vl_step_id_list(file, decl->ids); vl_fprintf_stmt(file, ";\n"); } void vl_step_paramdecl(FILE *file, vl_paramdecl *decl) { StpTRACE("Printing Parameter decl\n"); switch(decl->type) { case ParamDecl: vl_fprintf_stmt(file, "parameter "); break; case DefparamDecl: vl_fprintf_stmt(file, "defparam "); break; default: internal_error("Unexpected Param Decl"); break; } { vl_bassign_stmt *assign; lsHandle handle; lsGen gen; gen = lsStart(decl->assigns); if (lsNext(gen, (lsGeneric*)&assign, &handle) == LS_OK) { vl_step_bassign_stmt(file, assign); while(lsNext(gen, (lsGeneric*)&assign, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_bassign_stmt(file, assign); } } } vl_fprintf_stmt(file, ";\n"); } void vl_step_netdecl(FILE *file, vl_netdecl *decl) { StpTRACE("Printing Net decl\n"); switch(decl->type) { case WireDecl: vl_fprintf_stmt(file, "wire"); break; case TriDecl: vl_fprintf_stmt(file, "tri"); break; case Tri0Decl: vl_fprintf_stmt(file, "tri0"); break; case Tri1Decl: vl_fprintf_stmt(file, "tri1"); break; case Supply0Decl: vl_fprintf_stmt(file, "supply0"); break; case Supply1Decl: vl_fprintf_stmt(file, "supply1"); break; case WandDecl: vl_fprintf_stmt(file, "wand"); break; case TriandDecl: vl_fprintf_stmt(file, "triand"); break; case WorDecl: vl_fprintf_stmt(file, "wor"); break; case TriorDecl: vl_fprintf_stmt(file, "trior"); break; case TriregDecl: vl_fprintf_stmt(file, "trireg"); break; default: internal_error("Unexpected Net Decl"); break; } vl_step_strength(file, decl->strength); vl_step_range(file, decl->range); vl_step_delay(file, decl->delay); vl_step_net_list(file, decl->ids); vl_fprintf_stmt(file, ";\n"); } void vl_step_task(FILE *file, vl_task *task) { StpTRACE("Printing Task\n"); ASSERT(task->type == TaskDecl, "Unexpected Task Type"); vl_fprintf_stmt(file, "\ntask "); vl_step_id_range(file, task->name); vl_fprintf_stmt(file, ";\n"); vl_step_decl_list(file, task->decls); vl_step_stmt_list(file, task->stmts); vl_fprintf_stmt(file, "endtask\n"); } void vl_step_function(FILE *file, vl_function *func) { int old_dflow_analysis; vl_function *old_function; vl_module *old_module; vl_module *old_enclosemodule; StpTRACE("Printing Function\n"); old_dflow_analysis = dflow_analysis; dflow_analysis = 0; dataflow_init(); vl_fprintf_stmt(file, "\nfunc "); switch(func->type) { case IntFuncDecl: st_insert(vl_currentModule->func_st, func->name->name, (char*)func); vl_fprintf_stmt(file, "integer "); break; case RealFuncDecl: st_insert(vl_currentModule->func_st, func->name->name, (char*)func); vl_fprintf_stmt(file, "real "); break; case RangeFuncDecl: st_insert(vl_currentModule->func_st, func->name->name, (char*)func); vl_step_range(file, func->range); break; default: internal_error("Unexpected Function Type"); } vl_step_id_range(file, func->name); vl_fprintf_stmt(file, ";\n"); old_module = vl_currentModule; old_function = vl_currentFunction; old_enclosemodule = vl_encloseModule; vl_encloseModule = vl_currentModule; vl_currentModule = (vl_module*)func; vl_currentFunction = func; vl_step_decl_list(file, func->decls); vl_step_stmt_list(file, func->stmts); vl_currentModule = old_module; vl_currentFunction = old_function; vl_encloseModule = old_enclosemodule; vl_fprintf_stmt(file, "endfunction\n"); dflow_analysis = old_dflow_analysis; dataflow_end(); } void vl_step_gate_inst_list(FILE *file, vl_gate_inst_list *gatelist) { StpTRACE("Printing Gate Instance List\n"); switch(gatelist->type) { case AndGate: vl_fprintf_stmt(file, "and"); break; case NandGate: vl_fprintf_stmt(file, "nand"); break; case OrGate: vl_fprintf_stmt(file, "or"); break; case NorGate: vl_fprintf_stmt(file, "nor"); break; case XorGate: vl_fprintf_stmt(file, "xor"); break; case XnorGate: vl_fprintf_stmt(file, "xnor"); break; case BufGate: vl_fprintf_stmt(file, "buf"); break; case Bufif0Gate: vl_fprintf_stmt(file, "bufif0"); break; case Bufif1Gate: vl_fprintf_stmt(file, "bufif1"); break; case NotGate: vl_fprintf_stmt(file, "not"); break; case Notif0Gate: vl_fprintf_stmt(file, "notif0"); break; case Notif1Gate: vl_fprintf_stmt(file, "notif1"); break; case PulldownGate: vl_fprintf_stmt(file, "pulldown"); break; case PullupGate: vl_fprintf_stmt(file, "pullup"); break; case NmosGate: vl_fprintf_stmt(file, "nmos"); break; case RnmosGate: vl_fprintf_stmt(file, "rnmos"); break; case PmosGate: vl_fprintf_stmt(file, "pmos"); break; case RpmosGate: vl_fprintf_stmt(file, "rpmos"); break; case CmosGate: vl_fprintf_stmt(file, "cmos"); break; case RcmosGate: vl_fprintf_stmt(file, "rcmos"); break; case TranGate: vl_fprintf_stmt(file, "tran"); break; case RtranGate: vl_fprintf_stmt(file, "rtran"); break; case Tranif0Gate: vl_fprintf_stmt(file, "tranif0"); break; case Rtranif0Gate: vl_fprintf_stmt(file, "rtranif0"); break; case Tranif1Gate: vl_fprintf_stmt(file, "tranif1"); break; case Rtranif1Gate: vl_fprintf_stmt(file, "rtranif1"); break; default: internal_error("Unexpected Gate Type"); break; } vl_fprintf_stmt(file, " "); vl_step_strength(file, gatelist->strength); vl_step_delay(file, gatelist->delays); vl_step_gates(file, gatelist->gates); vl_fprintf_stmt(file, ";\n"); } void vl_step_gates(FILE *file, lsList gates) { vl_gate_inst *gate; lsHandle handle; lsGen gen; StpTRACE("Printing Gate Instances\n"); gen = lsStart(gates); if (lsNext(gen, (lsGeneric*)&gate, &handle) == LS_OK) { vl_step_gate(file, gate); while(lsNext(gen, (lsGeneric*)&gate, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_gate(file, gate); } } (void) lsFinish(gen); } void vl_step_prim_inst_list(FILE *file, vl_mod_prim_inst_list *primlist) { StpTRACE("Printing Primitive Instance List\n"); vl_step_id_range(file, primlist->name); vl_step_strength(file, primlist->strength); vl_step_delay(file, primlist->delays); vl_step_prims(file, primlist->mps); vl_fprintf_stmt(file, ";\n"); } void vl_step_prims(FILE *file, lsList prims) { vl_mod_prim_inst *prim; lsHandle handle; lsGen gen; StpTRACE("Printing Primitive Instances\n"); gen = lsStart(prims); if (lsNext(gen, (lsGeneric*)&prim, &handle) == LS_OK) { vl_step_prim(file, prim); while(lsNext(gen, (lsGeneric*)&prim, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_prim(file, prim); } } (void) lsFinish(gen); } void vl_step_mod_inst_list(FILE *file, vl_mod_prim_inst_list *modinstlist) { vl_module *result; StpTRACE("Printing Module Instance List\n"); result = vl_chk_param_dup_master(modinstlist); if (result) modinstlist->name = result->name; vl_step_id_range(file, modinstlist->name); vl_fprintf_stmt(file, " "); vl_step_param_vals(file, (lsList)modinstlist->delays); vl_step_mod_insts(file, modinstlist->mps); vl_fprintf_stmt(file, ";\n"); } void vl_step_mod_insts(FILE *file, lsList modinsts) { vl_mod_prim_inst *modinst; lsHandle handle; lsGen gen; StpTRACE("Printing Module Instances\n"); gen = lsStart(modinsts); if (lsNext(gen, (lsGeneric*)&modinst, &handle) == LS_OK) { vl_step_modinst(file, modinst); while(lsNext(gen, (lsGeneric*)&modinst, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_modinst(file, modinst); } } (void) lsFinish(gen); } void vl_step_procstmt(FILE *file, vl_procstmt *pstmt) { int old_dflow_context; graph_t *fg_FlowGraph; edge_t *back_edge; StpTRACE("Printing Process stmt\n"); old_dflow_context = dflow_context; dataflow_init(); fg_FlowGraph = fg_new_graph(); vl_currentProcStmt = pstmt; switch(pstmt->type) { case AlwaysStmt: { lsNewEnd(vl_currentModule->flow_graphs, (lsGeneric)fg_FlowGraph, 0); back_edge = fg_new_always_block(); dflow_context |= DFLOW_Always; vl_fprintf_stmt(file, "always\n"); break; } case InitialStmt: dflow_context |= DFLOW_Initial; if (pstmt->flags & TimedInitStmt) { lsNewEnd(vl_currentModule->flow_graphs,(lsGeneric)fg_FlowGraph,0); fg_new_always_block(); pstmt->type = AlwaysStmt; pstmt->flags |= PseudoAlways; } else { in_reset_stmt = 1; vl_currentModule->flags |= WithInitial; } vl_fprintf_stmt(file, "initial\n"); break; default: internal_error("Unexpected Process Statement Type"); break; } vl_step_stmt(file, pstmt->stmt); in_reset_stmt = 0; vl_currentProcStmt = NIL(vl_procstmt); dflow_context = old_dflow_context; dataflow_end(); if (pstmt->flags & PseudoAlways) { pstmt->fg_info = (char*)fg_pseudo_sink(); ((fg_node_info*)((vertex_t*)pstmt->fg_info)->user_data)->data = (char*)pstmt; } else { fg_closeloop(); } if (pstmt->type == AlwaysStmt && !(pstmt->flags & PseudoAlways)) { assert(fg_check_cyclic()); } fg_clean_fg(); } int vl_step_begin_end_stmt(FILE *file, vl_begin_end_stmt *bestmt) { int step_flag; StpTRACE("Printing beginend\n"); ASSERT(bestmt->type == BeginEndStmt, "Unexpected BeginEndStmt Type"); vl_fprintf_stmt(file, "begin\n"); vl_step_decl_list(file, bestmt->decls); step_flag = vl_step_stmt_list(file, bestmt->stmts); vl_fprintf_stmt(file, "end\n"); return step_flag; } int vl_step_if_else_stmt(FILE *file, vl_if_else_stmt *stmt) { set_t *if_set = NIL(set_t), *else_set = NIL(set_t); set_t *new_set = NIL(set_t); int step_flag_if = 0, step_flag_else = 0; vertex_t *old_Srce, *old_Sink; vertex_t *old_CMPSrce, *old_CMPSink; vertex_t *ctrl_vtx, *sink_vtx; vertex_t *cmp_ctrl_vtx, *cmp_sink_vtx; vertex_t *src, *sink; vertex_t *cmp_src, *cmp_sink; StpTRACE("Printing if_else_stmt\n"); ASSERT(stmt->type == IfElseStmt, "Unexpected IfElseStmt Type"); if (vl_currentFunction) vl_encloseModule->syndrome_width++; else { if (!in_reset_stmt) vl_currentModule->syndrome_width++; else vl_currentModule->rst_syndrome_width++; } if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_new_ifelse_block(&old_Srce, &old_Sink, &ctrl_vtx, &sink_vtx, &old_CMPSrce,&old_CMPSink, &cmp_ctrl_vtx,&cmp_sink_vtx); ((fg_node_info*)ctrl_vtx->user_data)->data = (char*)stmt->cond; stmt->cond->fg_info1 = (char*)ctrl_vtx; stmt->cond->fg_info2 = (char*)sink_vtx; fg_record_SrcSink(&src, &sink, &cmp_src, &cmp_sink); } vl_fprintf_stmt(file, "if ("); vl_step_expr(file, stmt->cond); vl_fprintf_stmt(file, ")\n"); dataflow_dup_set(); step_flag_if = vl_step_stmt(file, stmt->if_stmt); if_set = dataflow_pop_set(); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) stmt->cond->fg_aux1 = (char*)fg_closeloop(); if (stmt->else_stmt) { vl_fprintf_stmt(file, "else\n"); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) fg_restore_SrcSink(src, sink, cmp_src, cmp_sink); dataflow_dup_set(); step_flag_else = vl_step_stmt(file, stmt->else_stmt); else_set = dataflow_pop_set(); new_set = dataflow_merge_set(if_set, else_set); dataflow_replace_set(new_set); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) stmt->cond->fg_aux2 = (char*)fg_closeloop(); } else { if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_restore_SrcSink(src, sink, cmp_src, cmp_sink); stmt->cond->fg_aux2 = (char*)fg_closeloop(); } } if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_restore_SrcSink(src, sink, cmp_src, cmp_sink); fg_reduce_simple_branches_back_block(old_Srce, old_Sink, old_CMPSrce, old_CMPSink); } return step_flag_if | step_flag_else; } int vl_step_case_stmt(FILE *file, vl_case_stmt *stmt) { int step_flag = 0; vertex_t *old_Srce, *old_Sink; vertex_t *ctrl_vtx, *sink_vtx; vertex_t *old_CMPSrce, *old_CMPSink; vertex_t *ctrl_CMPvtx, *sink_CMPvtx; StpTRACE("Printing case_stmt\n"); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_new_case_block(&old_Srce, &old_Sink, &ctrl_vtx, &sink_vtx, &old_CMPSrce, &old_CMPSink, &ctrl_CMPvtx, &sink_CMPvtx); ((fg_node_info*)ctrl_vtx->user_data)->data = (char*)stmt->cond; stmt->cond->fg_info1 = (char*)ctrl_vtx; stmt->cond->fg_info2 = (char*)sink_vtx; } switch(stmt->type) { case CaseStmt: vl_fprintf_stmt(file, "case ("); break; case CasexStmt: vl_fprintf_stmt(file, "casex ("); break; case CasezStmt: vl_fprintf_stmt(file, "casez ("); break; default: internal_error("Unexpected Case Type"); break; } vl_step_expr(file, stmt->cond); vl_fprintf_stmt(file, ")\n"); { vl_case_item *item; lsHandle handle; lsGen gen; vertex_t *cur_src, *cur_sink; vertex_t *cur_cmp_src, *cur_cmp_sink; edge_t *ctrl_edge; if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) fg_record_SrcSink(&cur_src, &cur_sink, &cur_cmp_src, &cur_cmp_sink); gen = lsStart(stmt->case_items); while(lsNext(gen, (lsGeneric*)&item, &handle) != LS_NOMORE) { if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { ctrl_edge = fg_new_case_tag_block(cur_src, cur_sink, cur_cmp_src, cur_cmp_sink); ((fg_arc_info*)ctrl_edge->user_data)->data = (char*)item; item->fg_info = (char*)ctrl_edge; } dataflow_dup_set(); step_flag |= vl_step_case_item(file, item); if (item->type != DefaultItem) dataflow_free_set(dataflow_pop_set()); else dataflow_replace_set(dataflow_pop_set()); fg_closeloop(); } if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) fg_restore_SrcSink(cur_src, cur_sink, cur_cmp_src, cur_cmp_sink); } vl_fprintf_stmt(file, "endcase\n"); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) fg_reduce_simple_branches_back_block(old_Srce, old_Sink, old_CMPSrce, old_CMPSink); return step_flag; } void vl_step_forever_stmt(FILE *file, vl_forever_stmt *stmt) { StpTRACE("Printing forever_stmt\n"); ASSERT(stmt->type == ForeverStmt, "Unexpected ForeverStmt Type"); vl_fprintf_stmt(file, "forever\n"); vl_step_stmt(file, stmt->stmt); } void vl_step_repeat_stmt(FILE *file, vl_repeat_stmt *stmt) { StpTRACE("Printing repeat_stmt\n"); ASSERT(stmt->type == RepeatStmt, "Unexpected RepeatStmt Type"); vl_fprintf_stmt(file, "repeat ("); vl_step_expr(file, stmt->count); vl_fprintf_stmt(file, ")\n"); vl_step_stmt(file, stmt->stmt); } void vl_step_while_stmt(FILE *file, vl_while_stmt *stmt) { vertex_t *old_src, *old_sink, *ctrl_vtx, *sink_vtx, *old_CMPsrc, *old_CMPsink, *cmp_ctrl_vtx, *cmp_sink_vtx; vertex_t *src, *sink, *cmp_src, *cmp_sink; int contain_pause; StpTRACE("Printing while_stmt\n"); ASSERT(stmt->type == WhileStmt, "Unexpected WhileStmt Type"); if (!in_reset_stmt) vl_currentModule->syndrome_width++; if (!in_reset_stmt &&vlPhase==1 && fg_not_empty()) { fg_new_loop_block(&old_src, &old_sink, &ctrl_vtx, &sink_vtx, &old_CMPsrc, &old_CMPsink, &cmp_ctrl_vtx, &cmp_sink_vtx); ((fg_node_info*)ctrl_vtx->user_data)->data = (char*)stmt->cond; stmt->cond->fg_info1 = (char*)ctrl_vtx; stmt->cond->fg_info2 = (char*)sink_vtx; fg_record_SrcSink(&src, &sink, &cmp_src, &cmp_sink); } vl_fprintf_stmt(file, "while ("); vl_step_expr(file, stmt->cond); vl_fprintf_stmt(file, ")\n"); vl_step_stmt(file, stmt->stmt); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_closeloop(); fg_restore_SrcSink(src, sink, cmp_src, cmp_sink); contain_pause = fg_reduce_simple_branches_back_block(old_src, old_sink, old_CMPsrc, old_CMPsink); if (!contain_pause) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s: there exist delay free for loop(s)", vl_currentModule->name->name); compile_error(buf); } fg_force_edge(sink_vtx, ctrl_vtx, cmp_sink_vtx, cmp_ctrl_vtx); fg_restore_SrcSink(ctrl_vtx, old_sink, cmp_ctrl_vtx, old_CMPsink); } } void vl_step_for_stmt(FILE *file, vl_for_stmt *stmt) { vertex_t *old_src, *old_sink, *ctrl_vtx, *sink_vtx, *old_CMPsrc, *old_CMPsink, *cmp_ctrl_vtx, *cmp_sink_vtx; vertex_t *src, *sink, *cmp_src, *cmp_sink; int contain_pause; StpTRACE("Printing for_stmt\n"); ASSERT(stmt->type == ForStmt, "Unexpected ForStmt Type"); if (!in_reset_stmt) vl_currentModule->syndrome_width++; vl_fprintf_stmt(file, "for ("); vl_step_bassign_stmt(file, stmt->init); vl_fprintf_stmt(file, "; "); if (!in_reset_stmt &&vlPhase==1 && fg_not_empty()) { fg_new_loop_block(&old_src, &old_sink, &ctrl_vtx, &sink_vtx, &old_CMPsrc, &old_CMPsink, &cmp_ctrl_vtx, &cmp_sink_vtx); ((fg_node_info*)ctrl_vtx->user_data)->data = (char*)stmt->cond; stmt->cond->fg_info1 = (char*)ctrl_vtx; stmt->cond->fg_info2 = (char*)sink_vtx; fg_record_SrcSink(&src, &sink, &cmp_src, &cmp_sink); } vl_step_expr(file, stmt->cond); vl_fprintf_stmt(file, "; "); vl_step_bassign_stmt(file, stmt->end); vl_fprintf_stmt(file, ")\n"); vl_step_stmt(file, stmt->stmt); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { fg_closeloop(); fg_restore_SrcSink(src, sink, cmp_src, cmp_sink); contain_pause = fg_reduce_simple_branches_back_block(old_src, old_sink, old_CMPsrc, old_CMPsink); if (!contain_pause) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s: there exist delay free for loop(s)", vl_currentModule->name->name); compile_error(buf); } fg_force_edge(sink_vtx, ctrl_vtx, cmp_sink_vtx, cmp_ctrl_vtx); fg_restore_SrcSink(ctrl_vtx, old_sink, cmp_ctrl_vtx, old_CMPsink); } } void vl_step_delay_control_stmt(FILE *file, vl_delay_control_stmt *stmt) { vertex_t *pause_node; StpTRACE("Printing delay_control_stmt\n"); ASSERT(stmt->type == DelayControlStmt, "Unexpected DelayControlStmt Type"); if (implicitClocking && !vlTimedSystem) { char buf[MAXSTRLEN]; yylineno = -1; if (vl_currentModule) sprintf(buf, "%s: 'always'-statement contains delay which contradicts with implicit clocking", vl_currentModule->name->name); else sprintf(buf, "delay(s) in implicit clocking"); compile_error(buf); } vl_step_delay(file, stmt->delay); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { pause_node = fg_new_pause_node(); ((fg_node_info*)pause_node->user_data)->data = (char*)stmt; stmt->fg_info = (char*)pause_node; } vl_step_stmt(file, stmt->stmt); } int vl_step_event_control_stmt(FILE *file, vl_event_control_stmt *stmt) { int step_flag = 0; vertex_t *pause_node; StpTRACE("Printing event_control_stmt\n"); ASSERT(stmt->type == EventControlStmt, "Unexpected EventControlStmt Type"); vl_fprintf_stmt(file, "@("); step_flag = vl_step_event_expr(file, stmt->event); vl_fprintf_stmt(file, ")"); if (!in_reset_stmt && vlPhase==1 && fg_not_empty()) { pause_node = fg_new_pause_node(); ((fg_node_info*)pause_node->user_data)->data = (char*)stmt; stmt->fg_info = (char*)pause_node; } vl_step_stmt(file, stmt->stmt); return step_flag; } int vl_step_bassign_stmt(FILE *file, vl_bassign_stmt *bassign) { int step_flag = 0; vertex_t *assign_vtx; StpTRACE("Printing bassign_stmt\n"); if (!in_reset_stmt && vlPhase == 1 && fg_not_empty()) { assign_vtx = fg_new_assign_node(); bassign->fg_info = (char*)assign_vtx; } if (bassign->type == AssignStmt) { vl_fprintf_stmt(file, "assign "); } lhs_id = 1; vl_step_lval(file, bassign->lhs); lhs_id = 0; switch(bassign->type) { case AssignStmt: case BassignStmt: vl_fprintf_stmt(file, " = "); break; case NbassignStmt: vl_fprintf_stmt(file, " <= "); collect_latch(bassign->lhs->name->name); break; case DelayBassignStmt: vl_fprintf_stmt(file, " = "); vl_step_delay(file, (vl_delay *)bassign->control); break; case DelayNbassignStmt: vl_fprintf_stmt(file, " <= "); vl_step_delay(file, (vl_delay *)bassign->control); collect_latch(bassign->lhs->name->name); break; case EventBassignStmt: vl_fprintf_stmt(file, " = @("); step_flag = vl_step_event_expr(file, (vl_event_expr *)bassign->control); vl_fprintf_stmt(file, ")"); break; case EventNbassignStmt: vl_fprintf_stmt(file, " <= @("); step_flag = vl_step_event_expr(file, (vl_event_expr *)bassign->control); vl_fprintf_stmt(file, ")"); collect_latch(bassign->lhs->name->name); break; default: internal_error("Unexpected Assign Type"); break; } vl_step_expr(file, bassign->rhs); return step_flag; } void vl_step_wait_stmt(FILE *file, vl_wait_stmt *stmt) { vl_begin_end_stmt *faked_stmt; StpTRACE("Printing wait_stmt\n"); ASSERT(stmt->type == WaitStmt, "Unexpected WaitStmt Type"); faked_stmt = vl_fake_wait_stmt(file, stmt); vl_fprintf_stmt(file, "wait ("); vl_step_expr(file, stmt->cond); vl_fprintf_stmt(file, ")\n"); vl_step_stmt(file, stmt->stmt); stmt->stmt = faked_stmt; stmt->cond = NIL(vl_expr); } void vl_step_fork_join_stmt(FILE *file, vl_fork_join_stmt *stmt) { StpTRACE("Printing fork_join_stmt\n"); ASSERT(stmt->type == ForkJoinStmt, "Unexpected ForkJoinStmt Type"); vl_fprintf_stmt(file, "fork\n"); vl_step_decl_list(file, stmt->decls); vl_step_stmt_list(file, stmt->stmts); vl_fprintf_stmt(file, "join\n"); } void vl_step_task_enable_stmt(FILE *file, vl_task_enable_stmt *stmt) { vl_task *task_dfn; lsGen stmtgen; lsHandle stmthandle; lsList unrolled_stmt; void *task_stmt; void *new_stmt; StpTRACE("Printing task_enable_stmt\n"); ASSERT(((stmt->type == TaskEnableStmt) || (stmt->type == SysTaskEnableStmt)), "Unexpected TaskEnableStmt Type"); vl_step_id_range(file, stmt->name); if (!st_lookup(vl_currentModule->task_st, stmt->name->name, (char**)&task_dfn)) { char buf[MAXSTRLEN]; sprintf(buf, "Undefined task/function '%s'", stmt->name->name); yylineno = -1; compile_error(buf); } if (stmt->args) { vl_fprintf_stmt(file, " ("); vl_step_expr_list(file, stmt->args); vl_fprintf_stmt(file, " )"); assoc_formal_actual(task_dfn, task_dfn->io_lst, stmt->args); } aliasStack[aliasSP++] = task_dfn->sig_st; unrolled_stmt = lsCreate(); for (stmtgen = lsStart(task_dfn->stmts); lsNext(stmtgen, (lsGeneric*)&task_stmt, &stmthandle) != LS_NOMORE; ) { new_stmt = vl_copy_stmt(task_stmt); lsNewEnd(unrolled_stmt, (lsGeneric)new_stmt, 0); vl_step_stmt(file, new_stmt); } lsFinish(stmtgen); aliasSP--; ((vl_begin_end_stmt*)stmt)->type = BeginEndStmt; ((vl_begin_end_stmt*)stmt)->flags = 0; ((vl_begin_end_stmt*)stmt)->name = NIL(vl_id_range); ((vl_begin_end_stmt*)stmt)->decls = NIL(void); ((vl_begin_end_stmt*)stmt)->sig_st= NIL(st_table); ((vl_begin_end_stmt*)stmt)->stmts = unrolled_stmt; vl_fprintf_stmt(file, ";\n"); } void vl_step_disable_stmt(FILE *file, vl_disable_stmt *stmt) { StpTRACE("Printing disable_stmt\n"); ASSERT(stmt->type == DisableStmt, "Unexpected DisableStmt Type"); vl_fprintf_stmt(file, "disable "); vl_step_id_range(file, stmt->name); vl_fprintf_stmt(file, ";\n"); } void vl_step_deassign_stmt(FILE *file, vl_deassign_stmt *stmt) { StpTRACE("Printing deassign_stmt\n"); ASSERT(stmt->type == DeassignStmt, "Unexpected DeassignStmt Type"); if (!in_reset_stmt && vlPhase == 1 && fg_not_empty()) { vertex_t *assign_vtx; assign_vtx = fg_new_assign_node(); stmt->fg_info = (char*)assign_vtx; } vl_fprintf_stmt(file, "deassign "); vl_step_lval(file, stmt->lhs); vl_fprintf_stmt(file, ";\n"); } int vl_step_case_item(FILE *file, vl_case_item *item) { int step_flag = 0; StpTRACE("Printing case_item\n"); switch(item->type) { case CaseItem: if (vl_currentFunction) vl_encloseModule->syndrome_width++; else { if (!in_reset_stmt) vl_currentModule->syndrome_width++; else vl_currentModule->rst_syndrome_width++; } vl_expand_Q(file, item->exprs); vl_step_expr_list(file, item->exprs); vl_fprintf_stmt(file, ": "); break; case DefaultItem: vl_fprintf_stmt(file, "default: "); break; default: internal_error("Unexpected CaseItem Type"); break; } step_flag = vl_step_stmt(file, item->stmt); return step_flag; } int vl_step_event_expr(FILE *file, vl_event_expr *event) { int step_flag = 0; StpTRACE("Printing event_expr\n"); if (event == NIL(vl_event_expr)) return 0; switch(event->type) { case OrEventExpr: { vl_event_expr *e; lsHandle handle; lsGen gen; gen = lsStart(event->list); if (lsNext(gen, (lsGeneric*)&e, &handle) == LS_OK) { vl_step_event_expr(file, e); while(lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, " or "); vl_step_event_expr(file, e); } } (void) lsFinish(gen); return step_flag; } case NegedgeEventExpr: vl_fprintf_stmt(file, "negedge "); record_program_location(vl_currentProcStmt); step_flag = SYNCHRONIZED; vl_step_expr(file, event->expr); register_clock(file, event); break; case PosedgeEventExpr: vl_fprintf_stmt(file, "posedge "); if (vl_currentProcStmt) record_program_location(vl_currentProcStmt); step_flag = SYNCHRONIZED; vl_step_expr(file, event->expr); if (vl_currentProcStmt) register_clock(file, event); break; case EdgeEventExpr: vl_fprintf_stmt(file, "edge "); record_program_location(vl_currentProcStmt); step_flag = SYNCHRONIZED; vl_step_expr(file, event->expr); register_clock(file, event); break; case EventExpr: vl_step_expr(file, event->expr); break; default: internal_error("Unexpected EventExpr Type"); break; } return step_flag; } void vl_step_lval(FILE *file, vl_lval *lval) { StpTRACE("Printing lval\n"); switch(lval->type) { case IDExpr: vl_step_id_range(file, lval->name); break; case BitSelExpr: case PartSelExpr: vl_step_id_range(file, lval->name); vl_step_range(file, lval->range); break; case ConcatExpr: { vl_expr *e; lsHandle handle; lsGen gen; vl_fprintf_stmt(file, "{"); gen = lsStart(lval->concat); if (lsNext(gen, (lsGeneric*)&e, &handle) == LS_OK) { vl_step_expr(file, e); while(lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_expr(file, e); } } vl_fprintf_stmt(file, "}"); (void) lsFinish(gen); break; } default: internal_error("Unexpected Lval Type"); break; } } void vl_step_expr(FILE *file, vl_expr *expr) { vl_id_range *id_sym; if (!expr) return; StpTRACE("Printing expr\n"); switch (expr->type) { case BitExpr: vl_fprintf_stmt(file, "'b%s", expr->u.exprs.e3); break; case IntExpr: vl_fprintf_stmt(file, "%d", expr->u.intval); break; case RealExpr: vl_fprintf_stmt(file, "%f", expr->u.realval); break; case IDExpr: if (!vl_currentPrimitive && !vl_currentFunction) if (vl_currentModule->param_st) if (st_lookup(vl_currentModule->param_st, expr->u.name->name, (char**)&id_sym)) { vl_free_id(expr->u.name); expr->type = IntExpr; expr->u.intval = (int)(id_sym->mpg_master_exp); vl_fprintf_stmt(file, "%d", expr->u.intval); break; } vl_step_id_range(file, expr->u.name); break; case BitSelExpr: case PartSelExpr: vl_step_id_range(file, expr->u.idrng); break; case ConcatExpr: { vl_expr *e; lsHandle handle; lsGen gen; vl_fprintf_stmt(file, "{"); gen = lsStart((lsList)(expr->u.exprs.e1)); if (lsNext(gen, (lsGeneric*)&e, &handle) == LS_OK) { vl_step_expr(file, e); while(lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_expr(file, e); } } vl_fprintf_stmt(file, "}"); (void) lsFinish(gen); break; } case MinTypMaxExpr: { vl_fprintf_stmt(file, "("); vl_step_expr(file, expr->u.exprs.e1); if (expr->u.exprs.e2) { vl_fprintf_stmt(file, ":"); vl_step_expr(file, expr->u.exprs.e2); } if (expr->u.exprs.e3) { vl_fprintf_stmt(file, ":"); vl_step_expr(file, expr->u.exprs.e3); } vl_fprintf_stmt(file, ")"); break; } case StringExpr: vl_fprintf_stmt(file, "%s", expr->u.string); break; case FuncExpr: vl_step_id_range(file, expr->u.func_call.name); if (expr->u.func_call.args) { vl_fprintf_stmt(file, " ("); vl_step_expr_list(file, expr->u.func_call.args); vl_fprintf_stmt(file, ") "); } break; case UplusExpr: case UminusExpr: case UnotExpr: case UcomplExpr: case UandExpr: case UnandExpr: case UorExpr: case UnorExpr: case UxorExpr: case UxnorExpr: vl_fprintf_stmt(file, "%s", vl_get_expr_op(expr->type)); vl_step_expr(file, expr->u.exprs.e1); break; case BplusExpr: case BminusExpr: case BtimesExpr: case BdivExpr: case BremExpr: case Beq2Expr: case Bneq2Expr: case Beq3Expr: case Bneq3Expr: case BlandExpr: case BlorExpr: case BltExpr: case BleExpr: case BgtExpr: case BgeExpr: case BandExpr: case BorExpr: case BxorExpr: case BxnorExpr: case BlshiftExpr: case BrshiftExpr: vl_step_expr(file, expr->u.exprs.e1); vl_fprintf_stmt(file, " %s ", vl_get_expr_op(expr->type)); vl_step_expr(file, expr->u.exprs.e2); break; case TcondExpr: vl_step_expr(file, expr->u.exprs.e1); vl_fprintf_stmt(file, " ? "); vl_step_expr(file, expr->u.exprs.e2); vl_fprintf_stmt(file, " : "); vl_step_expr(file, expr->u.exprs.e3); break; case NondExpr: vl_fprintf_stmt(file, "$ND ( "); vl_step_expr_list(file, expr->u.expr_list); vl_fprintf_stmt(file, " ) "); break; } } void vl_step_expr_list(FILE *file, lsList exprs) { void *expr; lsHandle handle; lsGen gen; StpTRACE("Printing Expression List\n"); if (lsLength(exprs) <= 0) return; gen = lsStart(exprs); if (lsNext(gen, (lsGeneric*)&expr, &handle) == LS_OK) { vl_step_expr(file, expr); while(lsNext(gen, (lsGeneric*)&expr, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ","); vl_step_expr(file, expr); } } (void) lsFinish(gen); } void vl_step_range(FILE *file, vl_range *range) { StpTRACE("Printing range\n"); if (range == NIL(vl_range) || (range->left == NIL(vl_expr) && range->right == NIL(vl_expr))) return; vl_fprintf_stmt(file, "["); vl_step_expr(file, range->left); if (range->right) { vl_fprintf_stmt(file, " : "); vl_step_expr(file, range->right); } vl_fprintf_stmt(file, "]"); } void vl_step_delay(FILE *file, vl_delay *delay) { StpTRACE("Printing delay\n"); if (delay == NIL(vl_delay)) return; vl_fprintf_stmt(file, " #("); vl_step_expr(file, delay->delay1); if (delay->delay2) { vl_fprintf_stmt(file, ", "); vl_step_expr(file, delay->delay2); if (delay->delay3) { vl_fprintf_stmt(file, ", "); vl_step_expr(file, delay->delay3); } } vl_fprintf_stmt(file, ") "); } void vl_step_id_range(FILE *file, vl_id_range *id_range) { StpTRACE("Printing id[range]\n"); if (id_range == NIL(vl_id_range)) return; vl_fprintf_stmt(file, "%s ", id_range->name); if (id_range->range != NIL(vl_range)) vl_step_range(file, id_range->range); if (dflow_analysis) { dataflow_analysis(dflow_analysis, id_range, !lhs_id, lhs_id); } } void vl_step_id_list(FILE *file, lsList ids) { vl_id_range *id; lsHandle handle; lsGen gen; gen = lsStart(ids); if (lsNext(gen, (lsGeneric*)&id, &handle) == LS_OK) { vl_step_id_range(file, id); while(lsNext(gen, (lsGeneric*)&id, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_id_range(file, id); } } (void) lsFinish(gen); } void vl_step_id_range_list(FILE *file, lsList ids) { vl_id_range *id; lsHandle handle; lsGen gen; if (ids == (lsList)0) return; gen = lsStart(ids); if (lsNext(gen, (lsGeneric*)&id, &handle) == LS_OK) { vl_step_id_range(file, id); while(lsNext(gen, (lsGeneric*)&id, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_id_range(file, id); } } (void) lsFinish(gen); } void vl_step_net_list(FILE *file, lsList nets) { void *net; lsHandle handle; lsGen gen; gen = lsStart(nets); if (lsNext(gen, (lsGeneric*)&net, &handle) == LS_OK) { vl_step_net(file, net); while(lsNext(gen, (lsGeneric*)&net, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ", "); vl_step_net(file, net); } } (void) lsFinish(gen); } void vl_step_net(FILE *file, void *net) { switch(((vl_expr *)net)->type) { case BassignStmt: vl_step_bassign_stmt(file, net); break; case NbassignStmt: { char buf[MAXSTRLEN]; yylineno = ((vl_bassign_stmt*)net)->lineno; sprintf(buf, ":%s: invalid continuous assignment", vl_currentModule->name->name); compile_error(buf); break; } case IDExpr: vl_step_expr(file, net); break; default: vl_step_id_range(file, (vl_id_range*)net); break; } } void vl_step_ports (FILE *file, lsList ports) { void *item; lsHandle handle; lsGen gen; vl_fprintf_stmt(file, "("); if (ports != (lsList)0) { gen = lsStart(ports); if (lsNext(gen, (lsGeneric*)&item, &handle) == LS_OK) { vl_step_port(file, item); while (lsNext(gen, (lsGeneric*)&item, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ","); vl_step_port(file, item); } } (void) lsFinish(gen); } vl_fprintf_stmt(file, ")"); } void vl_step_port(FILE *file, vl_portPtr port) { if (port->type == NamedPort) { vl_fprintf_stmt(file, "."); vl_step_id_range(file, port->id); vl_fprintf_stmt(file, "("); } vl_step_id_range_list(file, port->port_exp); if (port->type == NamedPort) { vl_fprintf_stmt(file, ")"); } } void vl_step_connects (FILE *file, lsList connects) { void *item; lsHandle handle; lsGen gen; if (connects != (lsList)0) { gen = lsStart(connects); if (lsNext(gen, (lsGeneric*)&item, &handle) == LS_OK) { vl_step_port_connect(file, (vl_port_connectPtr)item); while (lsNext(gen, (lsGeneric*)&item, &handle) != LS_NOMORE) { vl_fprintf_stmt(file, ","); vl_step_port_connect(file, (vl_port_connectPtr)item); } } (void) lsFinish(gen); } } void vl_step_port_connect(FILE *file, vl_port_connectPtr connect) { if (connect->type == NamedConnect) { vl_fprintf_stmt(file, "."); vl_step_id_range(file, connect->id); vl_fprintf_stmt(file, "("); } vl_step_expr(file, connect->expr); if (connect->type == NamedConnect) { vl_fprintf_stmt(file, ")"); } } void vl_step_mod_item_list (FILE *file, lsList mitems) { void *item; lsHandle handle; lsGen gen; StpTRACE("Printing Module Items\n"); if (mitems != (lsList)0) { gen = lsStart(mitems); if (lsNext(gen, (lsGeneric*)&item, &handle) == LS_OK) { vl_step_mod_item(file, item); while(lsNext(gen, (lsGeneric*)&item, &handle) != LS_NOMORE) { vl_step_mod_item(file, item); } } (void) lsFinish(gen); } } void vl_step_mod_item(FILE *file, void *item) { switch(((vl_decl *)item)->type) { case RealDecl: case EventDecl: vl_step_basicdecl(file, (vl_decl *)item); break; case IntDecl: case TimeDecl: vl_step_basicdecl(file, (vl_decl *)item); break; case InputDecl: case OutputDecl: case InoutDecl: case RegDecl: vl_step_rangedecl(file, (vl_rangedecl *)item); break; case ParamDecl: case DefparamDecl: vl_step_paramdecl(file, (vl_paramdecl *)item); break; case WireDecl: case TriDecl: case Tri0Decl: case Tri1Decl: case Supply0Decl: case Supply1Decl: case WandDecl: case TriandDecl: case WorDecl: case TriorDecl: case TriregDecl: vl_step_netdecl(file, (vl_netdecl *)item); break; case ContAssign: vl_step_cont_assign(file, (vl_cont_assign *)item); break; case TaskDecl: vl_step_task(file, (vl_task *)item); break; case IntFuncDecl: case RealFuncDecl: case RangeFuncDecl: vl_step_function(file, (vl_function *)item); break; case AndGate: case NandGate: case OrGate: case NorGate: case XorGate: case XnorGate: case BufGate: case Bufif0Gate: case Bufif1Gate: case NotGate: case Notif0Gate: case Notif1Gate: case PulldownGate: case PullupGate: case NmosGate: case RnmosGate: case PmosGate: case RpmosGate: case CmosGate: case RcmosGate: case TranGate: case RtranGate: case Tranif0Gate: case Rtranif0Gate: case Tranif1Gate: case Rtranif1Gate: vl_step_gate_inst_list(file, (vl_gate_inst_list *)item); break; case TeslaTimerGate: break; case ModInst: { char *mp; if (st_lookup(vl_description->mp_st, ((vl_mod_prim_inst_list *)item)->name->name, &mp)) { if (((typestructPtr)mp)->type == CombPrimDecl || ((typestructPtr)mp)->type == SeqPrimDecl) goto step_prim_inst; } } vl_step_mod_inst_list(file, (vl_mod_prim_inst_list *)item); break; step_prim_inst: case PrimInst: vl_step_prim_inst_list(file, (vl_mod_prim_inst_list *)item); break; case AlwaysStmt: case InitialStmt: vl_step_procstmt(file, (vl_procstmt *)item); break; default: internal_error("Unexpected Module Item"); break; } } void vl_step_decl_list (FILE *file, void *decls) { void *decl; lsHandle handle; lsGen gen; StpTRACE("Printing Decls\n"); if (decls == NIL(void)) return; gen = lsStart(decls); if (lsNext(gen, (lsGeneric*)&decl, &handle) == LS_OK) { vl_step_decl(file, decl); while(lsNext(gen, (lsGeneric*)&decl, &handle) != LS_NOMORE) { vl_step_decl(file, decl); } } (void) lsFinish(gen); } int vl_step_stmt_list (FILE *file, void *stmts) { void *stmt; lsHandle handle; lsGen gen; int step_flag=0; StpTRACE("Printing Statements\n"); gen = lsStart(stmts); if (lsNext(gen, (lsGeneric*)&stmt, &handle) == LS_OK) { step_flag = vl_step_stmt(file, stmt); while(lsNext(gen, (lsGeneric*)&stmt, &handle) != LS_NOMORE) { step_flag |= vl_step_stmt(file, stmt); } } (void) lsFinish(gen); return step_flag; } void vl_step_strength (FILE *file, int s) { vl_fprintf_stmt(file, "%s", vl_get_strength(s)); } void vl_step_gate (FILE *file, vl_gate_inst *gate) { vl_step_id_range(file, gate->name); vl_fprintf_stmt(file, "("); vl_step_expr_list(file, gate->terms); vl_fprintf_stmt(file, ")"); } void vl_step_prim (FILE *file, vl_mod_prim_inst *prim) { vl_step_id_range(file, prim->name); vl_fprintf_stmt(file, "("); vl_step_expr_list(file, prim->ports); vl_fprintf_stmt(file, ")"); } void vl_step_param_vals (FILE *file, lsList param_vals) { if (param_vals == (lsList)0) return; vl_fprintf_stmt(file, "#("); if (!((vl_delay*)param_vals)->delay1 && !((vl_delay*)param_vals)->delay2 && ((vl_delay*)param_vals)->delay3) vl_step_expr_list(file, (lsList)((vl_delay*)param_vals)->delay3); else if ( ((vl_delay*)param_vals)->delay1 && !((vl_delay*)param_vals)->delay2) vl_step_expr(file, ((vl_delay*)param_vals)->delay1); vl_fprintf_stmt(file, ")"); } void vl_step_modinst (FILE *file, vl_mod_prim_inst *mod) { vl_step_id_range(file, mod->name); vl_fprintf_stmt(file, " ("); vl_step_connects(file, mod->ports); vl_fprintf_stmt(file, ") "); } int vl_step_stmt (FILE *file, void *stmt) { int step_flag=0; if (stmt == NIL(void)) { vl_fprintf_stmt(file, ";\n"); return step_flag; } switch(((vl_bassign_stmt *)stmt)->type) { case BeginEndStmt: step_flag = vl_step_begin_end_stmt(file, (vl_begin_end_stmt *)stmt); break; case IfElseStmt: step_flag = vl_step_if_else_stmt(file, (vl_if_else_stmt *)stmt); break; case CaseStmt: case CasexStmt: case CasezStmt: step_flag = vl_step_case_stmt(file, (vl_case_stmt *)stmt); break; case CaseItem: step_flag = vl_step_stmt(file, ((vl_case_item *)stmt)->stmt); break; case DefaultItem: step_flag = vl_step_stmt(file, ((vl_case_item *)stmt)->stmt); break; case ForeverStmt: vl_step_forever_stmt(file, (vl_forever_stmt *)stmt); break; case RepeatStmt: if (!Repeat_Unrolling) { vl_step_repeat_stmt(file, (vl_repeat_stmt *)stmt); } else { int i, up_bnd; lsList unrolled_stmt; void *new_stmt; unrolled_stmt = lsCreate(); up_bnd = vl_eval_expr(((vl_repeat_stmt*)stmt)->count); for (i=0; istmt); lsNewEnd(unrolled_stmt, (lsGeneric)new_stmt, 0); vl_step_stmt(file, new_stmt); } ((vl_begin_end_stmt*)stmt)->type = BeginEndStmt; ((vl_begin_end_stmt*)stmt)->flags = 0; ((vl_begin_end_stmt*)stmt)->name = NIL(vl_id_range); ((vl_begin_end_stmt*)stmt)->decls = NIL(void); ((vl_begin_end_stmt*)stmt)->sig_st= NIL(st_table); ((vl_begin_end_stmt*)stmt)->stmts = unrolled_stmt; } break; case WhileStmt: vl_step_while_stmt(file, (vl_while_stmt *)stmt); break; case ForStmt: if (!Loop_Unrolling) { vl_step_for_stmt(file, (vl_for_stmt *)stmt); } else { vl_id_range *idx; char *name, *val; lsList unrolled_stmt; void *new_stmt; vl_expr *ival; vl_lval *idx_lhs; vl_bassign_stmt *assign_idx=NULL; idx = ((vl_for_stmt*)stmt)->init->lhs->name; st_insert(vl_currentModule->param_st, idx->name, (char*)idx); unrolled_stmt = lsCreate(); for (idx->mpg_master_exp = (void*)vl_eval_expr(((vl_for_stmt*)stmt)->init->rhs); vl_eval_expr(((vl_for_stmt*)stmt)->cond); idx->mpg_master_exp = (void*)vl_eval_expr(((vl_for_stmt*)stmt)->end->rhs)) { idx_lhs = vl_create_lval(IDExpr, vl_copy_id_range(idx), NIL(vl_range),(lsList)0); ival = vl_create_expr(IntExpr, (int)idx->mpg_master_exp, (double)0.0, NIL(vl_expr),NIL(vl_expr),NIL(vl_expr)); new_stmt = (void*)vl_copy_stmt(((vl_for_stmt*)stmt)->stmt); if (indexAssignment) { assign_idx = vl_create_bassign_stmt(BassignStmt, idx_lhs, NIL(void), ival); lsNewEnd(unrolled_stmt, (lsGeneric)assign_idx, 0); } lsNewEnd(unrolled_stmt, (lsGeneric)new_stmt, 0); if (indexAssignment) vl_step_stmt(file, assign_idx); vl_step_stmt(file, new_stmt); } ((vl_begin_end_stmt*)stmt)->type = BeginEndStmt; ((vl_begin_end_stmt*)stmt)->flags = 0; ((vl_begin_end_stmt*)stmt)->name = NIL(vl_id_range); ((vl_begin_end_stmt*)stmt)->decls = NIL(void); ((vl_begin_end_stmt*)stmt)->sig_st= NIL(st_table); ((vl_begin_end_stmt*)stmt)->stmts = unrolled_stmt; name = idx->name; st_delete(vl_currentModule->param_st, &name, &val); } break; case DelayControlStmt: vl_step_delay_control_stmt(file, (vl_delay_control_stmt *)stmt); break; case EventControlStmt: step_flag = vl_step_event_control_stmt(file, (vl_event_control_stmt *)stmt); break; case AssignStmt: case BassignStmt: case NbassignStmt: case DelayBassignStmt: case DelayNbassignStmt: case EventBassignStmt: case EventNbassignStmt: step_flag = vl_step_bassign_stmt(file, (vl_bassign_stmt *)stmt); vl_fprintf_stmt(file, ";\n"); break; case WaitStmt: vl_step_wait_stmt(file, (vl_wait_stmt *)stmt); break; case ForkJoinStmt: vl_step_fork_join_stmt(file, (vl_fork_join_stmt *)stmt); break; case TaskEnableStmt: case SysTaskEnableStmt: vl_step_task_enable_stmt(file, (vl_task_enable_stmt *)stmt); break; case DisableStmt: vl_step_disable_stmt(file, (vl_disable_stmt *)stmt); break; case DeassignStmt: vl_step_deassign_stmt(file, (vl_deassign_stmt *)stmt); break; case SendEventStmt: vl_fprintf_stmt(file, "-> "); vl_step_id_range(file, ((vl_send_event_stmt *)stmt)->name); if (vlPhase == 1 && fg_not_empty()) ((vl_send_event_stmt*)stmt)->fg_info = (char*)fg_new_assign_node(); vl_fprintf_stmt(file, ";\n"); break; default: { char msg[MAXSTRLEN]; sprintf(msg, "vl_step_stmt:Unexpected Statement Type %d", ((vl_bassign_stmt *)stmt)->type); internal_error(msg); } } return step_flag; } void vl_step_decl (FILE *file, void *decl) { switch(((vl_decl *)decl)->type) { case RealDecl: case EventDecl: case IntDecl: case TimeDecl: vl_step_basicdecl(file, (vl_decl *)decl); break; case InputDecl: case OutputDecl: case InoutDecl: case RegDecl: vl_step_rangedecl(file, (vl_rangedecl *)decl); break; case ParamDecl: case DefparamDecl: vl_step_paramdecl(file, (vl_paramdecl *)decl); break; case WireDecl: case TriDecl: case Tri0Decl: case Tri1Decl: case Supply0Decl: case Supply1Decl: case WandDecl: case TriandDecl: case WorDecl: case TriorDecl: case TriregDecl: vl_step_netdecl(file, (vl_netdecl *)decl); break; default: internal_error("Unexprected Declaration Type"); break; } } void vl_step_cont_assign (FILE *file, vl_cont_assign *assign) { vl_fprintf_stmt(file, "assign "); vl_step_strength(file, assign->strength); vl_step_delay(file, assign->delay); vl_step_net_list(file, assign->assigns); vl_fprintf_stmt(file, ";\n"); } char *vl_get_prim_symbol(unsigned char sym) { switch(sym) { case PrimNone: return(""); case Prim0: return("0"); case Prim1: return("1"); case PrimX: return("X"); case PrimQ: return("?"); case PrimR: return("R"); case PrimF: return("F"); case PrimP: return("P"); case PrimN: return("N"); case PrimS: return("*"); case PrimM: return("-"); case PrimB: return("B"); case Prim0X: return("(0X)"); case Prim1X: return("(1X)"); case PrimX0: return("(X0)"); case PrimX1: return("(X1)"); case PrimXB: return("(XB)"); case PrimBX: return("(BX)"); case PrimBB: return("(BB)"); case PrimQ0: return("(?0)"); case PrimQ1: return("(?1)"); case PrimQB: return("(?B)"); default: { char msg[MAXSTRLEN]; sprintf(msg, "Unexpected primitive symbol type %d", sym); internal_error(msg); return(NULL); } } } char *vl_get_strength(int type) { switch(type) { case 0: return("\0"); case Supply0Supply1: return("(supply0, supply1)"); case Supply0Strong1: return("(supply0, strong1)"); case Supply0Pull1: return("(supply0, pull1)"); case Supply0Weak1: return("(supply0, weak1)"); case Supply0HighZ1: return("(supply0, highz1)"); case Strong0Supply1: return("(strong0, supply1)"); case Strong0Strong1: return("(strong0, strong1)"); case Strong0Pull1: return("(strong0, pull1)"); case Strong0Weak1: return("(strong0, weak1)"); case Strong0HighZ1: return("(strong0, highz1)"); case Pull0Supply1: return("(pull0, supply1)"); case Pull0Strong1: return("(pull0, strong1)"); case Pull0Pull1: return("(pull0, pull1)"); case Pull0Weak1: return("(pull0, weak1)"); case Pull0HighZ1: return("(pull0, highz1)"); case Weak0Supply1: return("(weak0, supply1)"); case Weak0Strong1: return("(weak0, strong1)"); case Weak0Pull1: return("(weak0, pull1)"); case Weak0Weak1: return("(weak0, weak1)"); case Weak0HighZ1: return("(weak0, highz1)"); case HighZ0Supply1: return("(highz0, supply1)"); case HighZ0Strong1: return("(highz0, strong1)"); case HighZ0Pull1: return("(highz0, pull1)"); case HighZ0Weak1: return("(highz0, weak1)"); case HighZ0HighZ1: return("(highz0, highz1)"); case Supply1Supply0: return("(supply1, supply0)"); case Supply1Strong0: return("(supply1, strong0)"); case Supply1Pull0: return("(supply1, pull0)"); case Supply1Weak0: return("(supply1, weak0)"); case Supply1HighZ0: return("(supply1, highz0)"); case Strong1Supply0: return("(strong1, supply0)"); case Strong1Strong0: return("(strong1, strong0)"); case Strong1Pull0: return("(strong1, pull0)"); case Strong1Weak0: return("(strong1, weak0)"); case Strong1HighZ0: return("(strong1, highz0)"); case Pull1Supply0: return("(pull1, supply0)"); case Pull1Strong0: return("(pull1, strong0)"); case Pull1Pull0: return("(pull1, pull0)"); case Pull1Weak0: return("(pull1, weak0)"); case Pull1HighZ0: return("(pull1, highz0)"); case Weak1Supply0: return("(weak1, supply0)"); case Weak1Strong0: return("(weak1, strong0)"); case Weak1Pull0: return("(weak1, pull0)"); case Weak1Weak0: return("(weak1, weak0)"); case Weak1HighZ0: return("(weak1, highz0)"); case HighZ1Supply0: return("(highz1, supply0)"); case HighZ1Strong0: return("(highz1, strong0)"); case HighZ1Pull0: return("(highz1, pull0)"); case HighZ1Weak0: return("(highz1, weak0)"); case HighZ1HighZ0: return("(highz1, highz0)"); case Small: return("(small)"); case Medium: return("(medium)"); case Large: return("(large)"); default: { char err_msg[MAXSTRLEN]; sprintf(err_msg, "Unexpected strength type %d", type); internal_error(err_msg); return(NULL); } } } char *vl_get_expr_op(int type) { switch(type) { case IDExpr: case BitSelExpr: case PartSelExpr: case ConcatExpr: case MinTypMaxExpr: case IntExpr: case RealExpr: case StringExpr: case FuncExpr: return(""); case UplusExpr: return("+"); case UminusExpr: return("-"); case UnotExpr: return("!"); case UcomplExpr: return("~"); case UandExpr: return("&"); case UnandExpr: return("~&"); case UorExpr: return("|"); case UnorExpr: return("~|"); case UxorExpr: return("^"); case UxnorExpr: return("~^"); case BplusExpr: return("+"); case BminusExpr: return("-"); case BtimesExpr: return("*"); case BdivExpr: return("/"); case BremExpr: return("%"); case Beq2Expr: return("=="); case Bneq2Expr: return("!="); case Beq3Expr: return("==="); case Bneq3Expr: return("!=="); case BlandExpr: return("&&"); case BlorExpr: return("||"); case BltExpr: return("<"); case BleExpr: return("<="); case BgtExpr: return(">"); case BgeExpr: return(">="); case BandExpr: return("&"); case BorExpr: return("|"); case BxorExpr: return("^"); case BxnorExpr: return("~^"); case BlshiftExpr: return("<<"); case BrshiftExpr: return(">>"); case TcondExpr: return("?"); default: internal_error("Unexpected expression type"); return(NULL); } } static void record_program_location(vl_procstmt *procstmt) { set_add(new_label(), procstmt->pc->values); } char *new_label() { static int label_count = 0; static char buf[MAXSTRLEN]; sprintf(buf, "%s%d", LABEL, label_count++); return buf; } static void register_clock(FILE *file, vl_event_expr *event) { if (event->expr->type != IDExpr) return; if (!vl_currentModule->clk) vl_currentModule->clk = event; else if (strcmp(vl_currentModule->clk->expr->u.name->name, event->expr->u.name->name) && implicitClocking && !vlTimedSystem) { char msg[MAXSTRLEN]; sprintf(msg, "'%s':%s is assumed to be clock, %s is reused as clock", vl_currentModule->name->name, vl_currentModule->clk->expr->u.name->name, event->expr->u.name->name); Translate_Warning(msg); } file = file; } vl_begin_end_stmt *vl_fake_wait_stmt(FILE *file, vl_wait_stmt *wait_stmt) { lsList assign_list; vl_bassign_stmt *assignment; vl_expr *cond_expr; void *wait_ctrl_stmt; vl_expr *id_expr; vl_event_expr *event_expr; vl_event_control_stmt *edge_stmt; vl_expr *ncond_expr; lsList stmt_list; vl_if_else_stmt *if_else_stmt; vl_begin_end_stmt *retval; cond_expr = wait_stmt->cond; wait_ctrl_stmt = wait_stmt->stmt; assignment = vl_create_bassign_stmt(AssignStmt, vl_create_lval(IDExpr, vl_create_id_range(vlStrdup(new_termname()), NIL(vl_range)), NIL(vl_range), (lsList)0), NIL(void), cond_expr); assign_list = lsCreate(); lsNewEnd(assign_list, (lsGeneric)assignment, 0); lsNewBegin(vl_currentModule->mod_items, (lsGeneric)vl_create_cont_assign_stmt(0, NIL(vl_delay), assign_list), 0); id_expr = vl_create_expr(IDExpr, 0, (double)0.0, assignment->lhs->name, NIL(vl_expr),NIL(vl_expr)); event_expr = vl_create_event_expr(PosedgeEventExpr, id_expr); edge_stmt = vl_create_event_control_stmt(event_expr, NIL(typestruct)); ncond_expr = vl_create_expr(UnotExpr, 0, (double)0.0, id_expr, NIL(vl_expr), NIL(vl_expr)); if_else_stmt = vl_create_if_else_stmt(ncond_expr, edge_stmt, NIL(typestruct)); vl_step_if_else_stmt(file, if_else_stmt); stmt_list = lsCreate(); lsNewEnd(stmt_list, (lsGeneric)if_else_stmt, 0); lsNewEnd(stmt_list, (lsGeneric)wait_ctrl_stmt, 0); retval = vl_create_begin_end_stmt(NIL(vl_id_range), LS_NH, stmt_list); return retval; } static void assoc_formal_actual(vl_task *task_dfn, lsList formal, lsList actual) { lsGen agen, fgen; lsHandle ahandle, fhandle; char *formal_arg; vl_expr *actual_arg; if (lsLength(formal) != lsLength(actual)) { compile_error("Initialize task with improper argument(s)"); } for (fgen=lsStart(formal), agen=lsStart(actual); lsNext(fgen, (lsGeneric*)&formal_arg, &fhandle) != LS_NOMORE && lsNext(agen, (lsGeneric*)&actual_arg, &ahandle) != LS_NOMORE; ) { char *dummy_formal, *dummy_actual; check_task_arg(actual_arg->type == IDExpr || actual_arg->type == PartSelExpr || actual_arg->type == BitSelExpr, task_dfn); dummy_formal = formal_arg; st_delete(task_dfn->sig_st, &dummy_formal, &dummy_actual); st_insert(task_dfn->sig_st, formal_arg, actual_arg->u.name->name); } lsFinish(fgen); lsFinish(agen); } vl_module *vl_chk_param_dup_master(vl_mod_prim_inst_list *modinstlist) { vl_module *retval; vl_delay *param_vals; vl_id_range *pval; lsList delay_list=(lsList)0; lsGen delay_gen=(lsGen)0; lsHandle delay_handle; int num_params=0; int i; vl_module *master, *new_module; char *pname; lsGen pgen; lsHandle phandle; vl_expr *de; int need_new_master; int rtvl; if (modinstlist->delays == NIL(vl_delay)) return NIL(vl_module); param_vals = modinstlist->delays; if (!param_vals->delay1 && !param_vals->delay2 && param_vals->delay3) { delay_list = (lsList)param_vals->delay3; delay_gen = lsStart(delay_list); num_params = lsLength(delay_list); } else if (param_vals->delay1 && !param_vals->delay2) { delay_list = (lsList)0; num_params = 1; } rtvl = st_lookup(vl_description->mp_st, modinstlist->name->name, (char**)&master); assert(rtvl); if (lsLength(master->param_list)==0) { if (WarningLevel >= 1) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s:Giving parameter to a module(%s) without parameter", vl_currentModule->name->name, master->name->name); compile_error(buf); } else return NIL(vl_module); } for (pgen=lsStart(master->param_list), need_new_master=0, i=0; lsNext(pgen, (lsGeneric*)&pname, &phandle)!=LS_NOMORE && iparam_st, pname, (char**)&pval); assert(retval); if (delay_list) { int rtvl2 = lsNext(delay_gen,(lsGeneric*)&de,&delay_handle); assert(rtvl2 != LS_NOMORE); i++; } else { de = param_vals->delay1; } if ((int)(pval->mpg_master_exp) != vl_eval_expr(de)) need_new_master=1; } lsFinish(pgen); if (delay_list) lsFinish(delay_gen); retval = master; if (need_new_master) { char buf[MAXSTRLEN]; vl_module *orig_module; sprintf(buf, "%s%04x", master->name->name, ++master->dup_count); new_module = vl_copy_rename_module(master, buf); if (delay_list) delay_gen = lsStart(delay_list); for (pgen=lsStart(new_module->param_list), need_new_master=0, i=0; lsNext(pgen, (lsGeneric*)&pname, &phandle)!=LS_NOMORE && iparam_st, pname, (char**)&pval); assert(retval); if (delay_list) { int rtvl2 = lsNext(delay_gen,(lsGeneric*)&de,&delay_handle); assert(rtvl2 != LS_NOMORE); i++; } else { de = param_vals->delay1; } *(int*)&(pval->mpg_master_exp) = vl_eval_expr(de); } lsFinish(pgen); if (delay_list) lsFinish(delay_gen); orig_module = vl_currentModule; vl_currentModule = new_module; vl_step_module(stdout, new_module); vl_currentModule = orig_module; retval = new_module; } return retval; } static void vl_expand_Q(FILE *file, lsList tags) { lsHandle handle; lsGen gen; vl_expr *expr; unsigned int i; int num_Q; char *bit_str; array_t *q_array; for (gen=lsStart(tags); lsNext(gen,(lsGeneric*)&expr,&handle)!=LS_NOMORE; ) { if (expr->type != BitExpr) continue; if (strstr((char*)expr->u.exprs.e3,"?")) { for (i=0, num_Q=0; iu.exprs.e3); i++) if (((char*)expr->u.exprs.e3)[i] == '?') num_Q++; bit_str = vlStrdup((char*)expr->u.exprs.e3); q_array = array_alloc(int, 0); for (i=0; iu.exprs.e3); i++) if (((char*)expr->u.exprs.e3)[i] == '?') array_insert_last(int, q_array, i); rec_expand_Q(num_Q-1, q_array, bit_str, tags, gen, &handle); array_free(q_array); vl_chk_free(bit_str); } } lsFinish(gen); } static void rec_expand_Q(int num_Q, array_t *q_array, char *bit_str, lsList tags, lsGen gen, lsHandle *phandle) { int b0, b1; vl_expr *new_expr; int ith; if (num_Q == -1) { encodebit(bit_str, &b1, &b0); new_expr = vl_create_expr(BitExpr, 0, (double)0.0, (void*)b1, (void*)b0, (void*)vlStrdup(bit_str)); lsInBefore(gen, (lsGeneric)new_expr, phandle); } else { ith = array_fetch(int, q_array, num_Q); bit_str[ith] = '1'; rec_expand_Q(num_Q-1, q_array, bit_str, tags, gen, phandle); bit_str[ith] = '0'; rec_expand_Q(num_Q-1, q_array, bit_str, tags, gen, phandle); } } static void check_task_arg(int ok, vl_task *task_dfn) { char buf[MAXSTRLEN]; if (ok) return; sprintf(buf, "%s: invoking task '%s' with non-simple id argiment(s); cannot be handled by vl2mv", vl_currentModule->name->name, task_dfn->name->name); yylineno = -1; compile_error(buf); }