/* 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_write.c,v 1.6 2009/03/09 20:25:58 fabio Exp $ */ #include #include #include "util.h" #include "st.h" #include "array.h" #include "list.h" #include "set.h" #include "graph.h" #include "stack.h" #include "set.h" #include "vl_types.h" #include "vl_defs.h" #include "vlr_int.h" #include "vl_create.h" #include "vl_traverse.h" #include "vl_write.h" #include "vl_write_util.h" #include "vl_fg_defs.h" #include "vl_fg_types.h" #include "vl_flowgraph.h" #include "vl_mux.h" #include "vl_vardecl.h" #include "vl_edgedetector.h" #include "vl_nonblock.h" #include "verilog.h" #include extern vl_desc *mod_list; extern int ith_module; extern int dflow_analysis; extern int vlTimedSystem; extern int vis_nond_var; extern int vis_nond; extern int Warn_Uninitialized; extern int encodeTimer; static int WrtTrace = 0; static int Being_Conditioned=0; static int recordCombAlways=0; static array_t *assign_array=NIL(array_t); static st_table *auxSigST=NIL(st_table); int dumpSyncCkt = 0; int implicitClockWire = 0; int vl_noTimers = 0; int vl_preDeclare = 0; int debug_mode = 0; int Use_MV_Lib = 0; int set_notation = 1; int do_encoding = 0; int implicitDeclare = 1; int implicitClocking = 1; int instantiateAll = 1; int combinationalReduction = 0; int chk_IncompleteBranch = 1; int smartEvent = 1; int wireRegister = 0; int nd_check_ok = 0; int compatibleChecking = 0; int check_rhs_sensitivity = 1; int decomposeTable = DEFAULT_MAX_TABLE_SIZE; int Zconnection = 0; int NoDetailedComment = 0; int portPerLine = 20; double vl_expr_aux1_val=(double)0; double vl_expr_aux2_val=(double)0; double vl_expr_aux3_val=(double)0; int vl_expr_aux1_flag = 0; int vl_expr_aux2_flag = 0; int vl_expr_aux3_flag = 0; int silent_err = 0; int Vlerrno = 0; vl_module *vl_encloseModule; int lhs_hi, lhs_lo; vl_term *lhs_term=NIL(vl_term); int insideConcat=0; vl_term *Initial_Signal = NIL(vl_term); set_t *sensitiveList = NIL(set_t); vl_term *edge_triggering = NIL(vl_term); FILE *mv_file; int lhs_must_be_wire = 0; graph_t *vl_writeFlowGraph=NIL(graph_t); stack_t vl_pauseStack = (stack_t)0; lsList vl_current_pause_list = (lsList)0; lsList vl_current_vars_list = (lsList)0; vl_id_range *masterIdDfn = NIL(vl_id_range); char *cntxt_event; lsGen curModGen; lsHandle curModHandle; lsHandle *PcurModHandle; int rst_ckt = 0; int use_rst_ckt = 0; int mark_sel_var = 0; char *ctrl_syndrome = NIL(char); lsList ctrl_list; int ith_ctrl; char *rst_ctrl_syndrome = NIL(char); lsList rst_ctrl_list; int rst_ith_ctrl; st_table *vl_currentModule_combVar_st; static int in_procedure = 0; static st_table *vl_current_init_vars=NIL(st_table); static st_table *final_vars=NIL(st_table); array_t *cur_vars_array = NIL(array_t); static void vl_write_function_list ARGS((FILE *file)); static void vl_write_formal_argument ARGS((FILE *file)); static void vl_write_initial_generator ARGS((FILE *file)); static void vl_write_timer ARGS((FILE *file, lsList graph_list)); static void vl_write_encoding ARGS((FILE *file)); static void vl_write_prim_table ARGS((FILE *file, vl_primitive *prim, char *edge_detectors)); static void instantiate_prim_latch ARGS((FILE *file, st_table *sig_st)); static void instantiate_edge_detector ARGS((FILE *file, vl_primitive *prim)); static void non_block_assignment ARGS((FILE *file, st_table *vars)); static void quasi_cont_assignment ARGS((FILE *file)); static void vl_write_gate_inst_list ARGS((FILE *file, vl_gate_inst_list *gate_list)); static void vl_write_tesla_timer_inst_list ARGS((FILE *file, vl_gate_inst_list *gate_list)); static void vl_write_prim_inst_list ARGS((FILE *file, vl_mod_prim_inst_list *priminstlist)); static void vl_predefine_vars ARGS((FILE *file, st_table *vars)); static void vl_timed_init_mux ARGS((FILE *file, vl_term *ctrl_term, st_table *orig_vars, st_table *init_vars, st_table *feedback_vars)); static void vl_write_prim_inst ARGS((FILE *file, vl_primitive *master, vl_mod_prim_inst *inst)); static void vl_write_gate_inst ARGS((FILE *file, short type, vl_gate_inst *gate)); static void vl_write_tesla_timer_inst ARGS((FILE *file, vl_gate_inst *gate, int lb, int ub)); static void vl_register_pause ARGS((vertex_t *pause_node, st_table *old_vars)); static void vl_prioritize_sequence ARGS((FILE *file, lsList vars_list, lsList pause_list, st_table *result_st)); static void vl_write_vector_red_op ARGS((FILE *file, short type, vl_term *in, int inverted, vl_term *out)); enum st_retval vl_write_desc(char *name, char *value, char *arg) { if (!Initial_Signal) Initial_Signal = vl_create_term(vl_create_id_range(vlStrdup("_initial_"),NIL(vl_range)), 0, -1); if (((typestructPtr)value)->type == ModDecl) { vl_write_module(mv_file, (vl_module*)value); } else if (((typestructPtr)value)->type == CombPrimDecl || ((typestructPtr)value)->type == SeqPrimDecl) { vl_write_primitive(mv_file, (vl_primitive*)value); } name = name; arg = arg; return ST_CONTINUE; } void vl_write_module(FILE *file, vl_module *mod) { char *dummy; if (mod == NULL) return; if (st_lookup(mod_list->mod_holes, mod->name->name, &dummy)) return; ASSERT(mod->type==ModDecl, "Expecting ModDecl"); vl_currentModule = mod; WrtTRACE("writing module\n"); ctrl_syndrome = (char*)chk_malloc(mod->syndrome_width+1); memset(ctrl_syndrome, (int)'-', mod->syndrome_width); ctrl_syndrome[mod->syndrome_width] = '\0'; rst_ctrl_syndrome = (char*)chk_malloc(mod->rst_syndrome_width+1); memset(rst_ctrl_syndrome, (int)'-', mod->rst_syndrome_width); rst_ctrl_syndrome[mod->rst_syndrome_width] = '\0'; ctrl_list = lsCreate(); rst_ctrl_list = lsCreate(); ith_ctrl = 0; rst_ith_ctrl = 0; fprintf(file, "%s %s ", HSIS_MODEL, mod->name->name); vl_write_formal_argument(file); fprintf(file, "\n"); vl_write_io_list(file); vl_write_svar(file); vl_write_consts(file); if (vlTimedSystem || !implicitClocking) { vl_preDeclare = 1; vl_write_timer(file, mod->flow_graphs); } vl_write_mod_item_list(file, mod->mod_items); if (vlTimedSystem || !implicitClocking) { vl_preDeclare = 0; vl_write_timer(file, mod->flow_graphs); } vl_write_initial_generator(file); fprintf(file, ".end\n"); vl_write_function_list(file); vl_write_encoding(file); vl_currentModule = NIL(vl_module); lsDestroy(ctrl_list, 0); lsDestroy(rst_ctrl_list, 0); vl_chk_free(ctrl_syndrome); vl_chk_free(rst_ctrl_syndrome); ctrl_syndrome = NIL(char); rst_ctrl_syndrome = NIL(char); } void vl_write_primitive(FILE *file, vl_primitive *prim) { char *edge_detectors; if (prim == NULL) return; assert(prim->type==CombPrimDecl || prim->type==SeqPrimDecl); vl_currentPrimitive = prim; vl_currentModule = (vl_module*)prim; WrtTRACE("writing primitive\n"); fprintf(file, "%s %s\n", HSIS_MODEL, prim->name->name); vl_write_io_list(file); instantiate_prim_latch(file, prim->sig_st); vl_write_svar(file); edge_detectors = vl_write_prim_table_header(file, prim); vl_write_prim_table(file, prim, edge_detectors); instantiate_edge_detector(file, prim); fprintf(file, ".end\n\n\n"); vl_currentModule = NIL(vl_module); vl_currentPrimitive = NIL(vl_primitive); vl_chk_free(edge_detectors); } static void vl_write_function_list(FILE *file) { st_generator *gen; char *fname; vl_function *func_def; gen = st_init_gen(vl_currentModule->func_st); while (st_gen(gen, (char**)&fname, (char**)&func_def)) { vl_write_function(file, func_def); } st_free_gen(gen); } void vl_write_function(FILE *file, vl_function *func) { st_table *vars_touched; array_t *vars_array; vl_module *old_module; if (func == NIL(vl_function)) return; old_module = vl_currentModule; vl_encloseModule = vl_currentModule; vl_currentModule = (vl_module*)func; vl_currentFunction = func; vl_pauseStack = create_stack(); WrtTRACE("writing function\n"); vars_array = array_alloc(st_table*, 0); vars_touched = st_init_table(strcmp, st_strhash); fprintf(file, "%s %s ", HSIS_MODEL, func->name->name); vl_write_formal_argument(file); fprintf(file, "\n"); vl_write_io_list(file); vl_write_svar(file); vl_write_stmt_list(file, func->stmts, NO_MUX, NIL(vl_term), vars_touched); array_insert_last(st_table*, vars_array, vars_touched); func_conflict_arbitrator(file, vl_currentFunction->name, vars_array); fprintf(file, ".end\n\n\n"); vl_currentModule = old_module; vl_currentFunction = NIL(vl_function); vl_encloseModule = NIL(vl_module); destroy_stack(vl_pauseStack, 0); vl_pauseStack = (lsList)0; } static void vl_write_formal_argument(FILE *file) { } void vl_write_io_list(FILE *file) { st_generator *gen; char *key; vl_id_range *id_sym; int lo, hi; char *dir; lsGen ports_gen; lsHandle port_handle, port_id_handle; vl_port *port; vl_id_range *port_id, *port_id_sym; int ithItem; fprintf(file, "%s I/O ports\n", HSIS_COMMENT); if (vl_currentModule->flags & WithInitial) if (ith_module!=0) if (use_rst_ckt) fprintf(file,".inputs %s\n", Initial_Signal->name->name); if (vl_currentModule->ports) { ports_gen = lsStart(vl_currentModule->ports); while (lsNext(ports_gen,(lsGeneric*)&port,&port_handle) != LS_NOMORE) { if (!vl_currentFunction) { if (!port->port_exp) continue; lsFirstItem(port->port_exp, (lsGeneric*)&port_id, &port_id_handle); } else port_id = (vl_id_range*)port; if (!st_lookup(vl_currentModule->sig_st, port_id->name, (char**)&port_id_sym)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "port %s is not defined in module %s", port_id->name, vl_currentModule->name->name); compile_error(buf); } if (!(port_id_sym->flags & InPort) && !(port_id_sym->flags & OutPort)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "port %s has no direction in module %s", port_id->name, vl_currentModule->name->name); compile_error(buf); } } lsFinish(ports_gen); } ithItem = 0; gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, (char**)&key, (char**)&id_sym)) { if (!(id_sym->flags & InPort) && !(id_sym->flags & OutPort)) continue; if (strstr(id_sym->name, SEP_LATCH)) continue; if (strstr(id_sym->name, SEP_QUASI)) continue; if (!vl_currentFunction && implicitClocking && !vlTimedSystem) { if (vl_currentModule->clk) { if (!strcmp(vl_currentModule->clk->expr->u.name->name, key) && !vl_currentPrimitive) { if (!implicitClockWire) continue; } } else { if (!strcmp(key, CLOCK)) { if (!implicitClockWire) continue; } } } dir = (id_sym->flags & InPort) ? ".inputs":".outputs"; if (id_sym->flags & MVar) { declare_mvar_io(file, dir, id_sym); } else { get_hilo(id_sym, &hi, &lo); if (lo > hi) { declare_bin_scalar_io(file, dir, id_sym); } else { declare_bin_vector_io(file, dir, id_sym); } } } st_free_gen(gen); } void vl_write_svar(FILE *file) { st_generator *gen; char *key; vl_id_range *id_sym; lsList domain; int lo, hi; gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { vl_enumerator *enum_elt; lsGen enum_gen; lsHandle enum_handle; int j; if (str_matchtail(id_sym->name,SEP_LATCH)) continue; if (!vl_currentFunction && implicitClocking && !vlTimedSystem) { if (vl_currentModule->clk) { if (!strcmp(vl_currentModule->clk->expr->u.name->name, key) && !vl_currentPrimitive) { if (!implicitClockWire) continue; else fprintf(file, "%s %s ;\n", SMV_CLOCK, vl_currentModule->clk->expr->u.name->name); } } } if (!(id_sym->flags & MVar)) { continue; } if (!id_sym->range) { domain = id_sym->id_type->specifier->u.enum_type->domain_list; get_hilo(id_sym, &hi, &lo); fprintf(file, ".mv %s %d ", id_sym->name, lsLength(domain)); for (enum_gen=lsStart(domain), j=0; lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE; j++) { fprintf(file, "%s ", enum_elt->name); } lsFinish(enum_gen); fprintf(file, "\n"); } else { int idx_hi, idx_lo, idx; idx_lo = vl_eval_expr(id_sym->range->left); if (id_sym->range->right) idx_hi = vl_eval_expr(id_sym->range->right); else idx_hi = idx_lo; for (idx=idx_lo; idx<=idx_hi; idx++) { domain = id_sym->id_type->specifier->u.enum_type->domain_list; get_hilo(id_sym, &hi, &lo); fprintf(file, ".mv %s%s%d%s %d ", id_sym->name, SEP_LARRAY, idx, SEP_RARRAY, lsLength(domain)); for (enum_gen=lsStart(domain); lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s ", enum_elt->name); } lsFinish(enum_gen); fprintf(file, "\n"); } } } st_free_gen(gen); } void vl_write_mod_item_list (FILE *file, lsList mitems) { vl_decl *item; lsHandle fg_handle; lsGen fg_gen; array_t *vars_array; st_table *var_touched, *final_vars; st_table *comb_st, *tmp_st; st_table *old_sensitiveList; WrtTRACE("writing Module Items\n"); vars_array = array_alloc(st_table*, 0); cur_vars_array = vars_array; vl_currentModule_combVar_st = comb_st = st_init_table(strcmp, st_strhash); if (mitems != (lsList)0) { for (curModGen = lsStart(mitems), fg_gen = lsStart(vl_currentModule->flow_graphs); lsNext(curModGen, (lsGeneric*)&item, &curModHandle) != LS_NOMORE; ) { PcurModHandle = &curModHandle; if (((vl_decl*)item)->type == AlwaysStmt) lsNext(fg_gen, (lsGeneric*)&vl_writeFlowGraph, &fg_handle); else vl_writeFlowGraph = NIL(graph_t); old_sensitiveList = sensitiveList; recordCombAlways = 0; if ((sensitiveList= fg_graph_has_one_data_detector(vl_writeFlowGraph)) && combinationalReduction && implicitClocking) { vl_currentModule->combVar_st = tmp_st = st_init_table(strcmp, st_strhash); recordCombAlways = 1; } else { vl_currentModule->combVar_st = tmp_st = NIL(st_table); } var_touched = vl_write_mod_item(file, item, NIL(st_table)); vl_writeFlowGraph = NIL(graph_t); if (var_touched) { array_insert_last(st_table*, vars_array, var_touched); } if (!vl_currentModule->combVar_st) { st_generator *gen; char *key; char *dummy; if (var_touched) { gen = st_init_gen(var_touched); while (st_gen(gen, &key, (char**)&dummy)) if (!st_lookup(vl_currentModule->seqVar_st, key, &dummy)) st_insert(vl_currentModule->seqVar_st, key, (char*)0); st_free_gen(gen); } } if (tmp_st) { if (vl_currentModule->combVar_st) { st_generator *gen; vl_id_range *id_sym; char *key; gen = st_init_gen(vl_currentModule->combVar_st); while (st_gen(gen, &key, (char**)&id_sym)) { st_insert(comb_st, key, (char*)id_sym); } st_free_gen(gen); } st_free_table(tmp_st); } sensitiveList = old_sensitiveList; } (void) lsFinish(fg_gen); } vl_currentModule->combVar_st = comb_st; vl_currentModule_combVar_st = NIL(st_table); final_vars = conflict_arbitrator(file, vars_array); non_block_assignment(file, final_vars); instantiate_latch(file, final_vars); quasi_cont_assignment(file); cur_vars_array = NIL(array_t); } char *vl_write_prim_table_header(FILE *file, vl_primitive *prim) { lsGen port_gen; vl_port *port; lsHandle port_handle, port_id_handle; vl_id_range *port_id, *port_id_sym; int ith_port=0; char *retval; fprintf(file, ".names "); retval = (char*)chk_malloc(lsLength(prim->ports)+1); port_gen = lsStart(prim->ports); while (lsNext(port_gen, (lsGeneric*)&port, &port_handle) != LS_NOMORE) { lsFirstItem(port->port_exp, (lsGeneric*)&port_id, &port_id_handle); if (!st_lookup(prim->sig_st, port_id->name, (char**)&port_id_sym)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "port %s is not defined in primitive %s", port_id->name, vl_currentModule->name->name); compile_error(buf); } retval[ith_port] = 0; if (prim->type ==SeqPrimDecl) { if (port_id_sym->flags & InPort) { if (need_edge_detector(prim->entries, ith_port)) { port_id_sym->flags |= EdgeDetector; fprintf(file, "%s%s %s ", port_id_sym->name, PIN_DELAYED, port_id_sym->name); retval[ith_port] = 1; } else { fprintf(file, "%s ", port_id_sym->name); } ith_port++; } } else { if (port_id_sym->flags & InPort) { fprintf(file, "%s ", port_id_sym->name); ith_port++; } } } lsFinish(port_gen); port_gen = lsStart(prim->ports); while (lsNext(port_gen, (lsGeneric*)&port, &port_handle) != LS_NOMORE) { lsFirstItem(port->port_exp, (lsGeneric*)&port_id, &port_id_handle); st_lookup(prim->sig_st, port_id->name, (char**)&port_id_sym); if (port_id_sym->flags & OutPort) { if (prim->type == SeqPrimDecl) fprintf(file, "%s %s%s\n", port_id_sym->name, port_id_sym->name, SEP_LATCH); else fprintf(file, "%s\n", port_id_sym->name); } } lsFinish(port_gen); return retval; } static void vl_write_prim_table(FILE *file, vl_primitive *prim, char *edge_detectors) { vl_prim_entry *e; int i, bin, c, num_combination, ith_dup; lsHandle handle; lsGen gen; if (prim->entries == NULL) return; WrtTRACE("Writing primitive table\n"); for(gen = lsStart(prim->entries); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE; ) { for (i=0, num_combination=1; i<10; i++) { if (e->inputs[i] == PrimNone) break; else { if (!(IS_TRANSITION(e->inputs[i]) || !edge_detectors[i])) if (!strcmp(vl_translate_prim_symbol(e->inputs[i]),"-")) num_combination <<= 1; } } for (c=0; cinputs[i] == PrimNone) break; else { if (IS_TRANSITION(e->inputs[i]) || !edge_detectors[i]) fprintf(file,"%s ", vl_translate_prim_symbol(e->inputs[i])); else if (!strcmp(vl_translate_prim_symbol(e->inputs[i]), "-")) { fprintf(file, "%d %d ", (c>>ith_dup)&1,(c>>ith_dup)&1); ith_dup++; } else fprintf(file,"%s %s ", vl_translate_prim_symbol(e->inputs[i]), vl_translate_prim_symbol(e->inputs[i])); } } if (prim->type == SeqPrimDecl && e->next_state == PrimM) { if (!strcmp(vl_translate_prim_symbol(e->next_state), "-")) { fprintf(file, "%d %d\n", bin, bin); if (bin++ < 1) goto dump_entry; } else { fprintf(file, "%s %s\n", vl_translate_prim_symbol(e->state), vl_translate_prim_symbol(e->state)); } continue; } if (prim->type == SeqPrimDecl) fprintf(file, "%s ", vl_translate_prim_symbol(e->state)); fprintf(file, "%s ", vl_translate_prim_symbol(e->next_state)); fprintf(file, "%s\n", vl_translate_prim_symbol(e->state)); } } (void) lsFinish(gen); } st_table *vl_write_mod_item(FILE *file, vl_decl *item, st_table *other_vars) { st_table *var_touched=NIL(st_table); vl_term *ctrl_term; switch(item->type) { case RealDecl: case EventDecl: break; case IntDecl: case TimeDecl: break; case InputDecl: case OutputDecl: case InoutDecl: case RegDecl: break; case ParamDecl: case DefparamDecl: break; case WireDecl: var_touched = st_init_table(strcmp, st_strhash); vl_write_wiring_assign(file, (vl_netdecl*)item, var_touched); break; case TriDecl: case Tri0Decl: case Tri1Decl: case Supply0Decl: case Supply1Decl: case WandDecl: case TriandDecl: case WorDecl: case TriorDecl: case TriregDecl: break; case ContAssign: var_touched = st_init_table(strcmp, st_strhash); vl_write_cont_assign(file, (vl_cont_assign*)item, var_touched); break; case TaskDecl: break; case IntFuncDecl: { char buf[MAXSTRLEN]; sprintf(buf, "'%s': can handle int function %s yet", vl_currentModule->name->name, ((vl_function*)item)->name->name); Translate_Warning(buf); break; } case RealFuncDecl: { char buf[MAXSTRLEN]; sprintf(buf, "'%s': can handle real function %s yet", vl_currentModule->name->name, ((vl_function*)item)->name->name); Translate_Warning(buf); break; } case RangeFuncDecl: 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_write_gate_inst_list(file, (vl_gate_inst_list*)item); break; case TeslaTimerGate: vl_write_tesla_timer_inst_list(file, (vl_gate_inst_list*)item); 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 write_prim_inst; } } vl_write_mod_inst_list(file, (vl_mod_prim_inst_list*)item); break; write_prim_inst: case PrimInst: vl_write_prim_inst_list(file, (vl_mod_prim_inst_list*)item); break; case InitialStmt: vl_write_reset(file, (vl_procstmt*)item); break; case AlwaysStmt: if (((fg_graph_info*)vl_writeFlowGraph->user_data)->fg_id == -1) { fg_new_fg_id(); ((fg_graph_info*)vl_writeFlowGraph->user_data)->fg_id = fg_fg_id(); } else { fg_set_fg_id(((fg_graph_info*)vl_writeFlowGraph->user_data) ->fg_id); } var_touched = st_init_table(strcmp, st_strhash); if (vlTimedSystem) { vl_current_init_vars = st_init_table(strcmp, st_strhash); vl_predefine_vars(file, var_touched); } var_touched = vl_write_procstmt(file, (vl_procstmt*)item, var_touched); if (vlTimedSystem) { ctrl_term = test_against_lc_init(file); if (final_vars && vlTimedSystem) vl_timed_init_mux(file, ctrl_term, NIL(st_table), vl_current_init_vars, final_vars); else vl_timed_init_mux(file, ctrl_term, NIL(st_table), vl_current_init_vars, var_touched); final_vars = NIL(st_table); st_free_table(vl_current_init_vars); vl_current_init_vars = NIL(st_table); } fg_associate_id_vars(fg_fg_id(), var_touched); break; default: internal_error("Unexpected Module Item"); break; } other_vars = other_vars; return var_touched; } void vl_write_mod_inst_list(FILE *file, vl_mod_prim_inst_list *modinstlist) { vl_module *mod; vl_mod_prim_inst *modinst; if (st_lookup(mod_list->mp_st, modinstlist->name->name, (char**)&mod)) { lsGen gen; lsHandle handle; gen = lsStart(modinstlist->mps); if (lsNext(gen, (lsGeneric*)&modinst, &handle) == LS_OK) { vl_write_mod_inst(file, mod, modinst); while (lsNext(gen, (lsGeneric*)&modinst, &handle) != LS_NOMORE) { vl_write_mod_inst(file, mod, modinst); } } lsFinish(gen); } else { char msg[MAXSTRLEN]; sprintf(msg, "module %s used without definition", modinstlist->name->name); Translate_Warning(msg); } } static void vl_write_prim_inst_list(FILE *file, vl_mod_prim_inst_list *priminstlist) { vl_primitive *prim; vl_mod_prim_inst *priminst; if (st_lookup(mod_list->mp_st, priminstlist->name->name, (char**)&prim)) { lsGen gen; lsHandle handle; gen = lsStart(priminstlist->mps); if (lsNext(gen, (lsGeneric*)&priminst, &handle) == LS_OK) { vl_write_prim_inst(file, prim, priminst); while (lsNext(gen, (lsGeneric*)&priminst, &handle) != LS_NOMORE) { vl_write_prim_inst(file, prim, priminst); } } lsFinish(gen); } else { char msg[MAXSTRLEN]; sprintf(msg, "primitive %s is used without definition", priminstlist->name->name); Translate_Warning(msg); } } static void vl_write_gate_inst_list(FILE *file, vl_gate_inst_list *gate_list) { vl_gate_inst *gate; lsGen gen; lsHandle handle; gen = lsStart(gate_list->gates); if (lsNext(gen, (lsGeneric*)&gate, &handle) == LS_OK) { vl_write_gate_inst(file, gate_list->type, gate); while(lsNext(gen, (lsGeneric*)&gate, &handle) != LS_NOMORE) { vl_write_gate_inst(file, gate_list->type, gate); } } (void) lsFinish(gen); } static void vl_write_tesla_timer_inst_list(FILE *file, vl_gate_inst_list *gate_list) { vl_gate_inst *gate; lsGen gen; lsHandle handle; int lb=0, ub=0; if (!gate_list->delays) { char buf[MAXSTRLEN]; sprintf(buf, "%s:teslaTimer needs #(LB:UB) delay specified", vl_currentModule->name->name); Translate_Warning(buf); } if (gate_list->delays->delay1->type == IntExpr) { char buf[MAXSTRLEN]; sprintf(buf, "%s:teslaTimer needs #(LB:UB) delay specified", vl_currentModule->name->name); Translate_Warning(buf); } lb = vl_eval_expr(gate_list->delays->delay1->u.exprs.e1); ub = vl_eval_expr(gate_list->delays->delay1->u.exprs.e2); for (gen=lsStart(gate_list->gates); lsNext(gen, (lsGeneric*)&gate, &handle)!=LS_NOMORE; ) { vl_write_tesla_timer_inst(file, gate, lb, ub); } (void) lsFinish(gen); } void vl_write_mod_inst(FILE *file, vl_module *master, vl_mod_prim_inst *inst) { int lo, hi; int constConnection; lsHandle inst_handle, mast_handle; lsGen inst_gen, mast_gen; vl_port_connect *inst_item; vl_port *mast_item; vl_expr *old_item_expr; lsList input_consts; const_term *ct; vl_enumerator *enum_elt; int ith_port; st_generator *stgen; char *key; int dummy; lsList back_patch_list; lsGen backgen; lsHandle backhandle; vl_expr *backexpr; char modbuf[MAXSTRLEN*8]; char workbuf[MAXSTRLEN]; if (inst->name) sprintf(modbuf, ".subckt %s %s ", master->name->name, inst->name->name); else sprintf(modbuf, ".subckt %s %s ", master->name->name, new_termname()); if (master->flags & WithInitial) { if (use_rst_ckt) { sprintf(workbuf, "%s=%s ", Initial_Signal->name->name, Initial_Signal->name->name); strcat(modbuf, workbuf); } } if (inst->ports && master->ports) { lsHandle handle; lsGen gen; vl_id_range *id, *cur_sig; int named_connection; input_consts = lsCreate(); back_patch_list = lsCreate(); auxSigST = st_init_table(strcmp, st_strhash); ith_port=0; named_connection = 0; inst_gen = lsStart(inst->ports); mast_gen = lsStart(master->ports); while (lsNext(mast_gen, (lsGeneric*)&mast_item, &mast_handle) != LS_NOMORE) { if (lsNext(inst_gen, (lsGeneric*)&inst_item, &inst_handle) != LS_NOMORE) { if (!mast_item->port_exp && !inst_item->expr) continue; else if ((!mast_item->port_exp && inst_item->expr) || (!inst_item->expr && mast_item->port_exp)) { char buf[MAXSTRLEN]; sprintf(buf, "'%s': try to instantiate module %s with incompatible arguments", vl_currentModule->name->name, master->name->name); yylineno = -1; compile_error(buf); } } else if (!named_connection) break; lsFirstItem(mast_item->port_exp, (lsGeneric*)&id, &handle); if (!st_lookup(master->sig_st, id->name, (char**)&id)) { char buf[MAXSTRLEN]; sprintf(buf, "port '%s' is not defined in module '%s'", id->name, master->name->name); semantic_error(buf); } old_item_expr = NIL(vl_expr); if (!named_connection) named_connection = (inst_item->type == NamedConnect); if (named_connection) { mast_item = search_match_port(inst_item->id->name, master->ports); lsFirstItem(mast_item->port_exp, (lsGeneric*)&id, &handle); if (!st_lookup(master->sig_st, id->name, (char**)&id)) { char buf[MAXSTRLEN]; sprintf(buf, "port '%s' is not defined in module '%s'", id->name, master->name->name); semantic_error(buf); } } if ((id->flags&OutPort) && Zconnection) { lsList assign_list; vl_id_range *tmp_id; vl_lval *tmp_lhs; vl_expr *tmp_rhs; vl_cont_assign *assign_stmt; tmp_id = vl_create_id_range(vlStrdup(new_termname()), NIL(vl_range)); if (inst_item->expr->type == ConcatExpr) tmp_lhs = vl_create_lval(ConcatExpr, NIL(vl_id_range),NIL(vl_range), (lsList)inst_item->expr->u.name); else tmp_lhs = vl_create_lval(inst_item->expr->type, inst_item->expr->u.idrng, inst_item->expr->u.idrng->range, (lsList)0); tmp_rhs = vl_create_expr(IDExpr, 0, (double)0.0, tmp_id, NIL(void), NIL(void)); assign_list = lsCreate(); lsNewEnd(assign_list, (lsGeneric)vl_create_bassign_stmt(AssignStmt, tmp_lhs, NIL(void), tmp_rhs), 0); assign_stmt = vl_create_cont_assign_stmt(0, NIL(vl_delay), assign_list); if (inst_item->expr->type == IDExpr || inst_item->expr->type == BitSelExpr || inst_item->expr->type == PartSelExpr) { int inVar=0; if (st_lookup(vl_currentModule->sig_st, inst_item->expr->u.name->name, (char**)&cur_sig)) inVar = ((cur_sig->flags & InPort) && !(cur_sig->flags & OutPort)); if (!inVar) lsInAfter(curModGen, (lsGeneric)assign_stmt, PcurModHandle); } chkUndefPorts(inst_item->expr, auxSigST); old_item_expr = inst_item->expr; inst_item->expr = vl_create_expr(IDExpr, 0, (double)0.0, tmp_id, NIL(void), NIL(void)); } if ((id->flags&OutPort) && (inst_item->expr->type==ConcatExpr)) { int m_lo, m_hi; get_hilo(id, &m_hi, &m_lo); write_out_port(file, id, m_hi,m_lo, inst_item->expr, auxSigST); write_var_decl(file, inst_item->expr->term); lsNewEnd(back_patch_list, (lsGeneric)inst_item->expr, 0); } else { masterIdDfn = id; if (old_item_expr) if (old_item_expr->type == ConcatExpr) vl_write_expr(file, old_item_expr, NIL(st_table)); vl_write_expr(file, inst_item->expr, NIL(st_table)); masterIdDfn = NIL(vl_id_range); } constConnection = 0; if (!inst_item->expr) { constConnection = 1; } else if (!inst_item->expr->term) { constConnection = 1; } else { if (id->id_type) { if (inst_item->expr->type == IDExpr && st_lookup(id->id_type->specifier-> u.enum_type->domain_st, inst_item->expr->u.name->name, (char**)&enum_elt)) constConnection = 1; } } if (constConnection) { int hi, lo; vl_term *term_out; char conn[MAXSTRLEN]; get_hilo(id, &hi, &lo); term_out = typed_new_term(id->id_type,NIL(vl_range),lo,hi); term_out->flag |= id->flags; lsNewEnd(input_consts, (lsGeneric)create_const_term(inst_item->expr,term_out),0); put_const_port_connect(NIL(FILE), conn, id, inst_item, input_consts, term_out); strcat(modbuf, conn); continue; } if (inst_item->expr->type == IDExpr || inst_item->expr->type == BitSelExpr || inst_item->expr->type == PartSelExpr) { int retval = st_lookup(vl_currentModule->sig_st, inst_item->expr->u.name->name, (char**)&cur_sig); assert(retval); } if (implicitClocking && !vlTimedSystem && !implicitClockWire) { if (master->clk) if (!strcmp(master->clk->expr->u.name->name, id->name)) continue; if (!strcmp(id->name,CLOCK)) continue; } { char conn[MAXSTRLEN]; if (id->flags & MVar) { put_mvar_port_connect(NIL(FILE), conn, id, inst_item); } else { get_hilo(id, &hi, &lo); if (lo > hi) { put_bin_scalar_port_connect(NIL(FILE), conn, id, inst_item); } else { put_bin_vector_port_connect(NIL(FILE), conn, id, inst_item); } } strcat(modbuf, conn); strcat(modbuf, " "); } ith_port++; } lsFinish(inst_gen); lsFinish(mast_gen); backgen = lsStart(back_patch_list); while (lsNext(backgen,(lsGeneric*)&backexpr,&backhandle)!=LS_NOMORE) { vl_write_outport_connect(file, backexpr); } lsFinish(backgen); gen = lsStart(input_consts); while(lsNext(gen, (lsGeneric*)&ct, &handle) != LS_NOMORE) { if (!isOutPort(ct->term->flag)) write_var_decl(file, ct->term); vl_write_const(file, ct->const_expr, ct->term); } lsFinish(gen); stgen = st_init_gen(auxSigST); while (st_gen(stgen, &key, (char**)&dummy)) { if (!dummy) fprintf(file, "%s %s %s %s;\n", SMV_VAR, key, SMV_COLON, SMV_BOOLEAN); else { int mhi, mlo; get_hilo((vl_id_range*)dummy, &mhi, &mlo); if (mhi < mlo) fprintf(file, "%s %s %s %s;\n", SMV_VAR, key, SMV_COLON, SMV_BOOLEAN); else fprintf(file, "%s %s %s %s %d%s%d %s %s;\n", SMV_VAR, key, SMV_COLON, SMV_ARRAY, mhi, SMV_RANGE, mlo, SMV_OF, SMV_BOOLEAN); } } st_free_gen(stgen); auxSigST = NIL(st_table); fprintf(file, "%s\n", modbuf); lsDestroy(input_consts, 0); } } static void vl_write_prim_inst(FILE *file, vl_primitive *master, vl_mod_prim_inst *inst) { vl_write_mod_inst(file, (vl_module*)master, inst); } static void vl_write_gate_inst(FILE *file, short type, vl_gate_inst *gate) { lsGen inst_gen; lsHandle inst_handle; vl_expr *inst_expr; vl_term *conn_term; vl_expr *old_item_expr = NIL(vl_expr); int constConnection; int ith_port; char buf[MAXSTRLEN]; char outbuf[MAXSTRLEN]; char *cp; cp = outbuf; *cp = '\0'; cp = strappendS(cp, ".subckt"); cp = strappend(cp, "__sis_"); cp = strappend(cp, GATE_NAME(type)); if (lsLength(gate->terms)>3) sprintf(buf,"%d",lsLength(gate->terms)-1); else buf[0]='\0'; cp = strappendS(cp, buf); if (gate->name) cp = strappendS(cp, gate->name->name); else cp = strappendS(cp, new_termname()); inst_gen = lsStart(gate->terms); ith_port = 1; while (lsNext(inst_gen, (lsGeneric*)&inst_expr, &inst_handle) != LS_NOMORE) { if ((ith_port==1 || type == TranGate) && Zconnection) { lsList assign_list; vl_id_range *tmp_id; vl_term *tmp_term; vl_lval *tmp_lhs; vl_expr *tmp_rhs; vl_cont_assign *assign_stmt; char *dummy; int no_resolve; no_resolve = 0; tmp_id = vl_create_id_range(vlStrdup(new_termname()), NIL(vl_range)); tmp_term = vl_create_term(tmp_id, 0, -1); write_var_decl(file, tmp_term); if (inst_expr->type == ConcatExpr) tmp_lhs = vl_create_lval(ConcatExpr, NIL(vl_id_range),NIL(vl_range), (lsList)inst_expr->u.name); else { if (implicitDeclare && inst_expr->type == IDExpr) { if (!st_lookup(vl_currentModule->sig_st, inst_expr->u.idrng->name, &dummy)) { st_insert(vl_currentModule->sig_st, inst_expr->u.idrng->name, (char*)vl_create_id_range(inst_expr->u.idrng->name, NIL(vl_range))); } else { no_resolve = !((((vl_id_range*)dummy)->flags & InPort) && (((vl_id_range*)dummy)->flags & OutPort)) && type == TranGate; } } tmp_lhs = vl_create_lval(inst_expr->type, inst_expr->u.idrng, inst_expr->u.idrng->range, (lsList)0); } if (!no_resolve) { tmp_rhs = vl_create_expr(IDExpr, 0, (double)0.0, tmp_id, NIL(void), NIL(void)); assign_list = lsCreate(); lsNewEnd(assign_list, (lsGeneric)vl_create_bassign_stmt(AssignStmt, tmp_lhs, NIL(void), tmp_rhs), 0); assign_stmt = vl_create_cont_assign_stmt(0, NIL(vl_delay), assign_list); lsInAfter(curModGen, (lsGeneric)assign_stmt, PcurModHandle); } old_item_expr = inst_expr; inst_expr = vl_create_expr(IDExpr, 0, (double)0.0, tmp_id, NIL(void), NIL(void)); } vl_write_expr(file, inst_expr, NIL(st_table)); constConnection = 0; if (!inst_expr) { constConnection = 1; } else if (!inst_expr->term) { constConnection = 1; } if (constConnection) { conn_term = new_term(NIL(vl_range),0,-1); vl_write_const(file, inst_expr, conn_term); } else { conn_term = inst_expr->term; } if (inst_expr->term->lo > inst_expr->term->hi) { sprintf(buf, "%c=%s", (ith_port==1)?'o':'a'+ith_port-2, conn_term->name->name); } else { sprintf(buf, "%c=%s%s%d%s", (ith_port==1)?'o':'a'+ith_port-2, conn_term->name->name, SEP_LBITSELECT, inst_expr->term->lo, SEP_RBITSELECT); } cp = strappendS(cp, buf); ith_port++; } lsFinish(inst_gen); fprintf(file, "%s\n", outbuf); } static void vl_write_tesla_timer_inst(FILE *file, vl_gate_inst *gate, int lb, int ub) { static int teslaTimerCounter = 0; char ps[MAXSTRLEN], ns[MAXSTRLEN]; char timer[MAXSTRLEN]; vl_term *(w[5]); int constConnection; int i; lsGen inst_gen; lsHandle inst_handle; vl_expr *inst_expr; if (lsLength(gate->terms) != 5) { char buf[MAXSTRLEN]; sprintf(buf, "%s:teslaTimer needs exactly 3 inputs + 2 outputs\n", vl_currentModule->name->name); Translate_Warning(buf); } for (inst_gen=lsStart(gate->terms), i=0; lsNext(inst_gen, (lsGeneric*)&inst_expr, &inst_handle) != LS_NOMORE; i++) { vl_write_expr(file, inst_expr, NIL(st_table)); constConnection = 0; if (!inst_expr) { constConnection = 1; } else if (!inst_expr->term) { constConnection = 1; } if (constConnection) { w[i] = new_term(NIL(vl_range),0,-1); vl_write_const(file, inst_expr, w[i]); } else w[i] = inst_expr->term; } lsFinish(inst_gen); sprintf(ps, "%s", new_termname()); sprintf(ns, "%s", new_termname()); sprintf(timer, "TESLATM%d", teslaTimerCounter++); fprintf(file, ".mv %s, %s 4 s w t1 t2\n", ps, ns); fprintf(file, ".latch %s %s\n.r %s\ns\n", ns, ps, ps); fprintf(file, ".timers %s\n", timer); fprintf(file, ".names %s %s %s %s %s %s %s %s\n", ps, w[0]->name->name, w[1]->name->name, w[4]->name->name, HSIS_ARROW, w[2]->name->name, w[3]->name->name, ns); fprintf(file, "s 0 - - 0 0 s\n"); fprintf(file, "s - 1 - 0 0 s\n"); if (lb==0) fprintf(file, "s 1 0 1 1 0 s\n"); else fprintf(file, "s 1 0 1 0 1 t1\n"); fprintf(file, "s 1 0 0 0 0 w && %s=0\n", timer); fprintf(file, "w - 1 - 0 0 s\n"); fprintf(file, "w - 0 0 0 0 w && %s<=%d\n", timer, ub); fprintf(file, "w - 0 1 1 0 s && %s>=%d && %s<=%d\n", timer, lb, timer, ub); fprintf(file, "w - 0 1 0 1 t1 && %s<%d\n", timer, lb); fprintf(file, "w - 0 - 0 1 t2 && %s>%d\n", timer, ub); fprintf(file, "t1 - 0 - 0 1 t1\n"); fprintf(file, "t1 - 1 - 0 1 s\n"); fprintf(file, "t2 - 0 - 0 1 t2\n"); fprintf(file, "t2 - 1 - 0 1 s\n"); } void vl_write_reset(FILE *file, vl_procstmt *init_stmt) { st_table *reset_vars=NIL(st_table); st_generator *gen; char *key; var_info *id_var; vl_id_range *id_sym; reset_vars = st_init_table(strcmp, st_strhash); rst_ckt = 1; vl_write_reset_stmt(file, init_stmt->stmt, reset_vars); non_block_assignment(file, reset_vars); gen = st_init_gen(reset_vars); while (st_gen(gen, &key, (char**)&id_var)) { if (st_lookup(vl_currentModule->sig_st, key, (char**)&id_sym)) { lsNewEnd(id_sym->initial, (lsGeneric)id_var->current_terminal, 0); if (strstr(id_sym->name, SEP_LATCH)) { char buf[MAXSTRLEN]; strcpy(buf, id_sym->name); strip_char(buf, SEP_LATCH); if (st_lookup(vl_currentModule->sig_st, buf, (char**)&id_sym)) lsNewEnd(id_sym->initial, (lsGeneric)id_var->current_terminal, 0); } } } st_free_gen(gen); rst_ckt = 0; } st_table *vl_write_procstmt(FILE *file, vl_procstmt *procstmt, st_table *vars) { int old_lhs_must_be_wire; WrtTRACE("Writing always/initial statement"); vl_pauseStack = create_stack(); vl_current_pause_list = lsCreate(); vl_current_vars_list = lsCreate(); in_procedure = 1; if (procstmt->type == AlwaysStmt) { old_lhs_must_be_wire = lhs_must_be_wire; if (((vl_bassign_stmt*)procstmt->stmt)->type != EventControlStmt) { lhs_must_be_wire = 1; } vars = vl_write_stmt(file, procstmt->stmt,NO_MUX,NIL(vl_term),vars); if (vlTimedSystem) final_vars = vars; lhs_must_be_wire = old_lhs_must_be_wire; if (procstmt->flags & PseudoAlways) { vl_register_pause((vertex_t *) procstmt->fg_info, vars); } if (lsLength(vl_current_pause_list) > 1 && vlTimedSystem) { st_table *new_table; new_table = st_init_table(strcmp, st_strhash); vl_prioritize_sequence(file, vl_current_vars_list, vl_current_pause_list, new_table); vars = new_table; } } in_procedure = 0; destroy_stack(vl_pauseStack, 0); vl_pauseStack = (lsList)0; lsDestroy(vl_current_pause_list, 0); lsDestroy(vl_current_vars_list, 0); vl_current_pause_list = (lsList)0; vl_current_vars_list = (lsList)0; return vars; } st_table *vl_write_stmt(FILE *file, void *stmt, int muxed, vl_term *muxsel, st_table *vars) { vl_id_range *id_sym; vl_term *out_term; vl_term *new_out; vl_term *tmp_term; vl_term *sel; st_table *pre_cond=NIL(st_table); st_table *old_init_vars=NIL(st_table); int using_ith_ctrl; int fg_id; int cur_bit_pos; int num_lhs_vars; lsList lhs_list; lsGen lhs_gen=(lsGen)0; lsHandle lhs_handle; vl_expr *lhs_expr; vl_id_range *lhs_var; vl_range *lhs_range; int old_check_rhs_sen; int i; if (stmt == NIL(void)) { return vars; } WrtTRACE("Writing statement"); switch(((vl_bassign_stmt *)stmt)->type) { case BeginEndStmt: vars = vl_write_begin_end_stmt(file, stmt, muxed, muxsel, vars); break; case IfElseStmt: Being_Conditioned++; vars = vl_write_if_else_stmt(file, stmt, vars); Being_Conditioned--; break; case CaseStmt: case CasexStmt: case CasezStmt: Being_Conditioned++; vars = vl_write_case_stmt(file, stmt, vars); Being_Conditioned--; break; case CaseItem: break; case DefaultItem: break; case ForeverStmt: break; case RepeatStmt: break; case WhileStmt: { if (!rst_ckt) { st_table *fork_in_vars; vl_term *dom_sel; using_ith_ctrl = rst_ith_ctrl; rst_ith_ctrl++; vl_write_expr(file, ((vl_while_stmt*)stmt)->cond, vars); tmp_term = new_term(NIL(vl_range), 0, -1); if (!((vl_while_stmt*)stmt)->cond->term) { sel = new_term(NIL(vl_range), 0, -1); vl_write_const(file, ((vl_while_stmt*)stmt)->cond, sel); ((vl_while_stmt*)stmt)->cond->term = sel; } else if (((vl_while_stmt*)stmt)->cond->term->lo <= ((vl_while_stmt*)stmt)->cond->term->hi) { sel = new_term(NIL(vl_range), 0, -1); vl_write_vector_bop(file, UorExpr, ((vl_while_stmt*)stmt)->cond->term, NIL(vl_term), sel); } else { sel = ((vl_while_stmt*)stmt)->cond->term; } assert ((((vl_while_stmt*)stmt)->cond->fg_info1 && ((vl_while_stmt*)stmt)->cond->fg_info2) || (!((vl_while_stmt*)stmt)->cond->fg_info1 && !((vl_while_stmt*)stmt)->cond->fg_info2)); if (((vl_while_stmt*)stmt)->cond->fg_info1) { fg_loop_collect_pause(file, (vertex_t*)((vl_while_stmt*)stmt)->cond->fg_info1, (vertex_t*)((vl_while_stmt*)stmt)->cond->fg_info2, &dom_sel); } if (((vl_while_stmt*)stmt)->cond->fg_info1) fg_update_node_info((vertex_t*) (((vl_while_stmt*)stmt)->cond->fg_info1), (char*)sel); vl_write_bin_connect(file, sel, tmp_term, 0); lsNewEnd(rst_ctrl_list, (lsGeneric)tmp_term, 0); rst_ctrl_syndrome[using_ith_ctrl] = '1'; old_init_vars = vl_current_init_vars; vl_current_init_vars = st_init_table(strcmp, st_strhash); fork_in_vars = st_copy(vars); vl_predefine_vars(file, vars); vars = vl_write_stmt(file, ((vl_while_stmt*)stmt)->stmt, muxed,muxsel,vars); rst_ctrl_syndrome[using_ith_ctrl] = '-'; vl_timed_init_mux(file, dom_sel, vars, vl_current_init_vars, fork_in_vars); vl_current_init_vars = old_init_vars; } break; } case ForStmt: { if (!rst_ckt) { st_table *fork_in_vars; vl_term *dom_sel; vl_write_stmt(file, ((vl_for_stmt*)stmt)->init,muxed,muxsel,vars); old_init_vars = vl_current_init_vars; vl_current_init_vars = st_init_table(strcmp, st_strhash); fork_in_vars = st_copy(vars); vl_predefine_vars(file, vars); using_ith_ctrl = rst_ith_ctrl; rst_ith_ctrl++; vl_write_expr(file, ((vl_for_stmt*)stmt)->cond, vars); tmp_term = new_term(NIL(vl_range), 0, -1); if (!((vl_for_stmt*)stmt)->cond->term) { sel = new_term(NIL(vl_range), 0, -1); vl_write_const(file, ((vl_for_stmt*)stmt)->cond, sel); ((vl_for_stmt*)stmt)->cond->term = sel; } else if (((vl_for_stmt*)stmt)->cond->term->lo <= ((vl_for_stmt*)stmt)->cond->term->hi) { sel = new_term(NIL(vl_range), 0, -1); vl_write_vector_bop(file, UorExpr, ((vl_for_stmt*)stmt)->cond->term, NIL(vl_term), sel); } else { sel = ((vl_for_stmt*)stmt)->cond->term; } assert ((((vl_for_stmt*)stmt)->cond->fg_info1 && ((vl_for_stmt*)stmt)->cond->fg_info2) || (!((vl_for_stmt*)stmt)->cond->fg_info1 && !((vl_for_stmt*)stmt)->cond->fg_info2)); if (((vl_for_stmt*)stmt)->cond->fg_info1) { fg_loop_collect_pause(file, (vertex_t*)((vl_for_stmt*)stmt)->cond->fg_info1, (vertex_t*)((vl_for_stmt*)stmt)->cond->fg_info2, &dom_sel); } if (((vl_for_stmt*)stmt)->cond->fg_info1) fg_update_node_info((vertex_t*) (((vl_for_stmt*)stmt)->cond->fg_info1), (char*)sel); vl_write_bin_connect(file, sel, tmp_term, 0); lsNewEnd(rst_ctrl_list, (lsGeneric)tmp_term, 0); rst_ctrl_syndrome[using_ith_ctrl] = '1'; vars = vl_write_stmt(file, ((vl_for_stmt*)stmt)->stmt,muxed,muxsel,vars); vars = vl_write_stmt(file, ((vl_for_stmt*)stmt)->end,muxed,muxsel,vars); rst_ctrl_syndrome[using_ith_ctrl] = '-'; vl_timed_init_mux(file, dom_sel, vars, vl_current_init_vars, fork_in_vars); vl_current_init_vars = old_init_vars; } break; } case DelayControlStmt: { vl_register_pause((vertex_t *)((vl_delay_control_stmt*)stmt)->fg_info, vars); vars = st_init_table(strcmp, st_strhash); vl_write_stmt(file, ((vl_delay_control_stmt*)stmt)->stmt, muxed, muxsel, vars); break; } case EventControlStmt: { vl_register_pause((vertex_t *)((vl_event_control_stmt*)stmt)->fg_info, vars); vars = st_init_table(strcmp, st_strhash); vars = vl_write_stmt(file, ((vl_event_control_stmt*)stmt)->stmt, muxed, muxsel, vars); break; } case DelayBassignStmt: case DelayNbassignStmt: { char buf[MAXSTRLEN]; yylineno = ((vl_bassign_stmt*)stmt)->lineno; sprintf(buf, "'%s' contains delay, do not know how to synthesize it", vl_currentModule->name->name); Translate_Warning(buf); break; } case AssignStmt: case BassignStmt: case NbassignStmt: case EventBassignStmt: case EventNbassignStmt: { yylineno = ((vl_bassign_stmt*)stmt)->lineno; if (((vl_bassign_stmt*)stmt)->lhs->type == ConcatExpr) { num_lhs_vars = lsLength(((vl_bassign_stmt*)stmt)->lhs->concat); lhs_list = ((vl_bassign_stmt*)stmt)->lhs->concat; lhs_gen = lsStart(lhs_list); } else { num_lhs_vars = 1; lhs_list = (lsList)0; } for (i=0; iu.name; lhs_range = lhs_var->range; } else { lhs_var = ((vl_bassign_stmt*)stmt)->lhs->name; lhs_range = ((vl_bassign_stmt*)stmt)->lhs->range; } if (!st_lookup(vl_currentModule->sig_st, lhs_var->name, (char**)&id_sym)) { char buf[MAXSTRLEN]; sprintf(buf, "variable %s not declared while used as lhs", lhs_var->name); compile_error(buf); id_sym = lhs_var; st_insert(vl_currentModule->sig_st, id_sym->name, (char*)id_sym); } if (lhs_range) if (((vl_bassign_stmt *)stmt)->type == NbassignStmt || ((vl_bassign_stmt *)stmt)->type == EventNbassignStmt) { char buf[MAXSTRLEN]; sprintf(buf, "'%s':non-blocking to partial vector, array element", id_sym->name); compile_error(buf); } if (id_sym->flags & InPort) { char buf[MAXSTRLEN]; sprintf(buf, "trying to assign to input variable %s", id_sym->name); yylineno = ((vl_bassign_stmt*)stmt)->lineno; compile_error(buf); } id_sym->edge_trigger = edge_triggering; if (recordCombAlways && !edge_triggering) { vl_id_range *temp_id_sym; if (!st_lookup(vl_currentModule->combVar_st, id_sym->name, (char**)&temp_id_sym)) { st_insert(vl_currentModule->combVar_st, id_sym->name, (char*)id_sym); } } else { id_sym->sensitiveList = sensitiveList; } } if (lhs_list) lsFinish(lhs_gen); old_check_rhs_sen = check_rhs_sensitivity; check_rhs_sensitivity = !(((vl_bassign_stmt*)stmt)->type == AssignStmt && vars); out_term = vl_write_assign(file,(vl_bassign_stmt*)stmt, muxed,muxsel,vars); check_rhs_sensitivity = old_check_rhs_sen; if (lhs_list) { lhs_gen = lsStart(((vl_bassign_stmt*)stmt)->lhs->concat); assert(array_n(assign_array) == num_lhs_vars); } for (i=0, cur_bit_pos=0; iu.name; retval = st_lookup(vl_currentModule->sig_st, lhs_expr->u.name->name, (char**)&id_sym); assert(retval); } if (((vl_bassign_stmt*)stmt)->type == NbassignStmt || ((vl_bassign_stmt*)stmt)->type == DelayNbassignStmt || ((vl_bassign_stmt*)stmt)->type == EventNbassignStmt) { char buf[MAXSTRLEN]; sprintf(buf, "%s%s", id_sym->name, SEP_LATCH); st_lookup(vl_currentModule->sig_st, buf, (char**)&id_sym); } else if (((vl_bassign_stmt*)stmt)->type == AssignStmt && vars) { char buf[MAXSTRLEN]; sprintf(buf, "%s%s", id_sym->name, SEP_QUASI); st_lookup(vl_currentModule->sig_st, buf, (char**)&id_sym); } if (!out_term) break; if (lhs_list) out_term = array_fetch(vl_term*, assign_array, i); new_out = vl_copy_term(out_term); if (lhs_list) { int hi, lo; get_hilo(id_sym, &hi, &lo); if (hi < lo) hi=lo=0; new_out->lo = cur_bit_pos; new_out->hi = new_out->lo + (hi-lo+1) -1; cur_bit_pos = new_out->hi + 1; } pre_cond = fg_assign_temporal_context((vertex_t*) (((vl_bassign_stmt*)stmt)->fg_info)); fg_id = fg_fg_id(); if (cntxt_event) record_pseudo_cntxt(file, fg_id, pre_cond, ctrl_syndrome, rst_ctrl_syndrome, vars); if (!rst_ckt) { syndrome_expr *newCtrlExpr; if (((vl_bassign_stmt *)stmt)->type == NbassignStmt || ((vl_bassign_stmt *)stmt)->type == DelayNbassignStmt || ((vl_bassign_stmt *)stmt)->type == EventNbassignStmt) { } newCtrlExpr = create_syndrome_expr(vlStrdup(ctrl_syndrome), new_out, pre_cond, fg_id); lsNewEnd(id_sym->syndrome_expr_list, (lsGeneric)newCtrlExpr, 0); st_insert(vars, id_sym->name, (char*)create_var_info(vl_copy_id_range(id_sym), out_term)); } else { syndrome_expr *newCtrlExpr; if (((vl_bassign_stmt *)stmt)->type == NbassignStmt || ((vl_bassign_stmt *)stmt)->type == DelayNbassignStmt || ((vl_bassign_stmt *)stmt)->type == EventNbassignStmt) { } newCtrlExpr = create_syndrome_expr(vlStrdup(rst_ctrl_syndrome), new_out, pre_cond, fg_id); lsNewEnd(id_sym->rst_syndrome_expr_list, (lsGeneric)newCtrlExpr, 0); st_insert(vars, id_sym->name, (char*)create_var_info(vl_copy_id_range(id_sym), out_term)); } } break; } case WaitStmt: { if (((vl_wait_stmt*)stmt)->cond == NIL(vl_expr)) { vl_write_begin_end_stmt(file, ((vl_wait_stmt*)stmt)->stmt, muxed, muxsel, vars); } break; } case ForkJoinStmt: break; case TaskEnableStmt: case SysTaskEnableStmt: break; case DisableStmt: break; case DeassignStmt: { syndrome_expr *newCtrlExpr; vl_term *operand_term; char quasi[MAXSTRLEN]; if (!st_lookup(vl_currentModule->sig_st, ((vl_deassign_stmt*)stmt)->lhs->name->name, (char**)&id_sym)) { char buf[MAXSTRLEN]; sprintf(buf, "%s:deassign '%s', which is undefined variable", vl_currentModule->name->name, ((vl_deassign_stmt*)stmt)->lhs->name->name); yylineno = -1; compile_error(buf); } sprintf(quasi, "%s%s", id_sym->name, SEP_QUASI); if (!st_lookup(vl_currentModule->sig_st, quasi, (char**)&id_sym)) { int retval; collect_quasi(quasi); retval = st_lookup(vl_currentModule->sig_st,quasi,(char**)&id_sym); assert(retval); } operand_term = vl_create_term(((vl_deassign_stmt*)stmt)->lhs->name, 0,-1); fg_id = fg_fg_id(); pre_cond = fg_assign_temporal_context((vertex_t*) (((vl_deassign_stmt*)stmt)->fg_info)); newCtrlExpr = create_syndrome_expr(vlStrdup(ctrl_syndrome), operand_term, pre_cond, fg_id); lsNewEnd((!rst_ckt)?id_sym->syndrome_expr_list: id_sym->rst_syndrome_expr_list, (lsGeneric)newCtrlExpr, 0); break; } case SendEventStmt: { char vnt_buf[MAXSTRLEN]; if (!st_lookup(vl_currentModule->sig_st, ((vl_send_event_stmt*)stmt)->name->name, (char**)&id_sym)) { char buf[MAXSTRLEN]; sprintf(buf, "variable %s not declared while used as event", ((vl_send_event_stmt*)stmt)->name->name); yylineno = -1; compile_error(buf); } out_term = new_term(NIL(vl_range), 0, -1); sprintf(vnt_buf, "%s%s%s", id_sym->name, SEP_GATEPIN, PIN_EVENT); if (smartEvent) write_int_connect(file, 1, out_term); else vl_write_bit_connect(file, vnt_buf, out_term->name->name, 1); new_out = vl_copy_term(out_term); pre_cond = fg_assign_temporal_context((vertex_t*) (((vl_send_event_stmt*)stmt)->fg_info)); fg_id = fg_fg_id(); lsNewEnd(id_sym->syndrome_expr_list, (lsGeneric)create_syndrome_expr(vlStrdup(ctrl_syndrome), new_out, pre_cond, fg_id), 0); st_insert(vars, id_sym->name, (char*)create_var_info(vl_copy_id_range(id_sym), out_term)); break; } default: { char msg[MAXSTRLEN]; sprintf(msg, "vl_write_stmt:Unexpected Statement Type %d", ((vl_bassign_stmt *)stmt)->type); internal_error(msg); } } return vars; } void vl_write_reset_stmt(FILE *file, void *stmt, st_table *vars) { if (stmt == NIL(void)) return; WrtTRACE("Writing reset statement"); vl_write_stmt(file, stmt, NO_MUX, NIL(vl_term), vars); } st_table *vl_write_begin_end_stmt(FILE *file, vl_begin_end_stmt *bestmt, int muxed, vl_term *control, st_table *vars) { WrtTRACE("Writing begin/end\n"); vl_write_decl_list(file, bestmt->decls, muxed, control, vars); vars = vl_write_stmt_list(file, bestmt->stmts, muxed, control, vars); return vars; } st_table *vl_write_if_else_stmt(FILE *file, vl_if_else_stmt *stmt, st_table *vars) { st_table *t_vars, *f_vars; st_generator *gen; char *key; var_info *t_in, *f_in, *cur_var; int using_ith_ctrl; vl_term *sel, *tmp_term; WrtTRACE("Writing if/then/else statement"); if (!rst_ckt) { using_ith_ctrl = ith_ctrl; ith_ctrl++; } else { using_ith_ctrl = rst_ith_ctrl; rst_ith_ctrl++; } if (!stmt->else_stmt) { if (sensitiveList && vl_currentModule->combVar_st) { if (chk_IncompleteBranch) { char buf[MAXSTRLEN]; recordCombAlways = 0; vl_currentModule->combVar_st = NIL(set_t); vl_step_stmt(stderr, stmt); sprintf(buf, "%s:incomplete if/ese, combinational reduction failed", vl_currentModule->name->name); yylineno = -1; compile_error(buf); } } } vl_write_expr(file, stmt->cond, vars); tmp_term = new_term(NIL(vl_range), 0, -1); if (!stmt->cond->term) { sel = new_term(NIL(vl_range), 0, -1); vl_write_const(file, stmt->cond, sel); stmt->cond->term = sel; } else if (stmt->cond->term->lo <= stmt->cond->term->hi) { sel = new_term(NIL(vl_range), 0, -1); vl_write_vector_bop(file, UorExpr, stmt->cond->term, NIL(vl_term), sel); } else { sel = stmt->cond->term; } assert ((stmt->cond->fg_info1 && stmt->cond->fg_info2) || (!stmt->cond->fg_info1 && !stmt->cond->fg_info2)); if (stmt->cond->fg_info1) fg_update_node_info((vertex_t*)(stmt->cond->fg_info1), (char*)sel); if (stmt->cond->fg_info1) { fg_if_collect_pause_rewrite_ctrl(file, (vertex_t*)stmt->cond->fg_info1, (vertex_t*)stmt->cond->fg_info2, &sel); stmt->cond->term = sel; } vl_write_bin_connect(file, sel, tmp_term, 0); if (!rst_ckt) lsNewEnd(ctrl_list, (lsGeneric)tmp_term, 0); else lsNewEnd(rst_ctrl_list, (lsGeneric)tmp_term, 0); t_vars = st_copy(vars); f_vars = st_copy(vars); dup_info_var_in_st(t_vars); dup_info_var_in_st(f_vars); reset_cond_list_in_st(t_vars); reset_cond_list_in_st(f_vars); if (!rst_ckt) ctrl_syndrome[using_ith_ctrl] = '1'; else rst_ctrl_syndrome[using_ith_ctrl] = '1'; t_vars = vl_write_stmt(file,stmt->if_stmt,MUX_T, stmt->cond->term,t_vars); if (!rst_ckt) ctrl_syndrome[using_ith_ctrl] = '0'; else rst_ctrl_syndrome[using_ith_ctrl] = '0'; f_vars = vl_write_stmt(file,stmt->else_stmt,MUX_F,stmt->cond->term,f_vars); if (!rst_ckt) ctrl_syndrome[using_ith_ctrl] = '-'; else rst_ctrl_syndrome[using_ith_ctrl] = '-'; fprintf(file, "%s if/else (", HSIS_COMMENT); (void)vl_step_expr(file, stmt->cond); fprintf(file, ")\n"); vars = create_var_muxes(file, stmt->cond->term, t_vars, f_vars, vars); gen = st_init_gen(t_vars); while (st_gen(gen, &key, (char**)&t_in)) { st_delete(t_vars, &key, (char**)&t_in); if (st_lookup(vars, key, (char**)&cur_var)) if (cur_var == t_in) continue; free_var_info(t_in); } st_free_gen(gen); gen = st_init_gen(f_vars); while (st_gen(gen, &key, (char**)&f_in)) { st_delete(t_vars, &key, (char**)&f_in); if (st_lookup(vars, key, (char**)&cur_var)) if (cur_var == f_in) continue; free_var_info(f_in); } st_free_gen(gen); return vars; } st_table *vl_write_case_stmt(FILE *file, vl_case_stmt *stmt, st_table *vars) { st_table **case_vars; int i; vl_case_item *item; lsHandle handle; lsGen gen; vl_term **controls, *prev_ctrl = NIL(vl_term); vl_term *pause_ripple=NIL(vl_term); int using_ith_ctrl = -1; char old_ctrl_syndrome[MAXSTRLEN]; WrtTRACE("Writing case\n"); if (!rst_ckt) strcpy(old_ctrl_syndrome, ctrl_syndrome); else strcpy(old_ctrl_syndrome, rst_ctrl_syndrome); assert((stmt->cond->fg_info1 && stmt->cond->fg_info2) || (!stmt->cond->fg_info1 && !stmt->cond->fg_info2)); switch (stmt->type) { case CaseStmt: case CasexStmt: case CasezStmt: break; default: internal_error("Unexpected Case Type"); break; } { vl_write_expr(file, stmt->cond, vars); case_vars = (st_table**)chk_malloc(lsLength(stmt->case_items) * sizeof(st_table*)); controls = (vl_term**)chk_malloc(lsLength(stmt->case_items) * sizeof(vl_term*)); for (i=0; icase_items); i++) { case_vars[i] = NIL(st_table); controls[i] = NIL(vl_term); } for (gen = lsStart(stmt->case_items), i = 0; (lsNext(gen,(lsGeneric*)&item,&handle) != LS_NOMORE); i++) { controls[i] = write_case_comparator(file, stmt->cond->term, item->exprs, vars); if (item->fg_info) { vertex_t *src_tag; src_tag = g_e_dest((edge_t*)item->fg_info); if (!controls[i]) { controls[i] = true_term(file); } fg_update_node_info((vertex_t*)(item->fg_info), (char*)controls[i]); fg_case_collect_pause_rewrite_ctrl(file, src_tag, (vertex_t*)stmt->cond->fg_info2, &controls[i], &pause_ripple); } if (item->type == CaseItem) { if (!rst_ckt) { lsNewEnd(ctrl_list, (lsGeneric)controls[i], 0); using_ith_ctrl = ith_ctrl; ith_ctrl++; ctrl_syndrome[using_ith_ctrl] = '1'; } else { lsNewEnd(rst_ctrl_list, (lsGeneric)controls[i], 0); using_ith_ctrl = rst_ith_ctrl; rst_ith_ctrl++; rst_ctrl_syndrome[using_ith_ctrl] = '1'; } } case_vars[i] = st_copy(vars); dup_info_var_in_st(case_vars[i]); reset_cond_list_in_st(case_vars[i]); case_vars[i] = vl_write_stmt(file, item->stmt, (controls[i])?MUX_T:NO_MUX, (controls[i])?controls[i]:NIL(vl_term), case_vars[i]); if (item->type == CaseItem) { if (!rst_ckt) ctrl_syndrome[using_ith_ctrl] = '0'; else rst_ctrl_syndrome[using_ith_ctrl] = '0'; } prev_ctrl = controls[i]; } (void)lsFinish(gen); if (pause_ripple) { fprintf(file, ".names %s\n0\n", pause_ripple->name->name); } } if (!rst_ckt) strcpy(ctrl_syndrome, old_ctrl_syndrome); else strcpy(rst_ctrl_syndrome, old_ctrl_syndrome); fprintf(file, "%s case (", HSIS_COMMENT); vl_step_expr(file, stmt->cond); fprintf(file, ")\n"); if (!prev_ctrl || vl_currentFunction) { st_table *vars_tmp, *vars_else; i=lsLength(stmt->case_items)-1; vars_else = case_vars[i]; for (i -= 2; i>=0; i--) { vars_tmp = st_copy(vars); dup_info_var_in_st(vars_tmp); reset_cond_list_in_st(vars_tmp); create_var_muxes(file, controls[i+1], case_vars[i+1], vars_else, vars_tmp); vars_else = vars_tmp; } create_var_muxes(file, controls[0], case_vars[0], vars_else, vars); } else { for (i=lsLength(stmt->case_items)-1; i>=0; i--) { case_vars[i] = create_var_muxes(file, controls[i], case_vars[i], st_copy(vars), vars); } } return vars; } void vl_write_cont_assign(FILE *file, vl_cont_assign *assign, st_table *vars) { vl_id_range *lhs_id; lsGen gen; lsHandle handle; vl_bassign_stmt *a; vl_term *lhs_term; int true_hi=0, true_lo=0; int num_lhs_vars; int cur_bit_pos; lsList lhs_list; lsGen lhs_gen=(lsGen)0; lsHandle lhs_handle; vl_expr *lhs_expr; vl_id_range *lhs_var; vl_range *lhs_range; int i; WrtTRACE("Writing cont_assign\n"); for (gen = lsStart(assign->assigns); lsNext(gen, (lsGeneric*)&a, &handle) != LS_NOMORE; ) { a->type = AssignStmt; if (a->lhs->type == MinTypMaxExpr) a->lhs->name = (vl_id_range*)((vl_expr*)a->lhs->name)->u.exprs.e1; if (a->lhs->type == ConcatExpr) { num_lhs_vars = lsLength(a->lhs->concat); lhs_list = a->lhs->concat; lhs_gen = lsStart(lhs_list); } else { num_lhs_vars = 1; lhs_list = (lsList)0; } for (i=0; iu.name; lhs_range = lhs_var->range; } else { lhs_var = a->lhs->name; lhs_range = a->lhs->range; } if (!st_lookup(vl_currentModule->sig_st, lhs_var->name, (char**)&lhs_id)) { int retval; st_insert(vl_currentModule->sig_st, lhs_var->name, (char*)vl_create_id_range(lhs_var->name, NIL(vl_range))); retval = st_lookup(vl_currentModule->sig_st, lhs_var->name, (char**)&lhs_id); assert(retval); } } if (lhs_list) lsFinish(lhs_gen); nd_check_ok = 1; lhs_term = vl_write_assign(file, a, 0, NIL(vl_term), NIL(st_table)); nd_check_ok = 0; if (vis_nond_var) { vis_nond_var = 0; return; } if (lhs_list) { assert(array_n(assign_array) == num_lhs_vars); lhs_gen = lsStart(lhs_list); true_lo = lhs_term->lo; true_hi = lhs_term->hi; } for (i=0, cur_bit_pos=0; isig_st, lhs_expr->u.name->name, (char**)&lhs_id); assert(retval); } if (lhs_list) lhs_term = array_fetch(vl_term*, assign_array, i); if (!(lhs_id->flags & InPort && !(lhs_id->flags & OutPort))) st_insert(vars, lhs_id->name, (char*)create_var_info(vl_copy_id_range(lhs_id), lhs_term)); else { vl_id_range *id_sym; int retval = st_lookup(vl_currentModule->sig_st, lhs_id->name, (char**)&id_sym); assert(retval); id_sym->name = lhs_term->name->name; } } if (lhs_list) { lsFinish(lhs_gen); lhs_term->lo = true_lo; lhs_term->hi = true_hi; array_free(assign_array); } } (void)lsFinish(gen); } void vl_write_wiring_assign(FILE *file, vl_netdecl *assignments, st_table *vars) { vl_id_range *lhs_id; lsGen gen; lsHandle handle; vl_bassign_stmt *a; vl_term *lhs_term; int hi, lo; WrtTRACE("Writing wire_assign\n"); gen = lsStart(assignments->ids); if (lsNext(gen, (lsGeneric*)&a, &handle) == LS_OK) { if (a->type == BassignStmt) { a->type = AssignStmt; st_lookup(vl_currentModule->sig_st, a->lhs->name->name, (char**)&lhs_id); get_hilo(lhs_id, &hi, &lo); lhs_term = vl_write_assign(file,a,0,NIL(vl_term),NIL(st_table)); st_insert(vars, lhs_id->name, (char*)create_var_info(vl_copy_id_range(lhs_id), lhs_term)); } while (lsNext(gen, (lsGeneric*)&a, &handle) != LS_NOMORE) { if (a->type == BassignStmt) { st_lookup(vl_currentModule->sig_st, a->lhs->name->name, (char**)&lhs_id); get_hilo(lhs_id, &hi, &lo); a->type = AssignStmt; lhs_term = vl_write_assign(file, a, 0, NIL(vl_term), NIL(st_table)); st_insert(vars, lhs_id->name, (char*)create_var_info(vl_copy_id_range(lhs_id), lhs_term)); } } } (void)lsFinish(gen); } st_table *vl_write_event_control_stmt(FILE *file, vl_event_control_stmt *stmt, st_table *vars) { int old_recordCombAlways; set_t *old_sensitiveList; vl_term *old_edge_triggering; WrtTRACE("Writing event_control_stmt\n"); old_recordCombAlways = recordCombAlways; if (stmt->event->type == OrEventExpr || stmt->event->type == EventExpr) recordCombAlways = 1; old_edge_triggering = edge_triggering; old_sensitiveList = sensitiveList; sensitiveList = vl_write_event_expr(file, stmt->event); vars = vl_write_stmt(file, stmt->stmt, 0, NIL(vl_term), vars); edge_triggering = old_edge_triggering; recordCombAlways = old_recordCombAlways; sensitiveList = old_sensitiveList; return vars; } vl_term *vl_write_assign(FILE *file, vl_bassign_stmt *assign, int muxed, vl_term *muxsel, st_table *vars) { char latch_name[MAXSTRLEN]; vl_id_range *lhs_id=NIL(vl_id_range); vl_term *term_out=NIL(vl_term), *assign_term=NIL(vl_term), *retval=NIL(vl_term); int lo, hi; int old_lhs_hi, old_lhs_lo; vl_term *old_lhs_term; char buf[MAXSTRLEN]; lsList lhs_list; lsGen lhs_gen=(lsGen)0; lsHandle lhs_handle; vl_expr *lhs_expr; int num_lhs_vars; vl_id_range *lhs_var; vl_range *lhs_range; int i; WrtTRACE("Writing assign_stmt\n"); fprintf(file, "%s ", HSIS_COMMENT); if (!NoDetailedComment) vl_step_bassign_stmt(file, assign); fprintf(file, "\n"); assert(assign->type!=DelayBassignStmt && assign->type != DelayNbassignStmt && assign->type != EventBassignStmt && assign->type != EventNbassignStmt); if (assign->lhs->type == ConcatExpr) { num_lhs_vars = lsLength(assign->lhs->concat); lhs_list = assign->lhs->concat; lhs_gen = lsStart(lhs_list); assign_array = array_alloc(vl_term*, 0); } else { num_lhs_vars = 1; lhs_list = (lsList)0; } for (i=0; iu.name; lhs_range = lhs_var->range; } else { lhs_var = assign->lhs->name; lhs_range = assign->lhs->range; } if (!st_lookup(vl_currentModule->sig_st, lhs_var->name, (char**)&lhs_id)) { char buf[MAXSTRLEN]; yylineno = assign->lineno; sprintf(buf, "'%s':'%s' is an undeclared variable", vl_currentModule->name->name, lhs_var->name); compile_error(buf); } if (assign->type == NbassignStmt || assign->type == DelayNbassignStmt || assign->type == EventNbassignStmt) { vl_id_range *id_sym; sprintf(latch_name, "%s%s", lhs_var->name, SEP_LATCH); st_lookup(vl_currentModule->sig_st, latch_name, (char**)&id_sym); id_sym->flags = lhs_id->flags; lhs_id = id_sym; } else if (assign->type == AssignStmt && vars) { vl_id_range *id_sym; sprintf(latch_name, "%s%s", lhs_var->name, SEP_QUASI); if (!st_lookup(vl_currentModule->sig_st, latch_name,(char**)&id_sym)) { int retval; collect_quasi(lhs_var->name); retval = st_lookup(vl_currentModule->sig_st, latch_name,(char**)&id_sym); assert(retval); } id_sym->flags = lhs_id->flags; lhs_id = id_sym; } else { } if (lhs_id->flags & InPort && !(lhs_id->flags & OutPort)) { char msg[MAXSTRLEN]; sprintf(msg, "%s:%s is input variable while used as lhs", vl_currentModule->name->name, lhs_id->name); } if (!lhs_list) { if (vars) check_assign(assign, 1); else check_assign(assign, 0); } get_hilo(lhs_id, &hi, &lo); if (!muxed) { if (vars) { sprintf(buf, "%s%s%s%s", lhs_id->name, SEP_GATEPIN, PIN_RAWOUT, new_termname()); } else { sprintf(buf, "%s%s%s%s", lhs_id->name, SEP_GATEPIN, PIN_RAWOUT, new_termname()); } } else { if (muxed & 1) { sprintf(buf, "%s%s%s%s%s%s", lhs_id->name, SEP_GATEPIN, muxsel->name->name, new_termname(), SEP_GATEPIN, PIN_TRUE); } else { sprintf(buf, "%s%s%s%s%s%s", lhs_id->name, SEP_GATEPIN, muxsel->name->name, new_termname(), SEP_GATEPIN, PIN_FALSE); } } assign_term = term_out = create_rename_term(lhs_id, buf, lo, hi); assign_term->flag = lhs_id->flags; assign_term->term_type = lhs_id->id_type; if (!(vis_nond && assign->rhs->type == NondExpr) || rst_ckt) write_var_decl(file, assign_term); if (lhs_range) { if (lhs_id->range) { var_info *cur_var; vl_term *orig_term; vl_write_expr(file, lhs_range->left, vars); if (vars) { if (st_lookup(vars, lhs_id->name, (char**)&cur_var)) { orig_term = cur_var->current_terminal; } else { orig_term = vl_create_term(lhs_var, lo, hi); orig_term->flag = lhs_id->flags; orig_term->term_type = lhs_id->id_type; } } else { orig_term = vl_create_term(lhs_var, lo, hi); } assign_term = new_term(NIL(vl_range), lo, hi); assign_term->flag = lhs_id->flags; assign_term->term_type = lhs_id->id_type; write_var_decl(file, assign_term); write_switch(file, lhs_id, lhs_range->left->term, lhs_range->left, orig_term, assign_term, term_out); } else { int left, right; left = vl_eval_expr(lhs_range->left); if (lhs_range->right) right = vl_eval_expr(lhs_range->right); else right = left; assign_term->term_type = lhs_id->id_type; assign_term->lo = left; assign_term->hi = right; } } if (assign_term->lo > assign_term->hi) { if (assign_term->lo != 0 && assign_term->hi != -1) { int temp; temp = assign_term->lo; assign_term->lo = assign_term->hi; assign_term->hi = temp; } } if (lhs_list) { array_insert_last(vl_term*, assign_array, assign_term); } } if (lhs_list) { lsFinish(lhs_gen); assign_term = concate_assigns(assign_array); write_var_decl(file, assign_term); } switch(assign->type) { case BassignStmt: case NbassignStmt: case AssignStmt: { old_lhs_hi = lhs_hi; old_lhs_lo = lhs_lo; old_lhs_term = lhs_term; lhs_hi = assign_term->hi; lhs_lo = assign_term->lo; lhs_term = assign_term; vl_write_expr(file, assign->rhs, vars); lhs_hi = old_lhs_hi; lhs_lo = old_lhs_lo; lhs_term = old_lhs_term; break; } case DelayBassignStmt: break; case DelayNbassignStmt: break; case EventBassignStmt: break; case EventNbassignStmt: break; default: break; } if (!rst_ckt) { if (!lhs_list) dump_debug_information(file, assign->lhs->name, assign_term, assign->lineno, ctrl_list, ctrl_syndrome); } if (vis_nond_var && !vars) { return retval; } if (ISVLCONST(assign->rhs->type) && assign->rhs->type != BitExpr) { vl_write_const(file, assign->rhs, assign_term); if (!(assign_term->flag & MVar)) { var_info *cur_var; vl_term *orig_term; if (vars && !lhs_list) { if (st_lookup(vars, lhs_id->name, (char**)&cur_var)) { orig_term = cur_var->current_terminal; } else { orig_term = vl_create_term(assign->lhs->name, lo, hi); } patch_unaffected_term(file, lhs_id, orig_term, assign_term); } else if (lhs_list) { connect_concat(file, assign_term, assign_array); } } } else { if ((term_out->flag & MVar) == (assign->rhs->term->flag & MVar)) { if (assign->rhs->term->flag & MVar) { vl_write_mv_connect(file, assign->rhs->term, assign_term); } else { var_info *cur_var; vl_term *orig_term; vl_write_bin_connect(file, assign->rhs->term, assign_term, 0); if (vars && !lhs_list) { if (st_lookup(vars, lhs_id->name, (char**)&cur_var)) { orig_term = cur_var->current_terminal; } else { orig_term = vl_create_term(assign->lhs->name, lo, hi); } patch_unaffected_term(file, lhs_id, orig_term, assign_term); } else if (lhs_list) { connect_concat(file, assign_term, assign_array); } } } else { char buf[MAXSTRLEN]; sprintf(buf, "connecting incompatible wires '%s' and '%s'", assign_term->name->name,assign->rhs->term->name->name); compile_error(buf); } vl_free_term(assign->rhs->term); } retval = term_out; return retval; } st_table *vl_write_decl_list(FILE *file, void *decls, int muxed, vl_term *control, st_table *vars) { file = file; decls = decls; muxed = muxed; control = control; return vars; } st_table *vl_write_stmt_list(FILE *file, lsList stmts, int muxed, vl_term *control, st_table *vars) { void *stmt; lsHandle handle; lsGen gen; st_table *new_vars; lsList vars_list, pause_list; set_t *pauseSet; WrtTRACE("Writing stmt_list\n"); pauseSet = set_empty(); if (vl_pauseStack) push_stack(vl_pauseStack, (void*)pauseSet); pause_list = lsCreate(); vars_list = lsCreate(); for (gen = lsStart(stmts); lsNext(gen, (lsGeneric*)&stmt, &handle) != LS_NOMORE; ) { new_vars = vl_write_stmt(file, stmt, muxed, control, vars); vars = new_vars; } (void) lsFinish(gen); if (vl_pauseStack) pop_stack(vl_pauseStack, (void**)&pauseSet); set_destroy(pauseSet); lsDestroy(vars_list, 0); lsDestroy(pause_list, (void (*)(lsGeneric))set_destroy); return vars; } void vl_write_expr_list(FILE *file, lsList exprs, st_table *vars) { vl_expr *expr; lsHandle handle; lsGen gen; WrtTRACE("Writing expr_list\n"); if (!exprs) return; gen = lsStart(exprs); if (lsNext(gen, (lsGeneric*)&expr, &handle) == LS_OK) { vl_write_expr(file, expr, vars); while (lsNext(gen, (lsGeneric*)&expr, &handle) != LS_NOMORE) { vl_write_expr(file, expr, vars); } } (void)lsFinish(gen); } void vl_write_expr(FILE *file, vl_expr *expr, st_table *vars) { int lo, hi, sub_hi, sub_lo, inverted; vl_term *term_in1, *term_in2, *term_out, *idx_term; vl_id_range *id_sym; var_info *id_var_info; char term1[MAXSTRLEN/8]; char *ripple=NIL(char); int auto_declared = 0; int hibit; FILE *bufStream; if (!expr) return; WrtTRACE("write expr"); switch (expr->type) { case BitExpr: hibit = strlen((char*)expr->u.exprs.e3)-1; term_out = new_term(NIL(vl_range), 0, (hibit==0)?-1:hibit); write_var_decl(file, term_out); if (lhs_term) term_out->flag = lhs_term->flag; vl_write_const(file, expr, term_out); expr->term = term_out; break; case IntExpr: break; case RealExpr: break; case IDExpr: if (vars) { if (st_lookup(vars, expr->u.name->name, (char**)&id_var_info)) { expr->term = term_out = vl_copy_term(id_var_info->current_terminal); break; } } { int const_expr; vl_id_range *ival; const_expr = 0; if (vl_currentModule->param_st) { if (st_lookup(vl_currentModule->param_st, expr->u.name->name, (char**)&ival)) const_expr = 1; } if (!const_expr && vl_encloseModule) { if (vl_encloseModule->param_st) if (st_lookup(vl_encloseModule->param_st, expr->u.name->name, (char**)&ival)) const_expr = 1; } if (const_expr) { write_const_param(file, expr, ival); break; } } if (!st_lookup(vl_currentModule->sig_st, expr->u.name->name, (char**)&id_sym)){ if (implicitDeclare) { int retval; st_insert(vl_currentModule->sig_st, expr->u.name->name, (char*)vl_create_id_range(expr->u.name->name, NIL(vl_range))); retval = st_lookup(vl_currentModule->sig_st,expr->u.name->name, (char**)&id_sym); assert(retval); auto_declared = 1; } else { char msg[MAXSTRLEN/8]; yylineno = -1; sprintf(msg, "'%s':%s not defined", vl_currentModule->name->name, expr->u.name->name); compile_error(msg); } } else { id_sym->flags |= AccessedVar; } if (sensitiveList) { if (check_rhs_sensitivity) { if (!set_find(id_sym->name, sensitiveList)) { recordCombAlways = 0; if (vl_currentModule->combVar_st) { vl_currentModule->combVar_st = NIL(set_t); { char buf[MAXSTRLEN/8]; sprintf(buf, "%s:combinational reduction failed on %s", vl_currentModule->name->name, id_sym->name); yylineno = -1; compile_error(buf); } } } } } get_hilo(id_sym, &hi, &lo); if (!(id_sym->flags & RegVar) && !(id_sym->flags & InPort) && !(id_sym->flags & WireVar) && in_procedure && wireRegister) { char buf[MAXSTRLEN/8]; sprintf(buf, "%s%s", expr->u.name->name, PIN_HIDDEN); id_sym->flags |= HiddenLatch; expr->term = term_out = create_rename_term(expr->u.name, vlStrdup(buf), lo, hi); } else if (!((id_sym->flags & InPort) && (id_sym->flags & RegVar))) { expr->term = term_out = vl_create_term(vl_copy_id_range(id_sym), lo, hi); } else { char buf[MAXSTRLEN/8]; expr->term = term_out = vl_create_term(vl_copy_id_range(expr->u.name), lo, hi); sprintf(buf, "%s%s%s", expr->term->name->name, SEP_DIR, PIN_IN); vl_chk_free(expr->term->name->name); expr->term->name->name = vlStrdup(buf); } if (auto_declared) id_sym->flags |= AutoDeclared; term_out->flag = id_sym->flags; term_out->term_type = id_sym->id_type; break; case BitSelExpr: case PartSelExpr: if (vars) { int const_expr; vl_id_range *ival; const_expr = 0; if (vl_currentModule->param_st) { if (st_lookup(vl_currentModule->param_st, expr->u.name->name, (char**)&ival)) const_expr = 1; } if (!const_expr && vl_encloseModule) { if (vl_encloseModule->param_st) if (st_lookup(vl_encloseModule->param_st, expr->u.name->name, (char**)&ival)) const_expr = 1; } if (const_expr) { write_const_param(file, expr, ival); break; } if (st_lookup(vars, expr->u.name->name, (char**)&id_var_info)) { if (id_var_info->current_terminal->name->range) { vl_write_expr(file, expr->u.idrng->range->left, vars); idx_term = expr->u.idrng->range->left->term; expr->term = write_array_access(file, id_var_info->current_terminal->name, idx_term, expr->u.idrng->range->left); break; } } else { if (!st_lookup(vl_currentModule->sig_st, expr->u.name->name, (char**)&id_sym)) { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s': indexing into an undeclared var %s", vl_currentModule->name->name, expr->u.name->name); yylineno = -1; compile_error(buf); } if (id_sym->range) { vl_write_expr(file, expr->u.idrng->range->left, vars); idx_term = expr->u.idrng->range->left->term; expr->term = write_array_access(file, id_sym, idx_term, expr->u.idrng->range->left); break; } else { expr = expr; } } } else { if (!st_lookup(vl_currentModule->sig_st, expr->u.name->name, (char**)&id_sym)) { char buf[MAXSTRLEN/8]; sprintf(buf, "%s:'%s' is an undeclared indexing variable", vl_currentModule->name->name, expr->u.name->name); yylineno = -1; compile_error(buf); } if (id_sym->range) { vl_write_expr(file, expr->u.idrng->range->left, vars); idx_term = expr->u.idrng->range->left->term; expr->term = write_array_access(file, id_sym, idx_term, expr->u.idrng->range->left); break; } else { expr = expr; } } if (vars) { if (st_lookup(vars, expr->u.name->name, (char**)&id_var_info)) { expr->term = vl_copy_term(id_var_info->current_terminal); get_hilo(id_var_info->id, &hi, &lo); } else { st_lookup(vl_currentModule->sig_st, expr->u.name->name, (char**)&id_sym); get_hilo(id_sym, &hi, &lo); expr->term = vl_create_term(vl_copy_id_range(expr->u.name), lo, hi); } } else { st_lookup(vl_currentModule->sig_st, expr->u.name->name, (char**)&id_sym); get_hilo(id_sym, &hi, &lo); expr->term = vl_create_term(vl_copy_id_range(expr->u.name), lo, hi); } if ((lo > hi) && (expr->term->flag & MVar)) { char buf[MAXSTRLEN/8]; sprintf(buf,"idnexing into a scalar variable %s", expr->term->name->name); semantic_error(buf); } sub_lo = MAX(lo, vl_eval_expr(expr->u.idrng->range->left)); if (expr->u.idrng->range->right) sub_hi = MIN(hi, vl_eval_expr(expr->u.idrng->range->right)); else sub_hi = sub_lo; if (sub_hi < sub_lo) if (sub_hi != -1 && sub_lo != 0) { int temp; temp = sub_lo; sub_lo = sub_hi; sub_hi = temp; } expr->term->lo = sub_lo; expr->term->hi = sub_hi; break; case MinTypMaxExpr: vl_write_expr(file, expr->u.exprs.e1, vars); expr->term = expr->u.exprs.e1->term; break; case ConcatExpr: { vl_expr *e; lsHandle handle; lsGen gen=(lsGen)0; int bitWidth=0; int i, j, rep=1; FILE *new_file; expr->term = term_out = new_term(NIL(vl_range), 0, -1); if (expr->u.exprs.e2) { rep = vl_eval_expr(expr->u.exprs.e2); } insideConcat = 1; term_out->lo = -1; term_out->hi = -1; new_file = vl_begin_buffer(); j = 0; for (i=0; iu.exprs.e1)); lsPrev(gen, (lsGeneric*)&e, &handle) != LS_NOMORE;) { vl_write_expr(new_file, e, vars); if (e->term) { bitWidth = (e->term->hi-e->term->lo+1); bitWidth = (bitWidth>0) ? bitWidth : 1; term_out->lo = term_out->hi + 1; term_out->hi = term_out->lo + bitWidth - 1; vl_write_bin_connect(new_file, e->term, term_out, 0); } else { if (e->type == IntExpr) { bitWidth = min_bit_width(e->u.intval); bitWidth = (bitWidth>0) ? bitWidth : 1; e->term = new_term(NIL(vl_range), 0, bitWidth-1); write_int_connect(new_file, e->u.intval, e->term); term_out->lo = term_out->hi + 1; term_out->hi = term_out->lo + bitWidth - 1; vl_write_bin_connect(new_file, e->term, term_out, 0); } else { Translate_Warning("unknown width const in concatenation"); bitWidth = 0; } } j++; } } term_out->lo = 0; write_var_decl(file, term_out); vl_append_buffer(file, new_file); vl_close_buffer(new_file); bitWidth--; (void) lsFinish(gen); insideConcat = 0; break; } case StringExpr: break; case FuncExpr: { vl_function *func_def; if (vl_currentFunction) { vl_currentModule = vl_encloseModule; } if (!st_lookup(vl_currentModule->func_st,expr->u.func_call.name->name, (char**)&func_def)) { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':function %s is used before declaration", vl_currentModule->name->name, expr->u.func_call.name->name); yylineno = -1; compile_error(buf); } else { expr->term = instantiate_function(file, func_def, expr->u.func_call.args, vars); } if (vl_currentFunction) { vl_currentModule = (vl_module*)vl_currentFunction; } break; } case UplusExpr: case UminusExpr: { if (expr->type == UminusExpr) { vl_expr *fake_expr; fake_expr = vl_create_expr(BminusExpr, 0, (double)0.0, vl_create_expr(IntExpr, 0, (double)0.0, NIL(void), NIL(void), NIL(void)), expr->u.exprs.e1, NIL(void)); vl_write_expr(file, fake_expr, vars); vl_chk_free((char*)fake_expr); expr->term = fake_expr->term; } else { vl_write_expr(file, expr->u.exprs.e1, vars); expr->term = expr->u.exprs.e1->term; } break; } case UnotExpr: case UcomplExpr:inverted=1; goto write_expr; case UnandExpr: expr->type = UandExpr; inverted=1; goto write_expr; case UnorExpr: expr->type = UorExpr; inverted=1; goto write_expr; case UxnorExpr: expr->type = UxorExpr; inverted=1; goto write_expr; case UandExpr: inverted=0; goto write_expr; case UorExpr: inverted=0; goto write_expr; case UxorExpr: inverted=0; write_expr: vl_write_expr(file, expr->u.exprs.e1, vars); if (!expr->u.exprs.e1->term) { int val; val = vl_eval_expr(expr); expr->term = term_out = new_term(NIL(vl_range), 0, -1); vl_write_const(file, expr, expr->term); break; } vl_mv_to_bin(expr->u.exprs.e1->term); term_in1=expr->u.exprs.e1->term; expr->term = term_out = new_term(NIL(vl_range), 0, -1); ripple = BLIF_GND; if (term_in1->lo <= term_in1->hi) { if (expr->type != UcomplExpr) { write_var_decl(file, term_out); vl_write_vector_red_op(file, expr->type, term_in1, inverted, term_out); } else { term_out->lo = term_in1->lo; term_out->hi = term_in1->hi; write_var_decl(file, term_out); vl_write_bin_connect(file, term_in1, term_out, 1); } } else { write_var_decl(file, term_out); vl_write_bit_connect(file, term_in1->name->name, term_out->name->name, inverted); } if (inverted) { switch (expr->type) { case UandExpr: expr->type = UnandExpr; break; case UorExpr: expr->type = UnorExpr; break; case UxorExpr: expr->type = UxnorExpr; break; } } vl_free_term(term_in1); break; case Beq3Expr: case Bneq3Expr: case Beq2Expr: case Bneq2Expr: expr->term = term_out = new_term(NIL(vl_range), 0, -1); vl_write_expr(file, expr->u.exprs.e1, vars); vl_write_expr(file, expr->u.exprs.e2, vars); if (expr->u.exprs.e1->term && expr->u.exprs.e2->term) { if (expr->u.exprs.e1->term->flag & AutoDeclared && expr->u.exprs.e2->term->flag & AutoDeclared) { char buf[MAXSTRLEN/8]; vl_step_expr(stderr, expr); fprintf(stderr, "\n"); sprintf(buf, "'%s': too many undefined variables for the binary operator\n", vl_currentModule->name->name); yylineno = -1; compile_error(buf); } } if (!(expr->u.exprs.e1->term)) { lo = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->lo : 0; hi = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->hi : MAX(data_width(expr->u.exprs.e1), data_width(expr->u.exprs.e2)); expr->u.exprs.e1->term = new_term(NIL(vl_range), lo, hi); if (expr->u.exprs.e2->term) { expr->u.exprs.e1->term->flag |= expr->u.exprs.e2->term->flag; expr->u.exprs.e1->term->term_type = expr->u.exprs.e2->term->term_type; } write_var_decl(file, expr->u.exprs.e1->term); vl_write_const(file, expr->u.exprs.e1, expr->u.exprs.e1->term); } if (!(expr->u.exprs.e2->term)) { lo = (expr->u.exprs.e1->term) ? expr->u.exprs.e1->term->lo : 0; hi = (expr->u.exprs.e1->term) ? expr->u.exprs.e1->term->hi : MAX(data_width(expr->u.exprs.e2), data_width(expr->u.exprs.e1)); expr->u.exprs.e2->term = new_term(NIL(vl_range), lo, hi); if (expr->u.exprs.e1->term) { expr->u.exprs.e2->term->flag |= expr->u.exprs.e1->term->flag; expr->u.exprs.e2->term->term_type = expr->u.exprs.e1->term->term_type; } write_var_decl(file, expr->u.exprs.e2->term); vl_write_const(file, expr->u.exprs.e2, expr->u.exprs.e2->term); } if ((expr->u.exprs.e1->term->term_type && !expr->u.exprs.e2->term->term_type) || (expr->u.exprs.e2->term->term_type && !expr->u.exprs.e1->term->term_type)) { vl_expr *e1, *e2; vl_enumerator *enum_elt; if (!expr->u.exprs.e1->term->term_type) { e1 = expr->u.exprs.e2; e2 = expr->u.exprs.e1; } else { e1 = expr->u.exprs.e1; e2 = expr->u.exprs.e2; } if (e2->type != IDExpr) { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':comparing symbolic var '%s' with incompatible expr '%s'", vl_currentModule->name->name, e1->term->name->name, e2->term->name->name); semantic_error(buf); } if (st_lookup(e1->term->term_type->specifier-> u.enum_type->domain_st, e2->u.name->name, (char**)&enum_elt)) { e2->term = typed_new_term(e1->term->term_type, e1->term->name->range, e1->term->lo, e1->term->hi); e2->term->flag = e1->term->flag; write_var_decl(file, e2->term); e2->type = IntExpr; e2->u.intval = enum_elt->val; vl_write_const(file, e2, e2->term); } else { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':comparing '%s' and '%s' of different domains", vl_currentModule->name->name, e1->term->name->name, e2->term->name->name); semantic_error(buf); } } fprintf(file, "%s ", HSIS_COMMENT); if (!NoDetailedComment) vl_step_expr(file, expr); fprintf(file, "\n"); term_in1=expr->u.exprs.e1->term; term_in2=expr->u.exprs.e2->term; term_in2->flag |= (term_in1->flag & MVar); if ((term_in1->flag&MVar) == (term_in2->flag&MVar)) { if (term_in1->flag & MVar) { vl_write_mv_comp(file, expr->type, term_in1, term_in2, term_out); } else { vl_write_bin_comp(file, expr->type, term_in1, term_in2, term_out); } } else if (term_in1->flag & MVar) { vl_mv_to_bin(term_in1); vl_write_bin_comp(file, expr->type, term_in1, term_in2, term_out); } else if (term_in2->flag & MVar) { vl_mv_to_bin(term_in2); vl_write_bin_comp(file, expr->type, term_in1, term_in2, term_out); } vl_free_term(term_in1); vl_free_term(term_in2); break; case BtimesExpr: case BdivExpr: case BremExpr: sprintf(term1, "'%s':operator '*', '/', '%%' are not supported", vl_currentModule->name->name); yylineno = -1; compile_error(term1); break; case BlshiftExpr: case BrshiftExpr: sprintf(term1, "'%s':operator '<<', '>>' are not supported", vl_currentModule->name->name); yylineno = -1; compile_error(term1); break; case BlandExpr: case BlorExpr: case BltExpr: case BleExpr: case BgtExpr: case BgeExpr: case BplusExpr: case BminusExpr: case BandExpr: case BorExpr: case BxorExpr: case BxnorExpr: vl_write_expr(file, expr->u.exprs.e1, vars); vl_write_expr(file, expr->u.exprs.e2, vars); if (!(expr->u.exprs.e1->term)) { lo = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->lo : 0; hi = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->hi : MAX(data_width(expr->u.exprs.e1)-1, data_width(expr->u.exprs.e2)-1); if (lo==0 && hi==0) hi = -1; expr->u.exprs.e1->term = new_term(NIL(vl_range), lo, hi); write_var_decl(file, expr->u.exprs.e1->term); vl_write_const(file, expr->u.exprs.e1, expr->u.exprs.e1->term); } if (!(expr->u.exprs.e2->term)) { lo = (expr->u.exprs.e1->term) ? expr->u.exprs.e1->term->lo : 0; hi = (expr->u.exprs.e1->term) ? expr->u.exprs.e1->term->hi : MAX(data_width(expr->u.exprs.e2)-1, data_width(expr->u.exprs.e1)-1); if (lo==0 && hi==0) hi = -1; expr->u.exprs.e2->term = new_term(NIL(vl_range), lo, hi); write_var_decl(file, expr->u.exprs.e2->term); vl_write_const(file, expr->u.exprs.e2, expr->u.exprs.e2->term); } vl_mv_to_bin(expr->u.exprs.e1->term); vl_mv_to_bin(expr->u.exprs.e2->term); if (IS_VLR_LOG_OP(expr->type)) { if (vector_width(expr->u.exprs.e1->term->lo, expr->u.exprs.e1->term->hi) != 1) { vl_term *red_term; red_term = new_term(NIL(vl_range), 0, -1); write_red_op(file, UorExpr, expr->u.exprs.e1->term, NIL(vl_term), red_term); expr->u.exprs.e1->term = red_term; } if (vector_width(expr->u.exprs.e2->term->lo, expr->u.exprs.e2->term->hi) != 1) { vl_term *red_term; red_term = new_term(NIL(vl_range), 0, -1); write_red_op(file, UorExpr, expr->u.exprs.e2->term, NIL(vl_term), red_term); expr->u.exprs.e2->term = red_term; } } term_in1=expr->u.exprs.e1->term; term_in2=expr->u.exprs.e2->term; fprintf(file, "%s ", HSIS_COMMENT); if (!NoDetailedComment) vl_step_expr(file, expr); fprintf(file, "\n"); expr->term = term_out = new_term(NIL(vl_range), 0, -1); if (term_in1) if (term_in1->name->unintType) expr->term->name->unintType = term_in1->name->unintType; if (term_in2) if (term_in2->name->unintType) expr->term->name->unintType = term_in2->name->unintType; if (term_in1->lo > term_in1->hi) { term_out->lo = term_in2->lo; term_out->hi = term_in2->hi; } else if (term_in2->lo > term_in2->hi) { term_out->lo = term_in1->lo; term_out->hi = term_in1->hi; } else { term_out->lo = 0; term_out->hi = MAX(term_in1->hi-term_in1->lo, term_in2->hi-term_in2->lo); } if (expr->type == BplusExpr || expr->type ==BminusExpr) { if (vector_width(lhs_lo,lhs_hi) > vector_width(term_out->lo,term_out->hi)) { if (term_out->lo > term_out->hi) term_out->hi = 1; else term_out->hi++; } } else if (expr->type == BlshiftExpr || expr->type == BrshiftExpr) { if (vector_width(lhs_lo,lhs_hi) > vector_width(term_out->lo, term_out->hi)) { term_out->lo = lhs_lo; term_out->hi = lhs_hi; } } bufStream = openStream(); if (Use_MV_Lib) vl_write_mv_lib(bufStream, expr->type, term_in1, term_in2, term_out); else ripple = vl_write_vector_bop(bufStream, expr->type, term_in1, term_in2, term_out); write_var_decl(file, term_out); dumpStream(file, bufStream); closeStream(bufStream); if (Use_MV_Lib) { if (expr->type == BplusExpr || expr->type == BminusExpr) { char buf[MAXSTRLEN/8]; sprintf(buf, "%s%s%d%s", term_out->name->name, SEP_LBITSELECT, ++term_out->hi, SEP_RBITSELECT); vl_write_bit_connect(file, ripple, buf, 0); } } vl_free_term(term_in1); vl_free_term(term_in2); break; case TcondExpr: vl_write_expr(file, expr->u.exprs.e1, vars); vl_write_expr(file, expr->u.exprs.e2, vars); vl_write_expr(file, expr->u.exprs.e3, vars); if (!(expr->u.exprs.e1->term)) { expr->u.exprs.e1->term = new_term(NIL(vl_range), 0, -1); vl_write_const(file, expr->u.exprs.e1, expr->u.exprs.e1->term); } if (!expr->u.exprs.e2->term && !expr->u.exprs.e3->term && lhs_term) { lo = lhs_lo; hi = lhs_hi; expr->u.exprs.e2->term = new_term(NIL(vl_range), lo, hi); expr->u.exprs.e2->term->flag = lhs_term->flag; expr->u.exprs.e2->term->term_type = lhs_term->term_type; write_var_decl(file, expr->u.exprs.e2->term); vl_write_const(file, expr->u.exprs.e2, expr->u.exprs.e2->term); expr->u.exprs.e3->term = new_term(NIL(vl_range), lo, hi); expr->u.exprs.e3->term->flag = lhs_term->flag; expr->u.exprs.e3->term->term_type = lhs_term->term_type; write_var_decl(file, expr->u.exprs.e3->term); vl_write_const(file, expr->u.exprs.e3, expr->u.exprs.e3->term); } if (!(expr->u.exprs.e2->term)) { lo = (expr->u.exprs.e3->term) ? expr->u.exprs.e3->term->lo : 0; hi = (expr->u.exprs.e3->term) ? expr->u.exprs.e3->term->hi : MAX(data_width(expr->u.exprs.e2), data_width(expr->u.exprs.e3)); expr->u.exprs.e2->term = new_term(NIL(vl_range), lo, hi); expr->u.exprs.e2->term->flag = expr->u.exprs.e3->term->flag; expr->u.exprs.e2->term->term_type = expr->u.exprs.e3->term->term_type; write_var_decl(file, expr->u.exprs.e2->term); vl_write_const(file, expr->u.exprs.e2, expr->u.exprs.e2->term); } if (!(expr->u.exprs.e3->term)) { lo = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->lo : 0; hi = (expr->u.exprs.e2->term) ? expr->u.exprs.e2->term->hi : MAX(data_width(expr->u.exprs.e3), data_width(expr->u.exprs.e2)); expr->u.exprs.e3->term = new_term(NIL(vl_range), lo, hi); expr->u.exprs.e3->term->flag = expr->u.exprs.e2->term->flag; expr->u.exprs.e3->term->term_type = expr->u.exprs.e2->term->term_type; write_var_decl(file, expr->u.exprs.e3->term); vl_write_const(file, expr->u.exprs.e3, expr->u.exprs.e3->term); } if ((expr->u.exprs.e2->term->term_type && !expr->u.exprs.e3->term->term_type) || (expr->u.exprs.e3->term->term_type && !expr->u.exprs.e2->term->term_type)) { vl_expr *e1, *e2; vl_enumerator *enum_elt; if (!expr->u.exprs.e2->term->term_type) { e1 = expr->u.exprs.e3; e2 = expr->u.exprs.e2; } else { e1 = expr->u.exprs.e2; e2 = expr->u.exprs.e3; } if (st_lookup(e1->term->term_type->specifier-> u.enum_type->domain_st, e2->u.name->name, (char**)&enum_elt)) { e2->term = typed_new_term(e1->term->term_type, e1->term->name->range, e1->term->lo, e1->term->hi); e2->term->flag = e1->term->flag; write_var_decl(file, e2->term); e2->type = IntExpr; e2->u.intval = enum_elt->val; vl_write_const(file, e2, e2->term); } else { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':comparing '%s' and '%s' of different domains", vl_currentModule->name->name, e1->term->name->name, e2->term->name->name); semantic_error(buf); } } if (!expr->u.exprs.e2 && !expr->u.exprs.e3) { vl_expr *e; vl_enumerator *enum_elt; e = expr->u.exprs.e2; if (st_lookup(lhs_term->term_type->specifier-> u.enum_type->domain_st, e->u.name->name, (char**)&enum_elt)) { e->term = typed_new_term(lhs_term->term_type, lhs_term->name->range, lhs_term->lo, lhs_term->hi); e->term->flag = lhs_term->flag; write_var_decl(file, e->term); e->type = IntExpr; e->u.intval = enum_elt->val; vl_write_const(file, e, e->term); } else { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':assign '%s' to '%s' of different domains", vl_currentModule->name->name, e->term->name->name, lhs_term->name->name); semantic_error(buf); } e = expr->u.exprs.e3; if (st_lookup(lhs_term->term_type->specifier-> u.enum_type->domain_st, e->u.name->name, (char**)&enum_elt)) { e->term = typed_new_term(lhs_term->term_type, lhs_term->name->range, lhs_term->lo, lhs_term->hi); e->term->flag = lhs_term->flag; write_var_decl(file, e->term); e->type = IntExpr; e->u.intval = enum_elt->val; vl_write_const(file, e, e->term); } else { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':assign '%s' to '%s' of different domains", vl_currentModule->name->name, e->term->name->name, lhs_term->name->name); semantic_error(buf); } } term_in1=expr->u.exprs.e2->term; term_in2=expr->u.exprs.e3->term; fprintf(file, "%s ", HSIS_COMMENT); if (!NoDetailedComment) vl_step_expr(file, expr); fprintf(file, "\n"); expr->term = term_out = new_term(NIL(vl_range), 0, -1); term_out->flag = term_in1->flag; term_out->term_type = term_in1->term_type; if (lhs_term) { if (insideConcat) { if (vector_width(term_in1->lo, term_in1->hi) == vector_width(term_in2->lo, term_in2->hi)) { term_out->lo = 0; term_out->hi = vector_width(term_in1->lo,term_in1->hi)-1; } else { term_out->lo = lhs_term->lo; term_out->hi = lhs_term->hi; } } else { term_out->lo = lhs_term->lo; term_out->hi = lhs_term->hi; } if (vector_width(term_in1->lo, term_in1->hi) < vector_width(term_out->lo, term_out->hi)) { vl_term *tmp_term; tmp_term = new_term(NIL(vl_range), term_out->lo, term_out->hi); write_var_decl(file, tmp_term); expand_term(file, term_in1, tmp_term); vl_free_term(term_in1); term_in1 = tmp_term; } else if (vector_width(term_in1->lo, term_in1->hi) > vector_width(term_out->lo, term_out->hi)) { vl_term *tmp_term; tmp_term = new_term(NIL(vl_range), term_out->lo, term_out->hi); write_var_decl(file, tmp_term); shrink_term(file, term_in1, tmp_term); vl_free_term(term_in1); term_in1 = tmp_term; } if (vector_width(term_in2->lo, term_in2->hi) < vector_width(term_out->lo, term_out->hi)) { vl_term *tmp_term; tmp_term = new_term(NIL(vl_range), term_out->lo, term_out->hi); write_var_decl(file, tmp_term); expand_term(file, term_in2, tmp_term); vl_free_term(term_in2); term_in2 = tmp_term; } else if (vector_width(term_in2->lo, term_in2->hi) > vector_width(term_out->lo, term_out->hi)) { vl_term *tmp_term; tmp_term = new_term(NIL(vl_range), term_out->lo, term_out->hi); write_var_decl(file, tmp_term); shrink_term(file, term_in2, tmp_term); vl_free_term(term_in2); term_in2 = tmp_term; } } else { if (term_in1->lo > term_in1->hi) { term_out->lo = term_in2->lo; term_out->hi = term_in2->hi; } else if (term_in2->lo > term_in2->hi) { term_out->lo = term_in1->lo; term_out->hi = term_in1->hi; } else { term_out->lo = 0; if (term_in1->hi-term_in1->lo != term_in2->hi-term_in2->lo) { char buf[MAXSTRLEN/8]; sprintf(buf, "'%s':different vector sizes %s %s", vl_currentModule->name->name, term_in1->name->name, term_in2->name->name); Translate_Warning(buf); } term_out->hi = MIN(term_in1->hi-term_in1->lo, term_in2->hi-term_in2->lo); } } write_var_decl(file, term_out); instantiate_mux(file, term_in1, term_in2, expr->u.exprs.e1->term, term_out); vl_free_term(term_in1); vl_free_term(term_in2); break; case NondExpr: { vl_term *nond_term=NIL(vl_term), *ctrl_term=NIL(vl_term); lsList nond_list; lsGen gen; lsHandle handle; vl_expr *nexp; int i; if (vars && !rst_ckt) semantic_error("don't use $ND in procedural block"); nond_list = lsCreate(); if ((nd_check_ok == 0 && vis_nond) && !rst_ckt) { char buf[MAXSTRLEN/8]; yylineno = -1; sprintf(buf, "'%s': The legal usage of $ND is continuous assignment:\n\tassign = $ND(...);", vl_currentModule->name->name); compile_error(buf); } for (gen=lsStart(expr->u.expr_list), i=0; lsNext(gen, (lsGeneric*)&nexp, &handle) != LS_NOMORE; i++) { vl_write_expr(file, nexp, vars); if (nexp->type == EventExpr || nexp->type == PosedgeEventExpr || nexp->type == NegedgeEventExpr || nexp->type == OrEventExpr) { ctrl_term = NIL(vl_term); } else { lsNewEnd(nond_list, (lsGeneric)nexp, 0); } } lsFinish(gen); nond_term = vl_write_nond_wire(file, ctrl_term, nond_list, lhs_term); lsDestroy(nond_list, 0); expr->term = nond_term; if (!rst_ckt) nd_check_ok = -1; break; } } if (nd_check_ok == -1 && expr->type != NondExpr && vis_nond) { char buf[MAXSTRLEN/8]; yylineno = -1; sprintf(buf, "'%s': The legal usage of $ND is continuous assignment:\n\tassign = $ND(...);", vl_currentModule->name->name); compile_error(buf); } if (nd_check_ok != -1) nd_check_ok = 0; } set_t *vl_write_event_expr(FILE *file, vl_event_expr *event) { set_t *retval=NIL(set_t); vl_event_expr *e; lsGen gen; lsHandle handle; st_generator *stgen; vl_term *et; char *dummy; int i, j; WrtTRACE("writing event_expr\n"); if (event == NIL(vl_event_expr)) return retval; switch(event->type) { case OrEventExpr: retval = st_init_table(ptrcmp, ptrhash); gen = lsStart(event->list); while (lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE) { vl_write_event_expr(file, e); st_insert(retval, (char*)edge_triggering, 0); } lsFinish(gen); assert(st_count(retval) == lsLength(event->list)); edge_triggering = new_term(NIL(vl_range), 0, -1); fprintf(file, ".names "); stgen = st_init_gen(retval); while (st_gen(stgen, (char**)&et, &dummy)) { fprintf(file, "%s ", et->name->name); } st_free_gen(stgen); fprintf(file, "%s\n%s 0\n", edge_triggering->name->name, HSIS_DEFAULT); for (i=0; iexpr, -1); break; case PosedgeEventExpr: edge_triggering = write_edge_detector(file, event->expr, 1); break; case EdgeEventExpr: break; case EventExpr: edge_triggering = write_edge_detector(file, event->expr, 0); break; default: internal_error("Unexpected EventExpr Type"); break; } return retval; } int vl_eval_expr(vl_expr *expr) { int i, val; int min, typ, max; double minf=0, typf=0, maxf=0; int aux1_flag, aux2_flag, aux3_flag; if (!expr) return 0; switch (expr->type) { case BitExpr: return expr->u.bexpr.part1; case IntExpr: return expr->u.intval; case RealExpr: vl_expr_aux1_val = expr->u.realval; vl_expr_aux1_flag = 1; return (int)expr->u.realval; case IDExpr: { vl_id_range *id_sym; int cant_evaluate=0; int cant_find=0; if (vl_currentPrimitive) cant_evaluate = 1; if (!vl_currentModule->param_st) cant_evaluate = 1; if (!cant_evaluate) if (!st_lookup(vl_currentModule->param_st, expr->u.name->name, (char**)&id_sym)) cant_find = 1; if (vl_encloseModule && !cant_evaluate) if (cant_find) if (st_lookup(vl_encloseModule->param_st, expr->u.name->name, (char**)&id_sym)) cant_find=0; if (cant_evaluate || cant_find) { char buf[MAXSTRLEN]; sprintf(buf, "%s:eval_expr:need constant instead of variable %s", vl_currentModule->name->name, expr->u.name->name); yylineno = -1; if (silent_err) { Vlerrno = 1; return 0; } else compile_error(buf); } return (int)(id_sym->mpg_master_exp); } case BitSelExpr: case PartSelExpr: if (!silent_err) { vl_step_expr(stderr, expr); yylineno = -1; compile_error("need constant instead of variable"); } else { Vlerrno = 1; return 0; } case ConcatExpr: { int i, rep=1; int acc=0, val, width; lsGen gen; lsHandle handle; vl_expr *e; if (expr->u.exprs.e2) { rep = vl_eval_expr(expr->u.exprs.e2); } for (i=0; iu.exprs.e1)); lsNext(gen, (lsGeneric*)&e, &handle) != LS_NOMORE;) { if (e->type != BitExpr) width_unknown(); val = vl_eval_expr(e); width = strlen((char*)e->u.exprs.e3); acc = (acc << width) | val; } lsFinish(gen); } return acc; } case MinTypMaxExpr: aux1_flag = aux2_flag = aux3_flag = 0; min = vl_eval_expr(expr->u.exprs.e1); aux1_flag=1; if (vl_expr_aux1_val) minf=vl_expr_aux1_val; else minf = min; if (expr->u.exprs.e2) { typ = vl_eval_expr(expr->u.exprs.e2); aux2_flag=1; if (vl_expr_aux1_val) typf=vl_expr_aux1_val; else typf = typ; } if (expr->u.exprs.e3) { max = vl_eval_expr(expr->u.exprs.e2); aux3_flag=1; if (vl_expr_aux1_val) maxf=vl_expr_aux1_val; else maxf = max; } if (!vl_expr_aux3_flag) { aux3_flag = aux2_flag; aux2_flag = 0; max = typ; maxf = typf; typ = 0; typf = (double)0; } vl_expr_aux1_flag = aux1_flag; vl_expr_aux2_flag = aux2_flag; vl_expr_aux3_flag = aux3_flag; vl_expr_aux1_val = minf; vl_expr_aux2_val = typf; vl_expr_aux3_val = maxf; return min; case StringExpr: break; case FuncExpr: case UplusExpr: return vl_eval_expr(expr->u.exprs.e1); case UminusExpr: return -vl_eval_expr(expr->u.exprs.e1); case UnotExpr: return !vl_eval_expr(expr->u.exprs.e1); case UcomplExpr: return ~vl_eval_expr(expr->u.exprs.e1); case UnandExpr: case UandExpr: case UnorExpr: case UorExpr: case UxnorExpr: case UxorExpr: Translate_Warning("reduction on constant"); for (i=0, val = vl_eval_expr(expr->u.exprs.e1); itype) { case UnandExpr: case UandExpr: val = (val & 1) & (val >> 1); break; case UnorExpr: case UorExpr: val = (val & 1) | (val >> 1); break; case UxnorExpr: case UxorExpr: val = (val & 1) ^ (val >> 1); break; } val >>= 1; } if (expr->type == UnandExpr || expr->type == UnorExpr || expr->type == UxnorExpr) val = !val; case BtimesExpr: return vl_eval_expr(expr->u.exprs.e1) * vl_eval_expr(expr->u.exprs.e2); case BdivExpr: return vl_eval_expr(expr->u.exprs.e1) / vl_eval_expr(expr->u.exprs.e2); case BremExpr: return vl_eval_expr(expr->u.exprs.e1) % vl_eval_expr(expr->u.exprs.e2); case BlshiftExpr: return vl_eval_expr(expr->u.exprs.e1) << vl_eval_expr(expr->u.exprs.e2); case BrshiftExpr: return vl_eval_expr(expr->u.exprs.e1) >> vl_eval_expr(expr->u.exprs.e2); case Beq3Expr: return vl_eval_expr(expr->u.exprs.e1) == vl_eval_expr(expr->u.exprs.e2); case Bneq3Expr: return vl_eval_expr(expr->u.exprs.e1) != vl_eval_expr(expr->u.exprs.e2); case Beq2Expr: return vl_eval_expr(expr->u.exprs.e1) == vl_eval_expr(expr->u.exprs.e2); case Bneq2Expr: return vl_eval_expr(expr->u.exprs.e1) != vl_eval_expr(expr->u.exprs.e2); case BlandExpr: return vl_eval_expr(expr->u.exprs.e1) && vl_eval_expr(expr->u.exprs.e2); case BlorExpr: return vl_eval_expr(expr->u.exprs.e1) || vl_eval_expr(expr->u.exprs.e2); case BltExpr: return vl_eval_expr(expr->u.exprs.e1) < vl_eval_expr(expr->u.exprs.e2); case BleExpr: return vl_eval_expr(expr->u.exprs.e1) <= vl_eval_expr(expr->u.exprs.e2); case BgtExpr: return vl_eval_expr(expr->u.exprs.e1) > vl_eval_expr(expr->u.exprs.e2); case BgeExpr: return vl_eval_expr(expr->u.exprs.e1) >= vl_eval_expr(expr->u.exprs.e2); case BplusExpr: return vl_eval_expr(expr->u.exprs.e1) + vl_eval_expr(expr->u.exprs.e2); case BminusExpr: return vl_eval_expr(expr->u.exprs.e1) - vl_eval_expr(expr->u.exprs.e2); case BandExpr: return vl_eval_expr(expr->u.exprs.e1) & vl_eval_expr(expr->u.exprs.e2); case BorExpr: return vl_eval_expr(expr->u.exprs.e1) | vl_eval_expr(expr->u.exprs.e2); case BxorExpr: return vl_eval_expr(expr->u.exprs.e1) ^ vl_eval_expr(expr->u.exprs.e2); case BxnorExpr: return ~(vl_eval_expr(expr->u.exprs.e1) ^vl_eval_expr(expr->u.exprs.e2)); case TcondExpr: return (vl_eval_expr(expr->u.exprs.e1)) ? vl_eval_expr(expr->u.exprs.e2) : vl_eval_expr(expr->u.exprs.e3); } return 0; } st_table *create_var_muxes(FILE *file, vl_term *sel, st_table *t_vars, st_table *f_vars, st_table *vars) { int lo=0, hi=0; var_info *cur_var; st_generator *gen; var_info *t_in, *f_in; char *key, buf[MAXSTRLEN]; vl_term *term_out; gen = st_init_gen(t_vars); while (st_gen(gen, &key, (char**)&t_in)) { if (strstr(key,SEP_LATCH)) continue; if (strstr(key,SEP_QUASI)) continue; sprintf(buf, "%s%s%s%s%s%s", t_in->id->name, SEP_GATEPIN, descape(sel->name->name,'\\','_'), SEP_GATEPIN, PIN_RAWOUT, new_termname()); if (st_lookup(f_vars, key, (char**)&f_in)) { if (st_lookup(vars, key, (char**)&cur_var)) { int t_in_cur_var, f_in_cur_var; t_in_cur_var = !strcmp(t_in->current_terminal->name->name, cur_var->current_terminal->name->name); f_in_cur_var = !strcmp(f_in->current_terminal->name->name, cur_var->current_terminal->name->name); if ( t_in_cur_var && f_in_cur_var) continue; if ((strstr(t_in->current_terminal->name->name, SEP_GATEPIN) || strstr(f_in->current_terminal->name->name, SEP_GATEPIN)) && !(t_in->current_terminal->hi == -1 || f_in->current_terminal->hi == -1) && (t_in->current_terminal->hi!=f_in->current_terminal->hi || t_in->current_terminal->lo!=f_in->current_terminal->lo)) { if (t_in->current_terminal->hi != f_in->current_terminal->hi || t_in->current_terminal->lo != f_in->current_terminal->lo) { int i, t_need_extend, f_need_extend; char in_buf[MAXSTRLEN], out_buf[MAXSTRLEN]; vl_term *t_new_term=NIL(vl_term), *f_new_term=NIL(vl_term); hi = MAX(t_in->current_terminal->hi,f_in->current_terminal->hi); lo = MIN(t_in->current_terminal->lo,f_in->current_terminal->lo); t_need_extend = (hi > t_in->current_terminal->hi || lo < t_in->current_terminal->lo); f_need_extend = (hi > f_in->current_terminal->hi || lo < f_in->current_terminal->lo); if (t_need_extend) { t_new_term = typed_new_term(t_in->current_terminal->term_type, t_in->id->range, lo, hi); write_var_decl(file, t_new_term); } if (f_need_extend) { f_new_term = typed_new_term(f_in->current_terminal->term_type, f_in->id->range, lo, hi); write_var_decl(file, f_new_term); } for (i=lo; i<=hi; i++) { if (t_need_extend) { if (i < t_in->current_terminal->lo || i > t_in->current_terminal->hi) { var_info *curr_var_info; st_lookup(vars, t_in->id->name, (char**)&curr_var_info); if (i >= curr_var_info->current_terminal->lo && i <= curr_var_info->current_terminal->hi) { sprintf(in_buf, "%s%s%d%s", curr_var_info-> current_terminal->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } else { sprintf(in_buf, "%s%s%d%s", t_in->id->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } } else { sprintf(in_buf, "%s%s%d%s", t_in->current_terminal->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } sprintf(out_buf, "%s%s%d%s", t_new_term->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); vl_write_bit_connect(file, in_buf, out_buf, 0); } if (f_need_extend) { if (i < f_in->current_terminal->lo || i > f_in->current_terminal->hi) { var_info *curr_var_info; st_lookup(vars, t_in->id->name, (char**)&curr_var_info); if (i >= curr_var_info->current_terminal->lo && i <= curr_var_info->current_terminal->hi) { sprintf(in_buf, "%s%s%d%s", curr_var_info-> current_terminal->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } else { sprintf(in_buf, "%s%s%d%s", f_in->id->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } } else { sprintf(in_buf, "%s%s%d%s", f_in->current_terminal->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); } sprintf(out_buf, "%s%s%d%s", f_new_term->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); vl_write_bit_connect(file, in_buf, out_buf, 0); } } if (t_need_extend) t_in->current_terminal = t_new_term; if (f_need_extend) f_in->current_terminal = f_new_term; } } else { if (t_in->current_terminal->hi-t_in->current_terminal->lo>= f_in->current_terminal->hi-f_in->current_terminal->lo){ lo = t_in->current_terminal->lo; hi = t_in->current_terminal->hi; } else { lo = f_in->current_terminal->lo; hi = f_in->current_terminal->hi; } } term_out = create_rename_term(t_in->id, buf, lo, hi); term_out->flag = t_in->current_terminal->flag; write_var_decl(file, term_out); instantiate_mux(file, t_in->current_terminal, f_in->current_terminal, sel, term_out); cur_var->current_terminal = term_out; if (!t_in_cur_var && !f_in_cur_var) { continue; } if (!t_in_cur_var && f_in_cur_var) { continue; } if (t_in_cur_var && !f_in_cur_var) { continue; } } } } st_free_gen(gen); gen = st_init_gen(t_vars); while (st_gen(gen, &key, (char**)&t_in)) { if (strstr(key,SEP_LATCH)) continue; if (strstr(key,SEP_QUASI)) continue; sprintf(buf, "%s%s%s%s%s%s", t_in->id->name, SEP_GATEPIN, descape(sel->name->name,'\\','_'), SEP_GATEPIN, PIN_RAWOUT, new_termname()); if (st_lookup(f_vars, key, (char**)&f_in)) { if (!st_lookup(vars, key, (char**)&cur_var)) { if (t_in->current_terminal->hi-t_in->current_terminal->lo >= f_in->current_terminal->hi-f_in->current_terminal->lo) { lo = t_in->current_terminal->lo; hi = t_in->current_terminal->hi; } else { lo = f_in->current_terminal->lo; hi = f_in->current_terminal->hi; } term_out = create_rename_term(t_in->id, buf, lo, hi); term_out->flag |= t_in->current_terminal->flag; write_var_decl(file, term_out); instantiate_mux(file, t_in->current_terminal, f_in->current_terminal, sel, term_out); assert(!st_lookup(vars,key,(char**)&cur_var)); st_insert(vars, key, (char*)create_var_info(vl_copy_id_range(t_in->id), term_out)); } } } st_free_gen(gen); gen = st_init_gen(t_vars); while (st_gen(gen, &key, (char**)&t_in)) { if (strstr(key,SEP_LATCH)) continue; if (strstr(key,SEP_QUASI)) continue; sprintf(buf, "%s%s%s%s%s%s", t_in->id->name, SEP_GATEPIN, descape(sel->name->name,'\\','_'), SEP_GATEPIN, PIN_RAWOUT, new_termname()); if (!st_lookup(f_vars, key, (char**)&f_in)) { vl_term *orig_id; char *dummy; term_out = create_rename_term(t_in->id, buf, t_in->current_terminal->lo, t_in->current_terminal->hi); term_out->flag |= t_in->current_terminal->flag; orig_id = vl_create_term(((t_in->id->flags & EventVar) && smartEvent)? vl_create_id_range(WRT_BLIF_GND(file), NIL(vl_range)) : vl_copy_id_range(t_in->id), t_in->current_terminal->lo, t_in->current_terminal->hi); if (vl_currentModule->combVar_st) if (st_lookup(vl_currentModule->combVar_st, orig_id->name->name, &dummy)) { vl_free_term(orig_id); orig_id = true_term(file); } if (vl_currentFunction) { vl_free_term(orig_id); orig_id = true_term(file); } orig_id->flag = t_in->current_terminal->flag; write_var_decl(file, term_out); if (rst_ckt) { instantiate_mux(file, t_in->current_terminal, t_in->current_terminal, sel, term_out); } else { instantiate_mux(file, t_in->current_terminal, orig_id, sel, term_out); } vl_free_term(orig_id); st_insert(vars, key, (char*)create_var_info(vl_copy_id_range(t_in->id), term_out)); } } st_free_gen(gen); gen = st_init_gen(f_vars); while (st_gen(gen, &key, (char**)&f_in)) { if (strstr(key,SEP_LATCH)) continue; if (strstr(key,SEP_QUASI)) continue; sprintf(buf, "%s%s%s%s%s%s", f_in->id->name, SEP_GATEPIN, descape(sel->name->name,'\\','_'), SEP_GATEPIN, PIN_RAWOUT, new_termname()); if (!st_lookup(t_vars, key, (char**)&t_in)) { vl_term *orig_id; term_out = create_rename_term(f_in->id, buf, f_in->current_terminal->lo, f_in->current_terminal->hi); term_out->flag |= f_in->current_terminal->flag; orig_id = vl_create_term(((f_in->id->flags & EventVar) && smartEvent)? vl_create_id_range(WRT_BLIF_GND(file), NIL(vl_range)) : vl_copy_id_range(f_in->id), f_in->current_terminal->lo, f_in->current_terminal->hi); orig_id->flag = f_in->current_terminal->flag; write_var_decl(file, term_out); if (rst_ckt) { instantiate_mux(file, f_in->current_terminal, f_in->current_terminal, sel, term_out); } else { instantiate_mux(file, orig_id, f_in->current_terminal, sel, term_out); } vl_free_term(orig_id); st_insert(vars, key, (char*)create_var_info(vl_copy_id_range(f_in->id), term_out)); } } st_free_gen(gen); return vars; } vl_term *write_case_comparator(FILE *file, vl_term *selector, lsList tags, st_table *vars) { int j; vl_expr *expr; lsHandle handle; lsGen gen; vl_term *term_out; vl_term *comp_result; char buf[MAXSTRLEN]; if (!tags) return NIL(vl_term); buf[0] = '\0'; term_out = new_term(NIL(vl_range), 0, -1); for (gen = lsStart(tags); lsNext(gen, (lsGeneric*)&expr, &handle) != LS_NOMORE; ) { comp_result = new_term(NIL(vl_range), 0, -1); write_case_tag_const(file, selector, expr, vars); write_comparator(file, selector, expr->term, comp_result); strcat(buf, comp_result->name->name); strcat(buf, " "); vl_free_term(comp_result); comp_result = NIL(vl_term); vl_free_term(expr->term); expr->term = NIL(vl_term); } (void)lsFinish(gen); fprintf(file, ".names %s %s\n", buf, term_out->name->name); fprintf(file, ".def 1\n"); for (j=0; jlo == in->hi) { if (out->lo > out->hi) { sprintf(in1, "%s%s%d%s", in->name->name, SEP_LBITSELECT, in->lo, SEP_RBITSELECT); sprintf(in2, "%s", out->name->name); vl_write_bit_connect(file, in1, in2, inverted); return; } else { sprintf(in1, "%s%s%d%s", in->name->name, SEP_LBITSELECT, in->lo, SEP_RBITSELECT); sprintf(in2, "%s%s%d%s", out->name->name, SEP_LBITSELECT, in->lo, SEP_RBITSELECT); vl_write_bit_connect(file, in1, in2, inverted); return; } } sprintf(rip_buf, "%s", new_termname()); sprintf(in1, "%s%s%d%s", in->name->name, SEP_LBITSELECT, in->lo, SEP_RBITSELECT); sprintf(in2, "%s%s%d%s", in->name->name, SEP_LBITSELECT, in->lo+1, SEP_RBITSELECT); strcpy(rip_buf, vl_write_bop(file, type, in1, in2, NIL(char), NIL(char), 1)); for (i=in->lo+2; i<=in->hi; i++) { strcpy(in1, rip_buf); sprintf(in2, "%s%s%d%s", in->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT); strcpy(rip_buf, vl_write_bop(file, type, in1, in2, NIL(char), NIL(char), 1)); } vl_write_bit_connect(file, rip_buf, out->name->name, inverted); } void vl_write_bit_connect(FILE *file, char *in, char *out, int inverted) { char **func; func = (set_notation)?set_log_function:log_function; fprintf(file, ".names %s %s\n", in, out); if (set_notation) { if (!inverted) fprintf(file, "- %s%s\n", HSIS_EQUAL, in); else fprintf(file, "%s", func[BLIF_NOT]); } else { if (!inverted) fprintf(file, "%s", func[BLIF_BITCONNECT]); else fprintf(file, "%s", func[BLIF_NOT]); } } void write_comparator(FILE *file, vl_term *in1, vl_term *in2, vl_term *out) { if ((in1->flag&MVar) == (in2->flag&MVar)) { if (in1->flag & MVar) { vl_write_mv_comp(file, (short)Beq2Expr, in1, in2, out); } else { vl_write_bin_comp(file, (short)Beq2Expr, in1, in2, out); } } else if (in1->flag & MVar) { vl_mv_to_bin(in1); vl_write_bin_comp(file, (short)Beq2Expr, in1, in2, out); } else if (in1->flag & MVar) { vl_mv_to_bin(in2); vl_write_bin_comp(file, (short)Beq2Expr, in1, in2, out); } } vl_term *instantiate_function(FILE *file, vl_function *master, lsList args, st_table *vars) { vl_port_connect *i_port; vl_term *retval; int hi, lo, temp; int constConnection; lsGen mast_gen, inst_gen, gen; lsHandle mast_handle, inst_handle, handle; vl_id_range *m; vl_expr *i; const_term *ct; vl_enumerator *enum_elt; lsList input_consts; i_port = vl_create_port_connect(ModuleConnect, NIL(vl_id_range), NIL(vl_expr)); input_consts = lsCreate(); if (lsLength(args)!=0 && lsLength(master->ports)!=0) { mast_gen = lsStart(master->ports); inst_gen = lsStart(args); lsNext(mast_gen, (lsGeneric*)&m, &mast_handle); while (lsNext(inst_gen, (lsGeneric*)&i, &inst_handle) != LS_NOMORE && lsNext(mast_gen, (lsGeneric*)&m, &mast_handle) != LS_NOMORE) { if (!st_lookup(master->sig_st, m->name, (char**)&m)) { char buf[MAXSTRLEN]; sprintf(buf, "port '%s' is not defined in module '%s'", m->name, master->name->name); semantic_error(buf); } vl_write_expr(file, i, vars); } lsFinish(inst_gen); lsFinish(mast_gen); } if (master->range) { lo = vl_eval_expr(master->range->left); hi = vl_eval_expr(master->range->right); if (hi < lo) { temp = hi; hi = lo; lo = temp; } } else { lo = 0; hi = -1; } retval = new_term(NIL(vl_range), lo, hi); write_var_decl(file, retval); fprintf(file, ".subckt %s %s ", master->name->name, new_termname()); if (lsLength(args)!=0 && lsLength(master->ports)!=0) { mast_gen = lsStart(master->ports); inst_gen = lsStart(args); lsNext(mast_gen, (lsGeneric*)&m, &mast_handle); if (lo > hi) { put_bin_scalar_func_connect(file, m, retval); } else { put_bin_vector_func_connect(file, m, retval); } while (lsNext(inst_gen, (lsGeneric*)&i, &inst_handle) != LS_NOMORE && lsNext(mast_gen, (lsGeneric*)&m, &mast_handle) != LS_NOMORE) { constConnection = 0; if (!i) { constConnection = 1; } else if (!i->term) { constConnection = 1; } else { if (m->id_type) { if (i->type == IDExpr && st_lookup(m->id_type->specifier-> u.enum_type->domain_st, i->u.name->name, (char**)&enum_elt)) constConnection = 1; } } i_port->expr = i; if (constConnection) { put_const_port_connect(file, NIL(char), m, i_port, input_consts, retval); continue; } if (m->flags & MVar) { put_mvar_port_connect(file, NIL(char), m, i_port); } else { get_hilo(m, &hi, &lo); if (lo > hi) { put_bin_scalar_port_connect(file, NIL(char), m, i_port); } else { put_bin_vector_port_connect(file, NIL(char), m, i_port); } } } lsFinish(inst_gen); lsFinish(mast_gen); fprintf(file, "\n"); gen = lsStart(input_consts); while(lsNext(gen, (lsGeneric*)&ct, &handle) != LS_NOMORE) { if (!isOutPort(ct->term->flag)) write_var_decl(file, ct->term); vl_write_const(file, ct->const_expr, ct->term); } lsFinish(gen); lsDestroy(input_consts, 0); } return retval; } void connect_func_output(FILE *file, vl_id_range *out_id_sym, st_table *vars) { vl_id_range *orig_id_sym; var_info *var; int hi, lo; int old_flags; int retval; if (!st_lookup(vars, out_id_sym->name, (char**)&var)) { char buf[MAXSTRLEN]; sprintf(buf, "function %s has no return value", out_id_sym->name); yylineno = -1; compile_error(buf); } retval = st_lookup(vl_currentFunction->sig_st, out_id_sym->name, (char**)&orig_id_sym); assert(retval); get_hilo(orig_id_sym, &hi, &lo); old_flags = orig_id_sym->flags; orig_id_sym->flags &= ~RegVar; if (var->current_terminal->flag & MVar) { instantiate_mvar_latch(file, 0, 0, lo, hi, out_id_sym, orig_id_sym, var, orig_id_sym->name); } else { if (lo > hi) { instantiate_bin_scalar_latch(file, 0, 0, out_id_sym, orig_id_sym, var, orig_id_sym->name); } else { instantiate_bin_vector_latch(file, 0, 0, lo, hi, out_id_sym, orig_id_sym, var, orig_id_sym->name); } } orig_id_sym->flags = old_flags; } void instantiate_latch(FILE *file, st_table *vars) { vl_id_range *id_sym, *orig_id_sym; st_generator *gen; char *key, *ps_buf, *dummy; var_info *var, *lvar; blif_latch *latch; char latch_name[MAXSTRLEN]; int lo, hi; int non_block_var; fprintf(file, "%s latches\n", HSIS_COMMENT); gen = st_init_gen(vars); while (st_gen(gen, &key, (char**)&var)) { sprintf(latch_name, "%s%s", key, SEP_LATCH); if (vl_currentModule->latch_st) { if (st_lookup(vl_currentModule->sig_st, key, (char**)&id_sym)) { if (!(id_sym->flags & RegVar) && !str_matchtail(id_sym->name,SEP_LATCH)) continue; non_block_var = str_matchtail(id_sym->name,SEP_LATCH); if (st_lookup(vl_currentModule->latch_st, key, (char**)&latch)) if (latch->flags & NBASSIGN_IN_ALWAYS) continue; if (dflow_analysis && !(id_sym->flags & OutPort) && !(id_sym->flags & InPort) && !(str_matchtail(id_sym->name,SEP_LATCH)) && !set_find(id_sym->name, vl_currentModule->uninit_set)) continue; if (!st_lookup(vars, latch_name, (char**)&lvar)) lvar = var; get_hilo(var->id, &hi, &lo); ps_buf = vlStrdup(var->id->name); if (str_matchtail(id_sym->name,SEP_LATCH)) { strip_char(ps_buf,SEP_LATCH); st_lookup(vl_currentModule->sig_st, ps_buf, (char**)&orig_id_sym); } else { orig_id_sym = id_sym; } if (st_lookup(vl_currentModule->quasi_st, ps_buf, (char**)&dummy)){ char *old_termname; char *dc; int n_entries; char qbuf[MAXSTRLEN]; vl_id_range *qid_sym; int retval; sprintf(qbuf, "%s%s", ps_buf, SEP_QUASI); retval = st_lookup(vl_currentModule->sig_st, qbuf, (char**)&qid_sym); assert(retval); old_termname = lvar->current_terminal->name->name; dc = check_dc((!rst_ckt)?qid_sym->syndrome_expr_list: qid_sym->rst_syndrome_expr_list); n_entries = lsLength((!rst_ckt)? qid_sym->syndrome_expr_list: qid_sym->rst_syndrome_expr_list); lvar->current_terminal->name->name = vlStrdup(new_termname()); write_var_decl(file, lvar->current_terminal); put_quasi_table(file, dc, ps_buf, old_termname, qid_sym, lvar->current_terminal, lo, hi, n_entries); vl_chk_free(old_termname); vl_chk_free(dc); } if (!use_rst_ckt && (orig_id_sym->flags & RegVar)) { if ((lsLength(id_sym->initial)==0) && Warn_Uninitialized) { char buf[MAXSTRLEN]; sprintf(buf, "%s:%s: uninitialized", vl_currentModule->name->name, id_sym->name); Translate_Notice(buf); } if ((orig_id_sym->flags) & MVar) { reset_mvar_latch(file, non_block_var, id_sym, lo, hi, ps_buf); } else { if (lo > hi) { reset_bin_scalar_latch(file, non_block_var, id_sym, ps_buf); } else { reset_bin_vector_latch(file, non_block_var, id_sym, lo, hi, ps_buf); } } } else { if (lsLength(id_sym->initial)>0 && get_decl_flags(var->id->mpg_master_exp) & RegVar) { instantiate_reset_mux(file, id_sym, lo, hi, var, lvar); } } if (var->current_terminal->flag & MVar) { instantiate_mvar_latch(file, non_block_var, mark_sel_var, lo, hi, id_sym, orig_id_sym, lvar, ps_buf); } else { if (lo > hi) { instantiate_bin_scalar_latch(file, non_block_var, mark_sel_var, id_sym, orig_id_sym, lvar, ps_buf); } else { instantiate_bin_vector_latch(file, non_block_var, mark_sel_var, lo, hi, id_sym, orig_id_sym, lvar, ps_buf); } } vl_chk_free(ps_buf); } } } st_free_gen(gen); gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { instantiate_input_latch(file, id_sym); if (wireRegister) instantiate_hidden_latch(file, id_sym); } st_free_gen(gen); } static void instantiate_prim_latch(FILE *file, st_table *sig_st) { st_generator *sig_gen; vl_id_range *id_sym; char *key; sig_gen = st_init_gen(sig_st); while (st_gen(sig_gen, (char**)&key, (char**)&id_sym)) { if (!(id_sym->flags & RegVar)) continue; fprintf(file, ".latch %s%s %s\n", id_sym->name, SEP_LATCH, id_sym->name); fprintf(file, ".r %s\n-\n", id_sym->name); } st_free_gen(sig_gen); } static void instantiate_edge_detector(FILE *file, vl_primitive *prim) { lsGen port_gen; lsHandle port_handle, port_id_handle; vl_port *port; vl_id_range *port_id, *port_id_sym; port_gen = lsStart(prim->ports); while (lsNext(port_gen, (lsGeneric*)&port, &port_handle) != LS_NOMORE) { int retval; lsFirstItem(port->port_exp, (lsGeneric*)&port_id, &port_id_handle); retval = st_lookup(prim->sig_st, port_id->name, (char**)&port_id_sym); assert(retval); if (port_id_sym->flags & EdgeDetector) { fprintf(file, ".latch %s %s%s\n", port_id_sym->name, port_id_sym->name, PIN_DELAYED); fprintf(file, ".r %s%s\n-\n", port_id_sym->name, PIN_DELAYED); } } lsFinish(port_gen); } static char *lib_fun[][2] = { {"vlr_mux", " %s a=%s b=%s s=%s o=%s\n"} }; void vl_put_lib(FILE *file, ...) { char buf[MAXSTRLEN]; char typ_buf[MAXSTRLEN]; char *cp, *tcp; int code; va_list args; vl_term *type_term; void *decl; lsList domain; lsGen enum_gen; lsHandle enum_handle; vl_enumerator *enum_elt; va_start(args, file); code = va_arg(args, int); type_term = va_arg(args, vl_term*); cp = buf; *cp = '\0'; cp = strappendS(cp, ".subckt"); cp = strappend(cp, lib_fun[code][0]); tcp = typ_buf; *tcp = '\0'; tcp = strappend(tcp, SEP_LTRANGE); if (type_term->flag & MVar) { (void) va_arg(args, char*); (void)vfprintf(file, ".names %s %s %s %s\n", args); if (!st_lookup(mod_list->decl_st, (char*)type_term->term_type, (char**)&decl)) { st_insert(mod_list->decl_st, (char*)type_term->term_type, (char*)type_term->term_type); } domain = type_term->term_type->specifier->u.enum_type->domain_list; for (enum_gen=lsStart(domain); lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s - 1 %s\n", enum_elt->name, enum_elt->name); fprintf(file, "- %s 0 %s\n", enum_elt->name, enum_elt->name); } lsFinish(enum_gen); } else { char *tbuf, *fbuf, *selbuf, *obuf; (void) va_arg(args, char*); tbuf = va_arg(args, char *); fbuf = va_arg(args, char *); selbuf = va_arg(args, char *); obuf = va_arg(args, char *); fprintf(file, ".names %s %s %s %s\n.def 0\n", selbuf, tbuf, fbuf, obuf); fprintf(file, "1 1 - 1\n0 - 1 1\n"); } va_end(args); } void vl_write_mv_lib(FILE *file, short type, vl_term *in1, vl_term *in2, vl_term *out) { int i; lsList domain; lsGen enum_gen; lsHandle enum_handle; vl_enumerator *enum_elt; fprintf(file, ".subckt "); switch(type) { case BandExpr: fprintf(file, "%s", BLIF_LIB_AND); break; case BorExpr: fprintf(file, "%s", BLIF_LIB_OR); break; case BxorExpr: fprintf(file, "%s", BLIF_LIB_XOR); break; case BxnorExpr:fprintf(file, "%s", BLIF_LIB_XNOR); break; case BplusExpr: fprintf(file, "%s", BLIF_LIB_ADD); break; case BminusExpr:fprintf(file, "%s", BLIF_LIB_SUB); break; case UandExpr: case UnandExpr: case UorExpr: case UnorExpr: case UxorExpr: case UxnorExpr: break; } if (in1->term_type != in2->term_type) { char buf[MAXSTRLEN]; sprintf(buf,"operation between var %s & %s of different types", in1->name->name, in2->name->name); semantic_error(buf); } domain = in1->term_type->specifier->u.enum_type->domain_list; fprintf(file, "%s", SEP_LTRANGE); for (enum_gen=lsStart(domain), i=1; lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!=LS_NOMORE; i++) fprintf(file, "%s%c", enum_elt->name, (i==lsLength(domain)?'\0':':')); fprintf(file, "%s", SEP_RTRANGE); fprintf(file, " %s %s %s %s\n", new_termname(), in1->name->name, in2->name->name, out->name->name); } st_table *conflict_arbitrator(FILE *file, array_t *vars_array) { st_generator *gen; st_table *vars, *retval; char *key; var_info *cur_var; array_t *controls; vl_term *ctrl_i; int lo, hi; int num_changer; int i; vl_id_range *id_sym, *temp_id_sym; fprintf(file,"%s conflict arbitrators\n", HSIS_COMMENT); retval = st_init_table(strcmp, st_strhash); gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { if ((id_sym->flags & InPort) && !(id_sym->flags & OutPort)) continue; if (!vl_currentPrimitive && !vl_currentFunction) { if (strstr(key,SEP_LATCH)) continue; if (strstr(key,SEP_QUASI)) continue; } if (!vl_currentPrimitive && !vl_currentFunction) if (dflow_analysis && !(id_sym->flags & OutPort) && !(id_sym->flags & InPort) && !(str_matchtail(id_sym->name,SEP_LATCH)) && !set_find(id_sym->name, vl_currentModule->uninit_set)) continue; if (!(id_sym->flags & RegVar) && !str_matchtail(id_sym->name,SEP_LATCH)) { create_wire_nondeterminism(file, key, id_sym, vars_array); continue; } if (!vl_currentPrimitive && !vl_currentFunction) if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, id_sym->name, (char**)&temp_id_sym) && !st_lookup(vl_currentModule->seqVar_st, id_sym->name, (char**)&temp_id_sym)){ create_wire_nondeterminism(file, key, id_sym, vars_array); continue; } } controls = array_alloc(vl_term*, 0); num_changer = 0; for (i=0; iflags &MVar) { create_mvar_nondeterminism(file, retval, key, id_sym, lo, hi, controls, vars_array); } else { if (lo > hi) { create_bin_scalar_nondeterminism(file, retval, key, id_sym, controls, vars_array); } else { create_bin_vector_nondeterminism(file, retval, key, id_sym, lo, hi, controls, vars_array); } } } st_free_gen(gen); return retval; } st_table *func_conflict_arbitrator(FILE *file, vl_id_range *out_id_sym, array_t *vars_array) { st_generator *gen; st_table *retval; char *key; int old_flags; vl_id_range *id_sym, *temp_id_sym; blif_latch *latch; fprintf(file,"%s conflict arbitrators\n", HSIS_COMMENT); retval = st_init_table(strcmp, st_strhash); gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { if (id_sym->flags & InPort) continue; if (!vl_currentPrimitive && !vl_currentFunction) if (st_lookup(vl_currentModule->latch_st, key, (char**)&latch) || strstr(key,SEP_LATCH)) continue; if (!vl_currentPrimitive && !vl_currentFunction) if (dflow_analysis && !(id_sym->flags & OutPort) && !(id_sym->flags & InPort) && !(str_matchtail(id_sym->name,SEP_LATCH)) && !set_find(id_sym->name, vl_currentModule->uninit_set)) continue; if (!(id_sym->flags & RegVar) && !str_matchtail(id_sym->name,SEP_LATCH)) { create_wire_nondeterminism(file, key, id_sym, vars_array); continue; } if (!vl_currentPrimitive && !vl_currentFunction) if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, id_sym->name, (char**)&temp_id_sym)){ create_wire_nondeterminism(file, key, id_sym, vars_array); continue; } } if (vl_currentFunction && strcmp(out_id_sym->name, key)) continue; else { old_flags = id_sym->flags; id_sym->flags &= ~RegVar; create_wire_nondeterminism(file, key, id_sym, vars_array); id_sym->flags = old_flags; } } st_free_gen(gen); return retval; } static void vl_write_initial_generator(FILE *file) { char buf[MAXSTRLEN]; if (ith_module!=0) return; if (!use_rst_ckt) return; sprintf(buf, "%s%s", Initial_Signal->name->name, "_PS"); fprintf(file, ".r %s\n1\n", Initial_Signal->name->name); fprintf(file, ".names %s\n", buf); fprintf(file, "0\n"); fprintf(file, ".latch %s %s\n", buf, Initial_Signal->name->name); } static void vl_write_encoding(FILE *file) { st_generator *id_gen, *symbolic_gen; char *key, *symbolic_value, *code; vl_id_range *id_sym; int hi, lo, v; int idx, idx_lo, idx_hi; int i; if (!do_encoding) return; id_gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(id_gen, &key, (char**)&id_sym)) { if (id_sym->symbolic_values) { if (!st_count(id_sym->symbolic_values)) continue; if (!(id_sym->flags & MVar)) { get_hilo(id_sym, &hi, &lo); if (lo < hi) { if (!id_sym->range) { fprintf(file, ".encode "); for (i=lo; i<=hi; i++) fprintf(file, "%s%s%d%s ", id_sym->name, SEP_LBITSELECT, i, SEP_RBITSELECT); fprintf(file, "%s\n", id_sym->name); symbolic_gen = st_init_gen(id_sym->symbolic_values); while (st_gen(symbolic_gen, &symbolic_value, &code)) { for (i=lo, v=atoi(code); i<=hi; i++, v >>= 1) fprintf(file, "%d ", v&1); fprintf(file, "%s\n", symbolic_value); } st_free_gen(symbolic_gen); fprintf(file, ".endcode\n\n"); } else { idx_lo = vl_eval_expr(id_sym->range->left); if (id_sym->range->right) idx_hi = vl_eval_expr(id_sym->range->right); else idx_hi = idx_lo; for (idx=idx_lo; idx<=idx_hi; idx++) { fprintf(file, ".encode "); for (i=lo; i<=hi; i++) fprintf(file, "%s%s%d%s%s%d%s ", id_sym->name, SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, i, SEP_RBITSELECT); fprintf(file, "%s%s%d%s\n", id_sym->name, SEP_LARRAY, idx, SEP_RARRAY); symbolic_gen = st_init_gen(id_sym->symbolic_values); while (st_gen(symbolic_gen, &symbolic_value, &code)) { for (i=lo, v=atoi(code); i<=hi; i++, v >>= 1) fprintf(file, "%d ", v&1); fprintf(file, "%s\n", symbolic_value); } st_free_gen(symbolic_gen); fprintf(file, ".endcode\n\n"); } } } } } } st_free_gen(id_gen); } static void non_block_assignment(FILE *file, st_table *vars) { st_generator *gen; lsList ripple=(lsList)0; char *key; char latch_name[MAXSTRLEN]; char *dc; vl_id_range *id_sym, *orig_id_sym; var_info *id_var; vl_term *out_term; vl_term *procedural_ctrl, *procedural_term; int n_entries, hi, lo; int non_block_wire = 0; fprintf(file, "%s non-blocking assignments %s\n", HSIS_COMMENT, (rst_ckt)?"for initial":""); gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { non_block_wire = 0; ripple = (lsList)0; procedural_ctrl = NIL(vl_term); procedural_term = NIL(vl_term); if (!strstr(key,SEP_LATCH)) continue; if (!rst_ckt && lsLength(id_sym->syndrome_expr_list)==0) continue; if (rst_ckt && lsLength(id_sym->rst_syndrome_expr_list)==0) continue; strcpy(latch_name, id_sym->name); strip_char(latch_name, SEP_LATCH); if (rst_ckt && !st_lookup(vars, latch_name, (char**)&id_var) && !st_lookup(vars, key, (char**)&id_var)) continue; if (st_lookup(vars, latch_name, (char**)&id_var)) { if (id_var->extra) { procedural_ctrl = array_or(file, (array_t*)(id_var->extra)); procedural_term = id_var->current_terminal; decomposeTable = 1; } } if (st_lookup(vl_currentModule->sig_st, latch_name, (char**)&orig_id_sym)) { vl_id_range *temp_id_sym; if (!(orig_id_sym->flags&RegVar)) non_block_wire = 1; if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, latch_name, (char**)&temp_id_sym)) { non_block_wire = 1; } } } n_entries = lsLength((!rst_ckt)? id_sym->syndrome_expr_list: id_sym->rst_syndrome_expr_list); get_hilo(id_sym, &hi, &lo); out_term = new_term(id_sym->range, lo, hi); out_term->flag = id_sym->flags; out_term->term_type = id_sym->id_type; out_term->name->unintType = id_sym->unintType; write_var_decl(file, out_term); dc = check_dc((!rst_ckt)?id_sym->syndrome_expr_list: id_sym->rst_syndrome_expr_list); if ((id_sym->flags & MVar) || (lo > hi)) { if (!id_sym->range) { put_nblock_scalar_simple_table(file, dc, id_sym, non_block_wire, latch_name, out_term, n_entries, lo, hi, ripple, procedural_ctrl, procedural_term); } else { put_nblock_scalar_array_table(file, dc, id_sym, non_block_wire, latch_name, out_term, n_entries, lo, hi, ripple); } } else { put_nblock_vector_table(file, dc, id_sym, non_block_wire, latch_name, out_term, n_entries, lo, hi, &ripple, procedural_ctrl, procedural_term); } st_insert(vars, key, (char*)create_var_info(vl_copy_id_range(id_sym), out_term)); vl_chk_free(dc); } st_free_gen(gen); } static void quasi_cont_assignment(FILE *file) { st_generator *gen; char *key; vl_id_range *id_sym; char quasi_name[MAXSTRLEN]; char sync_name[MAXSTRLEN]; char *dc; int n_entries, hi, lo; vl_term *out_term; fprintf(file, "%s quasi-continuous assignment\n", HSIS_COMMENT); gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { if (!strstr(key,SEP_QUASI)) continue; if (!rst_ckt && lsLength(id_sym->syndrome_expr_list) == 0) continue; if (rst_ckt && lsLength(id_sym->rst_syndrome_expr_list) == 0) continue; strcpy(quasi_name, id_sym->name); strip_char(quasi_name, SEP_QUASI); get_hilo(id_sym, &hi, &lo); out_term = new_term(id_sym->range, lo, hi); out_term->flag = id_sym->flags; out_term->term_type = id_sym->id_type; vl_chk_free(out_term->name->name); out_term->name->name = strip_char(vlStrdup(id_sym->name),SEP_QUASI); dc = check_dc((!rst_ckt)?id_sym->syndrome_expr_list: id_sym->rst_syndrome_expr_list); n_entries = lsLength((!rst_ckt)? id_sym->syndrome_expr_list: id_sym->rst_syndrome_expr_list); sprintf(sync_name, "%s%s%s", quasi_name, SEP_GATEPIN, PIN_PS); put_quasi_table(file, dc, quasi_name, sync_name, id_sym, out_term, lo, hi, n_entries); vl_chk_free(dc); } st_free_gen(gen); } static void vl_prioritize_sequence(FILE *file, lsList vars_list, lsList pause_list, st_table *result_st) { st_generator *vars_gen; lsGen gen, pause_gen, pt_gen; lsHandle handle, pause_handle, pt_handle; lsList pt_list; vl_id_range *id_sym; char *key; st_table *new_vars, *pause_set; st_table *t_set, *i_set; var_info *id_var_info; int touched; vl_term *pause_term, *new_term; int hi, lo, i, j, k; int bit, idx; int table_width=0; int t_dup=0, val; char header_buf[MAXSTRLEN], buf[MAXSTRLEN], var_buf[MAXSTRLEN]; char *t_name; assert(lsLength(vars_list) == lsLength(pause_list)); if (lsLength(vars_list) == 0) return; fprintf(file, "%s sequence prioritizer\n", HSIS_COMMENT); vars_gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(vars_gen, &key, (char**)&id_sym)) { table_width = 0; for (gen=lsStart(vars_list), touched = 0; lsNext(gen,(lsGeneric*)&new_vars,&handle) != LS_NOMORE; ) { if (st_lookup(new_vars, key, (char**)&id_var_info)) { touched = 1; break; } } (void)lsFinish(gen); if (!touched) continue; get_hilo(id_sym, &hi, &lo); new_term = typed_new_term(id_sym->id_type, id_sym->range, lo, hi); new_term->flag |= (id_sym->flags & MVar) ? MVar : 0; write_var_decl(file, new_term); t_set = st_init_table(strcmp, st_strhash); i_set = st_init_table(st_ptrcmp, st_ptrhash); sprintf(header_buf, ".names "); pt_list = lsCreate(); for (gen=lsStart(vars_list), pause_gen=lsStart(pause_list), i=0; lsNext(gen,(lsGeneric*)&new_vars,&handle) != LS_NOMORE&& lsNext(pause_gen,(lsGeneric*)&pause_set,&pause_handle) != LS_NOMORE; ) { if (st_lookup(new_vars, key, (char**)&id_var_info)) { table_width++; pause_term = fg_write_lc_in_LabelSet(file, pause_set, 1); lsNewEnd(pt_list, (lsGeneric)pause_term, 0); t_dup=0; if (st_lookup(t_set, id_var_info->current_terminal->name->name, &t_name)) { st_insert(i_set, (char*)i, 0); t_dup=1; } else { st_insert(t_set, id_var_info->current_terminal->name->name, 0); } i++; new_term->flag |= id_var_info->current_terminal->flag; } } (void)lsFinish(gen); (void)lsFinish(pause_gen); sprintf(var_buf, "%s", id_sym->name); strip_char(var_buf, SEP_LATCH); if (!id_sym->range) { if (lo > hi || id_sym->flags &MVar) { sprintf(buf, "%s\n", new_term->name->name); strcat(header_buf, buf); sprintf(buf, "%s -\n", HSIS_DEFAULT); strcat(header_buf, buf); } else { sprintf(buf, "%s ", HSIS_ARROW); strcat(header_buf, buf); for (bit=lo; bit<=hi; bit++) { sprintf(buf, "%s%s%d%s ", new_term->name->name, SEP_LBITSELECT, bit, SEP_RBITSELECT); strcat(header_buf, buf); } strcat(header_buf, "\n"); sprintf(buf, "%s ", HSIS_DEFAULT); strcat(header_buf, buf); for (bit=lo; bit<=hi; bit++) { sprintf(buf, "- "); strcat(header_buf, buf); } strcat(header_buf, "\n"); } } else { int idx_hi, idx_lo; idx_lo = vl_eval_expr(id_sym->range->left); if (id_sym->range->right) idx_hi = vl_eval_expr(id_sym->range->right); else idx_hi = idx_lo; sprintf(buf, "%s ", HSIS_ARROW); strcat(header_buf, buf); for (idx=idx_lo; idx<=idx_hi; idx++) { if (lo > hi || id_sym->flags &MVar) { sprintf(buf, "%s%s%d%s ", new_term->name->name, SEP_LARRAY, idx, SEP_RARRAY); strcat(header_buf, buf); } else { for (bit=lo; bit<=hi; bit++) { sprintf(buf, "%s%s%d%s%s%d%s ", new_term->name->name, SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, bit, SEP_RBITSELECT); strcat(header_buf, buf); } } } strcat(header_buf, "\n"); sprintf(buf, "%s ", HSIS_DEFAULT); strcat(header_buf, buf); for (idx=idx_lo; idx<=idx_hi; idx++) { if (lo > hi || id_sym->flags & MVar) { sprintf(buf, "- "); strcat(header_buf, buf); } else { for (bit=lo; bit<=hi; bit++) { sprintf(buf, "- "); strcat(header_buf, buf); } } } } fprintf(file, "%s", header_buf); for (gen=lsStart(vars_list), pause_gen=lsStart(pause_list), pt_gen=lsStart(pt_list), i=0; lsNext(gen,(lsGeneric*)&new_vars,&handle) != LS_NOMORE&& lsNext(pause_gen,(lsGeneric*)&pause_set,&pause_handle) != LS_NOMORE; ) { if (st_lookup(new_vars, key, (char**)&id_var_info)) { int retval = lsNext(pt_gen,(lsGeneric*)&pause_term,&pt_handle); assert(retval != LS_NOMORE); if (!id_sym->range) { if (lo > hi || id_sym->flags & MVar) { for (j=0; jcurrent_terminal->name->name); i++; } else { for (j=0; j current_terminal->name->name, SEP_LBITSELECT, k, SEP_RBITSELECT); fprintf(file, "\n"); i++; } } else { int idx_hi, idx_lo; idx_lo = vl_eval_expr(id_sym->range->left); if (id_sym->range->right) idx_hi = vl_eval_expr(id_sym->range->right); else idx_hi = idx_lo; if (lo > hi || id_sym->flags & MVar) { for (j=0; jcurrent_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY); i++; } else { for (j=0; jcurrent_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, k, SEP_RBITSELECT); i++; } } } } (void)lsFinish(gen); (void)lsFinish(pause_gen); (void)lsFinish(pt_gen); st_insert(result_st, id_sym->name, (char*)create_var_info(vl_copy_id_range(id_sym), new_term)); } st_free_gen(vars_gen); } static void vl_register_pause(vertex_t *pause_node, st_table *old_vars) { set_t *pause_set; pause_set = set_empty(); set_add(((fg_node_info*)pause_node->user_data)->loc, pause_set); lsNewEnd(vl_current_pause_list, (lsGeneric)pause_set, 0); lsNewEnd(vl_current_vars_list, (lsGeneric)old_vars, 0); } static void vl_predefine_vars(FILE *file, st_table *vars) { st_generator *gen; char *key; vl_id_range *id_sym; vl_term *init_term; int hi, lo; var_info *id_var; char *dummy; gen = st_init_gen(vl_currentModule->sig_st); while (st_gen(gen, &key, (char**)&id_sym)) { if (!(id_sym->flags & RegVar)) continue; if (strstr(id_sym->name, SEP_LATCH)) continue; if (strstr(id_sym->name, SEP_QUASI)) continue; if (vl_currentModule_combVar_st) if (st_lookup(vl_currentModule_combVar_st, id_sym->name, &dummy)) continue; get_hilo(id_sym, &hi, &lo); init_term = typed_new_term(id_sym->id_type, id_sym->range, lo, hi); init_term->flag = id_sym->flags; id_var = create_var_info(vl_copy_id_range(id_sym), init_term); st_insert(vars, id_sym->name, (char*)id_var); id_var = create_var_info(vl_copy_id_range(id_sym), init_term); st_insert(vl_current_init_vars, id_sym->name, (char*)id_var); } st_free_gen(gen); } static void vl_timed_init_mux(FILE *file, vl_term *ctrl_term, st_table *orig_vars, st_table *init_vars, st_table *feedback_vars) { st_generator *gen; char *key; var_info *init_var, *feedback_var, *orig_var; vl_term *orig_term=NIL(vl_term); int hi, lo; char *buf; int use_defined_term=0; fprintf(file, "%s feedback mux\n", HSIS_COMMENT); gen = st_init_gen(init_vars); while (st_gen(gen, &key, (char**)&init_var)) { use_defined_term=0; if (orig_vars) { if (st_lookup(orig_vars, key, (char**)&orig_var)) { orig_term = orig_var->current_terminal; use_defined_term=1; } } if (!use_defined_term) { get_hilo(init_var->id, &hi, &lo); buf = vlStrdup(init_var->id->name); orig_term = ((init_var->id->flags & EventVar) && smartEvent) ? vl_create_term(vl_create_id_range(WRT_BLIF_GND(file), NIL(vl_range)), 0, -1) : create_rename_term(init_var->id, buf, lo, hi); orig_term->flag = init_var->current_terminal->flag; write_var_decl(file, init_var->current_terminal); } if (st_lookup(feedback_vars, key, (char**)&feedback_var)) { instantiate_mux(file, orig_term, feedback_var->current_terminal, ctrl_term, init_var->current_terminal); } else { if (orig_term->flag & MVar) vl_write_mv_connect(file, orig_term, init_var->current_terminal); else { if ((init_var->id->flags & EventVar) && smartEvent) write_int_connect(file, 0, init_var->current_terminal); else vl_write_bin_connect(file, orig_term, init_var->current_terminal, 0); } } } st_free_gen(gen); } vl_term *test_against_lc_init(FILE *file) { vl_term *retval; retval = new_term(NIL(vl_range), 0, -1); fprintf(file, ".names %s%06x %s\n%s 0\n%s%d%s 1\n", FG_LC_PS,((fg_graph_info*)vl_writeFlowGraph->user_data)->fg_id, retval->name->name, HSIS_DEFAULT, FG_LLOC, 0, FG_RLOC); return retval; } static void vl_write_timer(FILE *file, lsList graph_list) { lsGen gen; lsHandle handle; graph_t *graph; fg_graph_info *gdata; int i; for (gen=lsStart(graph_list); lsNext(gen, (lsGeneric*)&graph, &handle) != LS_NOMORE; ) { if (vl_preDeclare) { gdata = ((fg_graph_info*)graph->user_data); if (gdata->fg_id == -1) { fg_new_fg_id(); gdata->fg_id = fg_fg_id(); } 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); continue; } if (graph) { if (!fg_check_timer_consistency(file, graph)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s: contains delay free cycle(s)", vl_currentModule->name->name); fprintf(stderr, "%s\n", buf); } fg_set_fg(graph); fg_write_timer(file, graph); fg_set_fg(NIL(graph_t)); } } lsFinish(gen); } FILE *openStream() { return tmpfile(); } void closeStream(FILE *stream) { fclose(stream); } void dumpStream(FILE *to, FILE *from) { char buf[MAXSTRLEN]; rewind(from); while(fgets(buf, MAXSTRLEN, from)!=NULL) fputs(buf, to); } char * cfsm_inputs(char *inputs) { int len, i; char arg[MAXSTRLEN]; char token[MAXSTRLEN]; char *cp; static char buf[MAXSTRLEN]; buf[0] = '\0'; len = strlen(inputs); for (cp=inputs; cp 0) { token[i] = '\0'; sprintf(arg, " %s=%s", token, token); strcat(buf, arg); } } return buf; } char *cfsm_ports(char *ports) { int len, i; char arg[MAXSTRLEN]; char token[MAXSTRLEN]; char *cp; static char buf[MAXSTRLEN]; int ithToken; buf[0] = '\0'; len = strlen(ports); ithToken=0; for (cp=ports; cp 0) { token[i] = '\0'; if (ithToken > 0) sprintf(arg, " , %s", token); else sprintf(arg, " %s", token); strcat(buf, arg); ithToken++; } } return buf; } FILE *vl_begin_buffer() { return tmpfile(); } void vl_close_buffer(FILE *buffer) { fclose(buffer); } void vl_append_buffer(FILE *main_stream, FILE *buffer) { char buf[MAXSTRLEN]; rewind(buffer); while(fgets(buf, MAXSTRLEN, buffer)!=NULL) fputs(buf, main_stream); }