/* Copyright (c) 1992, 1993 Regents of the University of California All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. However, any distribution of this software or derivative works must include the above copyright notice. This software is made available AS IS, and neither the Electronics Research Laboratory or the Universify of California make any warranty about the software, its performance or its conformity to any specification. Author: Szu-Tsung Cheng, stcheng@ic.Berkeley.EDU 10/92 10/93 $Header: /projects/development/hsv/CVSRepository/vl2mv/src/parser/vl_latch.c,v 1.2 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 "vl_types.h" #include "vl_defs.h" #include "vlr_int.h" #include "vl_fg_defs.h" #include "vl_create.h" #include "vl_write.h" #include "vl_write_util.h" #include "vl_vardecl.h" #include "vl_mux.h" #include "verilog.h" extern int dumpSyncCkt; extern int set_notation; extern int smartEvent; extern int implicitClocking; extern vl_desc *mod_list; extern char *sync_assign(); static void check_comb_reduction ARGS((vl_id_range *id_sym)); void instantiate_mvar_latch(FILE *file, int non_block_var, int mark_sel_var, int lo, int hi, vl_id_range *id_sym, vl_id_range *orig_id_sym, var_info *lhsvar, char *lname) { int idx, idx_lo, idx_hi; lsList domain; lsGen enum_gen; lsHandle enum_handle; vl_enumerator *enum_elt; vl_id_range *temp_id_sym; vl_term *feed_back_array; int old_id_type; st_table *sensitiveList; int dummy; old_id_type = orig_id_sym->flags; domain = id_sym->id_type->specifier->u.enum_type->domain_list; if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, orig_id_sym->name, (char**)&temp_id_sym) && !st_lookup(vl_currentModule->seqVar_st, orig_id_sym->name, (char**)&temp_id_sym)) { orig_id_sym->flags &= ~RegVar; } else { check_comb_reduction(orig_id_sym); } } sensitiveList = NIL(st_table); if(!id_sym->range) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; char buf[MAXSTRLEN]; sprintf(buf, "%s%s", id_sym->name, PIN_FEEDBACK); feed_back = create_rename_term(id_sym, buf, 0, -1); feed_back->term_type = id_sym->id_type; instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back->name, lname, 0, -1)); fprintf(file, "%s %s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), feed_back->name->name); vl_free_term(feed_back); } else { if (!implicitClocking && orig_id_sym->edge_trigger) { vl_term *feed_back, *new_terminal; feed_back = vl_create_term(orig_id_sym, 0, -1); new_terminal = typed_new_term(orig_id_sym->id_type, orig_id_sym->range, 0, -1); feed_back->flag |= lhsvar->current_terminal->flag; new_terminal->flag |= lhsvar->current_terminal->flag; write_mvar_decl(file, new_terminal); instantiate_mux(file, lhsvar->current_terminal, feed_back, orig_id_sym->edge_trigger, new_terminal); lhsvar->current_terminal = new_terminal; } fprintf(file, "%s %s %s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH)); if (st_lookup(vl_currentModule->quasi_st,lname,(char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); if (!(orig_id_sym->flags&RegVar)) { if (set_notation) { fprintf(file, "- %s%s\n", HSIS_EQUAL, lhsvar->current_terminal->name->name); } else { for (enum_gen=lsStart(domain); lsNext(enum_gen, (lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s %s\n", enum_elt->name,enum_elt->name); } lsFinish(enum_gen); } } else if (non_block_var && mark_sel_var) { fprintf(file, ".names %s \n", lname); fprintf(file, "%s\n", strip_char(lname,SEP_SEL_VAR)); for (enum_gen=lsStart(domain); lsNext(enum_gen, (lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s %s\n", enum_elt->name, enum_elt->name); } lsFinish(enum_gen); } } } else { char buf[MAXSTRLEN]; 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%s", id_sym->name, PIN_FEEDBACK); feed_back_array = create_rename_term(id_sym, buf, 0, -1); for (idx=idx_lo; idx<=idx_hi; idx++) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; sprintf(buf, "%s%s%d%s", feed_back_array->name->name, SEP_LARRAY, idx, SEP_RARRAY); feed_back = create_rename_term(feed_back_array->name, buf, 0, -1); sprintf(buf, "%s%s%d%s", lname, SEP_LARRAY, idx, SEP_RARRAY); instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back_array->name, buf, 0, -1)); fprintf(file, "%s %s%s%d%s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY, feed_back->name->name); vl_free_term(feed_back); } else { if (!implicitClocking && orig_id_sym->edge_trigger) { vl_term *feed_back, *new_terminal; feed_back = vl_create_term(orig_id_sym, 0, -1); new_terminal = typed_new_term(orig_id_sym->id_type, orig_id_sym->range, 0, -1); instantiate_mux(file, lhsvar->current_terminal, feed_back, orig_id_sym->edge_trigger, new_terminal); lhsvar->current_terminal = new_terminal; } fprintf(file, "%s %s%s%d%s %s%s%d%s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY); if (st_lookup(vl_currentModule->quasi_st, lname,(char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); if (!(orig_id_sym->flags&RegVar)) { if (set_notation) { fprintf(file, "- %s%s%s%d%s\n", HSIS_EQUAL, lhsvar->current_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY); } else { for (enum_gen=lsStart(domain); lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s %s\n", enum_elt->name, enum_elt->name); } lsFinish(enum_gen); } } else if (non_block_var && mark_sel_var) { fprintf(file, ".names %s%s%d%s ", lname, SEP_LARRAY, idx, SEP_RARRAY); fprintf(file, "%s%s%d%s\n", strip_char(lname,SEP_SEL_VAR), SEP_LARRAY, idx, SEP_RARRAY); for (enum_gen=lsStart(domain); lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!= LS_NOMORE;) { fprintf(file, "%s %s\n", enum_elt->name, enum_elt->name); } lsFinish(enum_gen); } } } } orig_id_sym->flags = old_id_type; lo = lo; hi = hi; } void instantiate_bin_scalar_latch(FILE *file, int non_block_var, int mark_sel_var, vl_id_range *id_sym, vl_id_range *orig_id_sym, var_info *lhsvar, char *lname) { int i; int modify_id_flag = 0; int idx, idx_lo, idx_hi; vl_id_range *temp_id_sym; int old_id_type=0; vl_term *feed_back_array; st_table *sensitiveList; int dummy; if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, orig_id_sym->name, (char**)&temp_id_sym) && !st_lookup(vl_currentModule->seqVar_st, orig_id_sym->name, (char**)&temp_id_sym)) { modify_id_flag = 1; old_id_type = orig_id_sym->flags; orig_id_sym->flags &= ~RegVar; } else { check_comb_reduction(orig_id_sym); } } sensitiveList = NIL(st_table); if (!id_sym->range) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; char buf[MAXSTRLEN]; sprintf(buf, "%s", id_sym->name); feed_back = create_rename_term(id_sym, buf, 0, -1); instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back->name, lname, 0, -1)); fprintf(file, "%s %s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), feed_back->name->name); vl_free_term(feed_back); } else { if (!implicitClocking && orig_id_sym->edge_trigger) { vl_term *feed_back, *new_terminal; feed_back = vl_create_term(orig_id_sym, 0, -1); new_terminal = typed_new_term(orig_id_sym->id_type, orig_id_sym->range, 0, -1); instantiate_mux(file, lhsvar->current_terminal, feed_back, orig_id_sym->edge_trigger, new_terminal); lhsvar->current_terminal = new_terminal; } if (id_sym->flags & EventVar) { vl_write_bit_connect(file, lhsvar->current_terminal->name->name, lname, 0); if (!smartEvent) fprintf(file, ".latch %s %s%s%s\n", lname, lname, SEP_GATEPIN, PIN_EVENT); } else { fprintf(file, "%s %s %s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH)); if (st_lookup(vl_currentModule->quasi_st, lname, (char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); } if (!(orig_id_sym->flags&RegVar)) { fprintf(file, "1 1\n0 0\n"); } else if (non_block_var && mark_sel_var) { fprintf(file, ".names %s ", lname); fprintf(file, "%s\n", strip_char(lname,SEP_SEL_VAR)); for (i=0; i<=1; i++) { fprintf(file, "%d %d\n", i, i); } } } } else { char buf[MAXSTRLEN]; 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%s", id_sym->name, PIN_FEEDBACK); feed_back_array = create_rename_term(id_sym, buf, 0, -1); for (idx=idx_lo; idx<=idx_hi; idx++) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; sprintf(buf, "%s%s%s%d%s", feed_back_array->name->name, PIN_FEEDBACK, SEP_LARRAY, idx, SEP_RARRAY); feed_back = create_rename_term(feed_back_array->name, buf, 0, -1); sprintf(buf, "%s%s%d%s", lname, SEP_LARRAY, idx, SEP_RARRAY); instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back_array->name, buf, 0, -1)); fprintf(file, "%s %s%s%d%s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY, feed_back->name->name); vl_free_term(feed_back); } else { if (!implicitClocking && orig_id_sym->edge_trigger) { vl_term *feed_back, *new_terminal; feed_back = vl_create_term(orig_id_sym, 0, -1); new_terminal = typed_new_term(orig_id_sym->id_type, orig_id_sym->range, 0, -1); instantiate_mux(file, lhsvar->current_terminal, feed_back, orig_id_sym->edge_trigger, new_terminal); lhsvar->current_terminal = new_terminal; } fprintf(file, "%s %s%s%d%s %s%s%d%s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY); if (st_lookup(vl_currentModule->quasi_st, lname,(char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); if (!(orig_id_sym->flags&RegVar)) { fprintf(file, "1 1\n0 0\n"); } else if (non_block_var && mark_sel_var) { fprintf(file, ".names %s%s%d%s ", lname, SEP_LARRAY, idx, SEP_RARRAY); fprintf(file, "%s%s%d%s\n", strip_char(lname,SEP_SEL_VAR), SEP_LARRAY, idx, SEP_RARRAY); for (i=0; i<=1; i++) { fprintf(file, "%d %d\n", i, i); } } } } } if (modify_id_flag) orig_id_sym->flags = old_id_type; } void instantiate_bin_vector_latch(FILE *file, int non_block_var, int mark_sel_var, int lo, int hi, vl_id_range *id_sym, vl_id_range *orig_id_sym, var_info *lhsvar, char *lname) { int i; int idx, idx_lo, idx_hi; int old_id_type=0; vl_id_range *temp_id_sym; vl_term *feed_back_array; st_table *sensitiveList; int need_recover_id_sym=0; int dummy; extern int combinationalReduction; if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, orig_id_sym->name, (char**)&temp_id_sym) && !st_lookup(vl_currentModule->seqVar_st, orig_id_sym->name, (char**)&temp_id_sym)) { old_id_type = orig_id_sym->flags; need_recover_id_sym = 1; orig_id_sym->flags &= ~RegVar; } else { check_comb_reduction(orig_id_sym); } } if (id_sym->syndrome_expr_list) if (lsLength(id_sym->syndrome_expr_list) == 0) if (id_sym->rst_syndrome_expr_list) if (lsLength(id_sym->rst_syndrome_expr_list) == 0) if (combinationalReduction) return; sensitiveList = NIL(st_table); if (orig_id_sym->flags & RegVar) { if (!sensitiveList) { if (!implicitClocking && orig_id_sym->edge_trigger) { vl_term *feed_back, *new_terminal; feed_back = vl_create_term(orig_id_sym, lo, hi); new_terminal = typed_new_term(orig_id_sym->id_type, orig_id_sym->range, lo, hi); instantiate_mux(file, lhsvar->current_terminal, feed_back, orig_id_sym->edge_trigger, new_terminal); lhsvar->current_terminal = new_terminal; } } } for (i=lo; i<=hi; i++) { if (!id_sym->range) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; char buf[MAXSTRLEN]; sprintf(buf, "%s%s", id_sym->name, PIN_FEEDBACK); feed_back = create_rename_term(id_sym, buf, lo, hi); instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back->name,lname, 0,-1)); fprintf(file, "%s %s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), feed_back->name->name); vl_free_term(feed_back); } else { fprintf(file, "%s %s%s%d%s %s%s%d%s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, SEP_LBITSELECT, i, SEP_RBITSELECT, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LBITSELECT, i, SEP_RBITSELECT); if (st_lookup(vl_currentModule->quasi_st, lname,(char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); if (!(orig_id_sym->flags&RegVar)) { fprintf(file, "1 1\n0 0\n"); } else if (non_block_var && mark_sel_var) { fprintf(file, ".names %s%s%d%s %s%s%d%s", lname, SEP_LBITSELECT, i, SEP_RBITSELECT, strip_char(lname, SEP_SEL_VAR), SEP_LBITSELECT, i, SEP_RBITSELECT); fprintf(file, "1 1\n0 0\n"); } } } else { char buf[MAXSTRLEN]; 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%s", id_sym->name, PIN_FEEDBACK); feed_back_array = create_rename_term(id_sym, buf, lo, hi); for (idx=idx_lo; idx<=idx_hi; idx++) { if (sensitiveList && (orig_id_sym->flags & RegVar)) { vl_term *feed_back; char buf[MAXSTRLEN]; sprintf(buf, "%s%s%d%s", feed_back_array->name->name, SEP_LARRAY, idx, SEP_RARRAY); feed_back = create_rename_term(feed_back_array->name, buf, lo, hi); sprintf(buf, "%s%s%d%s", lname, SEP_LARRAY, idx, SEP_RARRAY); instantiate_mux(file, lhsvar->current_terminal, feed_back, sensitive_control(file, sensitiveList), create_rename_term(feed_back_array->name,buf, lo, hi)); fprintf(file, "%s %s%s%d%s %s\n", ".latch", non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY, feed_back->name->name); vl_free_term(feed_back); } else { fprintf(file, "%s %s%s%d%s%s%d%s %s%s%d%s%s%d%s", (orig_id_sym->flags&RegVar)? ".latch":".names", lhsvar->current_terminal->name->name, SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, i, SEP_RBITSELECT, non_block_var? sel_var(strip_char(lname,SEP_LATCH)): strip_char(lname,SEP_LATCH), SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, i, SEP_RBITSELECT); if (st_lookup(vl_currentModule->quasi_st, lname,(char**)&dummy)) fprintf(file, "%s%s", SEP_GATEPIN, PIN_PS); fprintf(file, "\n"); if (!(orig_id_sym->flags&RegVar)) { fprintf(file, "1 1\n0 0\n"); } else if(non_block_var && mark_sel_var) { fprintf(file, ".names %s%s%d%s%s%d%s %s%s%d%s%s%d%s\n", lname, SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, i, SEP_RBITSELECT, strip_char(lname,SEP_SEL_VAR), SEP_LARRAY, idx, SEP_RARRAY, SEP_LBITSELECT, i, SEP_RBITSELECT); fprintf(file, "1 1\n0 0\n"); } } } } } if (need_recover_id_sym) orig_id_sym->flags = old_id_type; } static void check_comb_reduction(vl_id_range *id_sym) { char *dummy; char buf[MAXSTRLEN]; if (vl_currentModule->combVar_st) { if (st_lookup(vl_currentModule->combVar_st, id_sym->name, &dummy) && st_lookup(vl_currentModule->seqVar_st, id_sym->name, &dummy)) { sprintf(buf, "%s%s", id_sym->name, SEP_QUASI); if (!st_lookup(vl_currentModule->sig_st, buf, &dummy)) { sprintf(buf, "%s:'%s' is touched by both sequential/combinational ", vl_currentModule->name->name, id_sym->name); strcat(buf, "procedurarl blocks,\nhowever, combinational "); strcat(buf, "block is not assigning to that variable\n"); strcat(buf, "through quasi-assignment. Compilation abort"); yylineno = -1; compile_error(buf); } } } } char *sync_assign() { static char retval[MAXSTRLEN]; if (implicitClocking && vl_currentModule->clk && dumpSyncCkt) { if (vl_currentModule->clk->type == NegedgeEventExpr) sprintf(retval, "%s ( %s )", SMV_IF, vl_currentModule->clk->expr->u.name->name); else sprintf(retval, "%s ( %s%s )", SMV_IF, SMV_NOT, vl_currentModule->clk->expr->u.name->name); } else { sprintf(retval, "%s", SMV_ASSIGN); } return retval; }