void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t net_const) { ivl_scope_t const_scope = ivl_const_scope(net_const); unsigned idx, count, lineno; const char *file; count = ivl_scope_params(const_scope); file = ivl_const_file(net_const); lineno = ivl_const_lineno(net_const); /* Look to see if the constant matches a parameter in its scope. */ for (idx = 0; idx < count; idx += 1) { ivl_parameter_t par = ivl_scope_param(const_scope, idx); if (lineno != ivl_parameter_lineno(par)) continue; if (strcmp(file, ivl_parameter_file(par)) == 0) { /* Check that the appropriate expression bits match the * original parameter bits. */ // HERE: Verify that the values match and then print the name. // Does this work with out of scope references? Check real parameters. emit_id(ivl_parameter_basename(par)); return; } } /* If the scopes don't match then we assume this is an empty port. */ if (const_scope != scope) { /* This constant could really be from an input port. */ if (emit_as_input(scope, net_const)) return; fprintf(vlog_out, "/* Empty */"); return; } switch (ivl_const_type(net_const)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: emit_number(ivl_const_bits(net_const), ivl_const_width(net_const), ivl_const_signed(net_const), ivl_const_file(net_const), ivl_const_lineno(net_const)); break; case IVL_VT_STRING: emit_number_as_string(net_const); break; case IVL_VT_REAL: emit_real_number(ivl_const_real(net_const)); break; default: fprintf(vlog_out, "<invalid>"); fprintf(stderr, "%s:%u: vlog95 error: Unknown constant type " "(%d).\n", ivl_const_file(net_const), ivl_const_lineno(net_const), (int)ivl_const_type(net_const)); vlog_errors += 1; break; } }
static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr) { unsigned idx, count, lineno; const char *file; count = ivl_scope_params(scope); file = ivl_expr_file(expr); lineno = ivl_expr_lineno(expr); for (idx = 0; idx < count; idx += 1) { ivl_parameter_t par = ivl_scope_param(scope, idx); if (lineno != ivl_parameter_lineno(par)) continue; if (strcmp(file, ivl_parameter_file(par)) == 0) { /* Check that the appropriate expression bits match the * original parameter bits. */ ivl_expr_t pex = ivl_parameter_expr(par); unsigned wid = ivl_expr_width(expr); unsigned param_wid = ivl_expr_width(pex); const char *my_bits = ivl_expr_bits(expr); const char *param_bits = ivl_expr_bits(pex); unsigned bit; if (param_wid < wid) wid = param_wid; for (bit = 0; bit < wid; bit += 1) { if (my_bits[bit] != param_bits[bit]) { fprintf(stderr, "%s:%u: vlog95 error: Constant " "expression bits do not match " "parameter bits.\n", ivl_expr_file(expr), ivl_expr_lineno(expr)); break; } } // HERE: Does this work with an out of scope parameter reference? // What about real parameters? emit_id(ivl_parameter_basename(par)); return 1; } } return 0; }
int draw_scope(ivl_scope_t net, ivl_scope_t parent) { unsigned idx; const char *type; const char*prefix = ivl_scope_is_auto(net) ? "auto" : ""; switch (ivl_scope_type(net)) { case IVL_SCT_MODULE: type = "module"; break; case IVL_SCT_FUNCTION: type = "function"; break; case IVL_SCT_TASK: type = "task"; break; case IVL_SCT_BEGIN: type = "begin"; break; case IVL_SCT_FORK: type = "fork"; break; case IVL_SCT_GENERATE: type = "generate"; break; default: type = "?"; assert(0); } fprintf(vvp_out, "S_%p .scope %s%s, \"%s\" \"%s\" %d %d", net, prefix, type, vvp_mangle_name(ivl_scope_basename(net)), ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)), ivl_scope_lineno(net)); if (parent) { fprintf(vvp_out, ", %d %d, S_%p;\n", ivl_file_table_index(ivl_scope_def_file(net)), ivl_scope_def_lineno(net), parent); } else { fprintf(vvp_out, ";\n"); } fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net), ivl_scope_time_precision(net)); for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) { ivl_parameter_t par = ivl_scope_param(net, idx); ivl_expr_t pex = ivl_parameter_expr(par); switch (ivl_expr_type(pex)) { case IVL_EX_STRING: fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), ivl_expr_string(pex)); break; case IVL_EX_NUMBER: fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), ivl_expr_signed(pex)? "+":""); { const char*bits = ivl_expr_bits(pex); unsigned nbits = ivl_expr_width(pex); unsigned bb; for (bb = 0 ; bb < nbits; bb += 1) fprintf(vvp_out, "%c", bits[nbits-bb-1]); } fprintf(vvp_out, ">;\n"); break; case IVL_EX_REALNUM: fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), draw_Cr_to_string(ivl_expr_dvalue(pex)), ivl_expr_dvalue(pex)); break; default: fprintf(vvp_out, "; parameter type %d unsupported\n", ivl_expr_type(pex)); break; } } /* Scan the scope for logic devices. For each device, draw out a functor that connects pin 0 to the output, and the remaining pins to inputs. */ for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) { ivl_net_logic_t lptr = ivl_scope_log(net, idx); draw_logic_in_scope(lptr); } /* Scan the signals (reg and net) and draw the appropriate statements to make the signal function. */ for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) { ivl_signal_t sig = ivl_scope_sig(net, idx); switch (ivl_signal_type(sig)) { case IVL_SIT_REG: draw_reg_in_scope(sig); break; default: draw_net_in_scope(sig); break; } } for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) { ivl_event_t event = ivl_scope_event(net, idx); draw_event_in_scope(event); } for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) { ivl_lpm_t lpm = ivl_scope_lpm(net, idx); draw_lpm_in_scope(lpm); } for (idx = 0 ; idx < ivl_scope_switches(net) ; idx += 1) { ivl_switch_t sw = ivl_scope_switch(net, idx); draw_switch_in_scope(sw); } if (ivl_scope_type(net) == IVL_SCT_TASK) draw_task_definition(net); if (ivl_scope_type(net) == IVL_SCT_FUNCTION) draw_func_definition(net); ivl_scope_children(net, (ivl_scope_f*) draw_scope, net); return 0; }