/* * This function traverses the scope tree looking for the enclosing module * scope. When it is found the module scope is returned. */ ivl_scope_t get_module_scope(ivl_scope_t scope) { while (ivl_scope_type(scope) != IVL_SCT_MODULE) { ivl_scope_t pscope = ivl_scope_parent(scope); assert(pscope); scope = pscope; } return scope; }
/* * A user defined task call with arguments is generated as a block with * input assignments, a simple call and then output assignments. This is * handled by the is_utask_call_with_args() routine above. */ static void emit_stmt_utask(ivl_scope_t scope, ivl_statement_t stmt) { ivl_scope_t task_scope = ivl_stmt_call(stmt); assert(ivl_scope_type(task_scope) == IVL_SCT_TASK); assert(ivl_scope_ports(task_scope) == 0); fprintf(vlog_out, "%*c", get_indent(), ' '); emit_scope_path(scope, task_scope); fprintf(vlog_out, ";"); emit_stmt_file_line(stmt); fprintf(vlog_out, "\n"); }
static void emit_select_name(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) { /* A select of a number is really a parameter select. */ if (ivl_expr_type(expr) == IVL_EX_NUMBER) { /* Look in the current scope. */ if (emit_param_name_in_scope(scope, expr)) return; /* Now look in the enclosing module scope if this is not a * module scope. */ if (ivl_scope_type(scope) != IVL_SCT_MODULE) { if (emit_param_name_in_scope(get_module_scope(scope), expr)) return; } // HERE: For now we only look in the current and module scope for the // parameter that is being selected. We need to also look in other // scopes, but that involves a big search. fprintf(vlog_out, "<missing>"); fprintf(stderr, "%s:%u: vlog95 error: Unable to find parameter " "for select expression \n", ivl_expr_file(expr), ivl_expr_lineno(expr)); vlog_errors += 1; } else { emit_expr(scope, expr, wid); } }
int target_design(ivl_design_t des) { ivl_scope_t *roots; unsigned nroots, idx; unsigned has_root_scope = 0; const char*path = ivl_design_flag(des, "-o"); /* Set the indent spacing with the -pspacing flag passed to iverilog * (e.g. -pspacing=4). The default is 2 spaces. */ const char*spacing_str = ivl_design_flag(des, "spacing"); /* Use -pfileline to determine if file and line information is * printed for most lines. (e.g. -pfileline=1). The default is no * file/line information will be printed for individual lines. */ const char*fileline_str = ivl_design_flag(des, "fileline"); /* Use -pallowsigned to allow signed registers/nets and the * $signed() and $unsigned() system tasks as an extension. */ const char*allowsigned_str = ivl_design_flag(des, "allowsigned"); assert(path); /* Check for and use a provided indent spacing. */ if (strcmp(spacing_str, "") != 0) { char *eptr; long value = strtol(spacing_str, &eptr, 0); /* Nothing usable in the spacing string. */ if (spacing_str == eptr) { fprintf(stderr, "vlog95 error: Unable to extract spacing " "increment from string: %s\n", spacing_str); return 1; } /* Extra stuff at the end. */ if (*eptr != 0) { fprintf(stderr, "vlog95 error: Extra characters '%s' " "included at end of spacing string: %s\n", eptr, spacing_str); return 1; } /* The increment must be greater than zero. */ if (value < 1) { fprintf(stderr, "vlog95 error: Spacing increment (%ld) must " "be greater than zero.\n", value); return 1; } /* An increment of more than sixteen is too much. */ if (value > 16) { fprintf(stderr, "vlog95 error: Spacing increment (%ld) must " "be sixteen or less.\n", value); return 1; } indent_incr = value; } /* Check to see if file/line information should be printed. */ if (strcmp(fileline_str, "") != 0) { char *eptr; long value = strtol(fileline_str, &eptr, 0); /* Nothing usable in the file/line string. */ if (fileline_str == eptr) { fprintf(stderr, "vlog95 error: Unable to extract file/line " "information from string: %s\n", fileline_str); return 1; } /* Extra stuff at the end. */ if (*eptr != 0) { fprintf(stderr, "vlog95 error: Extra characters '%s' " "included at end of file/line string: %s\n", eptr, fileline_str); return 1; } /* The file/line flag must be positive. */ if (value < 0) { fprintf(stderr, "vlog95 error: File/line flag (%ld) must " "be positive.\n", value); return 1; } emit_file_line = value > 0; } /* Check to see if we should also print signed constructs. */ if (strcmp(allowsigned_str, "") != 0) { char *eptr; long value = strtol(allowsigned_str, &eptr, 0); /* Nothing usable in the allow signed string. */ if (allowsigned_str == eptr) { fprintf(stderr, "vlog95 error: Unable to extract allow " "signed information from string: %s\n", allowsigned_str); return 1; } /* Extra stuff at the end. */ if (*eptr != 0) { fprintf(stderr, "vlog95 error: Extra characters '%s' " "included at end of allow signed string: " "%s\n", eptr, allowsigned_str); return 1; } /* The allow signed flag must be positive. */ if (value < 0) { fprintf(stderr, "vlog95 error: Allow signed flag (%ld) must " "be positive.\n", value); return 1; } allow_signed = value > 0; } design = des; #ifdef HAVE_FOPEN64 vlog_out = fopen64(path, "w"); #else vlog_out = fopen(path, "w"); #endif if (vlog_out == 0) { perror(path); return -1; } fprintf(vlog_out, "/*\n"); fprintf(vlog_out, " * 1364-1995 Verilog generated by Icarus Verilog " "VLOG95 Code Generator,\n"); fprintf(vlog_out, " * Version: " VERSION " (" VERSION_TAG ")\n"); fprintf(vlog_out, " * Converted using %s delays and %s signed support.\n", ivl_design_delay_sel(des), allow_signed ? "with" : "without"); fprintf(vlog_out, " */\n"); sim_precision = ivl_design_time_precision(des); /* Get all the root modules and then convert each one. */ ivl_design_roots(des, &roots, &nroots); /* Emit any root scope tasks or functions first. */ for (idx = 0; idx < nroots; idx += 1) { switch(ivl_scope_type(roots[idx])) { case IVL_SCT_FUNCTION: case IVL_SCT_TASK: if (! has_root_scope) { fprintf(vlog_out, "module ivl_root_scope;\n"); indent += indent_incr; has_root_scope = 1; } /* Say this task/function has a parent so the * definition is emitted correctly. */ emit_scope(roots[idx], roots[idx]); break; default: break; } } if (has_root_scope) { indent -= indent_incr; assert(indent == 0); fprintf(vlog_out, "endmodule /* ivl_root_scope */\n"); } /* Emit the rest of the scope objects. */ for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0); free_emitted_scope_list(); /* Emit any UDP definitions that the design used. */ emit_udp_list(); /* Emit any UDPs that are Icarus generated (D-FF). */ emit_icarus_generated_udps(); /* If there were errors then add this information to the output. */ if (vlog_errors) { fprintf(vlog_out, "\n"); fprintf(vlog_out, "/*\n"); if (vlog_errors == 1) { fprintf(vlog_out, " * There was 1 error during " "translation.\n"); } else { fprintf(vlog_out, " * There were %d errors during " "translation.\n", vlog_errors); } fprintf(vlog_out, " */\n"); /* Add something that makes the file invalid to make sure * the user knows there were errors. */ fprintf(vlog_out, "<Add some text to make sure this file is not " "valid Verilog>\n"); } fclose(vlog_out); /* A do nothing call to prevent warnings about this routine not * being used. */ dump_nexus_information(0, 0); return vlog_errors; }
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; }
/* * Icarus encodes a user task call with arguments as: * begin * <input 1> = <arg> * ... * <input n> = <arg> * <task_call> * <arg> = <output 1> * ... * <arg> = <output n> * end * This routine looks for that pattern and translates it into the * appropriate task call. It returns true (1) if it successfully * translated the block to a task call, otherwise it returns false * (0) to indicate the block needs to be emitted. */ static unsigned is_utask_call_with_args(ivl_scope_t scope, ivl_statement_t stmt) { unsigned idx, ports, task_idx = 0; unsigned count = ivl_stmt_block_count(stmt); unsigned lineno = ivl_stmt_lineno(stmt); ivl_scope_t task_scope = 0; port_expr_t port_exprs; /* Check to see if the block is of the basic form first. */ for (idx = 0; idx < count; idx += 1) { ivl_statement_t tmp = ivl_stmt_block_stmt(stmt, idx); if (ivl_statement_type(tmp) == IVL_ST_ASSIGN) continue; if (ivl_statement_type(tmp) == IVL_ST_UTASK && !task_scope) { task_idx = idx; task_scope = ivl_stmt_call(tmp); assert(ivl_scope_type(task_scope) == IVL_SCT_TASK); continue; } return 0; } /* If there is no task call or it takes no argument then return. */ if (!task_scope) return 0; ports = ivl_scope_ports(task_scope); if (ports == 0) return 0; /* Allocate space to save the port information and initialize it. */ port_exprs = (port_expr_t) malloc(sizeof(struct port_expr_s)*ports); for (idx = 0; idx < ports; idx += 1) { port_exprs[idx].type = IVL_SIP_NONE; port_exprs[idx].expr.rval = 0; } /* Check that the input arguments are correct. */ for (idx = 0; idx < task_idx; idx += 1) { ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx); unsigned port = utask_in_port_idx(task_scope, assign); if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) { free(port_exprs); return 0; } port_exprs[port].type = IVL_SIP_INPUT; port_exprs[port].expr.rval = ivl_stmt_rval(assign); } /* Check that the output arguments are correct. */ for (idx = task_idx + 1; idx < count; idx += 1) { ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx); unsigned port = utask_out_port_idx(task_scope, assign); if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) { free(port_exprs); return 0; } if (port_exprs[port].type == IVL_SIP_INPUT) { port_exprs[port].type = IVL_SIP_INOUT; // HERE: We probably should verify that the current R-value matches the // new L-value. } else { port_exprs[port].type = IVL_SIP_OUTPUT; } port_exprs[port].expr.lval = assign; } /* Check that the task call has the correct line number. */ if (lineno != ivl_stmt_lineno(ivl_stmt_block_stmt(stmt, task_idx))) { free(port_exprs); return 0; } /* Verify that all the ports were defined. */ for (idx = 0; idx < ports; idx += 1) { if (port_exprs[idx].type == IVL_SIP_NONE) { free(port_exprs); return 0; } } /* Now that we have the arguments figured out, print the task call. */ fprintf(vlog_out, "%*c", get_indent(), ' '); emit_scope_path(scope, task_scope); fprintf(vlog_out, "("); emit_port(scope, port_exprs[0]); for (idx = 1; idx < ports; idx += 1) { fprintf(vlog_out, ", "); emit_port(scope, port_exprs[idx]); } free(port_exprs); fprintf(vlog_out, ");"); emit_stmt_file_line(stmt); fprintf(vlog_out, "\n"); return 1; }
static int show_scope(ivl_scope_t net, void*x) { unsigned idx; const char *is_auto; fprintf(out, "scope: %s (%u parameters, %u signals, %u logic)", ivl_scope_name(net), ivl_scope_params(net), ivl_scope_sigs(net), ivl_scope_logs(net)); is_auto = ivl_scope_is_auto(net) ? "automatic " : ""; switch (ivl_scope_type(net)) { case IVL_SCT_MODULE: fprintf(out, " module %s%s", ivl_scope_tname(net), ivl_scope_is_cell(net) ? " (cell)" : ""); break; case IVL_SCT_FUNCTION: fprintf(out, " function %s%s", is_auto, ivl_scope_tname(net)); break; case IVL_SCT_BEGIN: fprintf(out, " begin : %s", ivl_scope_tname(net)); break; case IVL_SCT_FORK: fprintf(out, " fork : %s", ivl_scope_tname(net)); break; case IVL_SCT_TASK: fprintf(out, " task %s%s", is_auto, ivl_scope_tname(net)); break; default: fprintf(out, " type(%u) %s", ivl_scope_type(net), ivl_scope_tname(net)); break; } fprintf(out, " time units = 1e%d\n", ivl_scope_time_units(net)); fprintf(out, " time precision = 1e%d\n", ivl_scope_time_precision(net)); for (idx = 0 ; idx < ivl_scope_attr_cnt(net) ; idx += 1) { ivl_attribute_t attr = ivl_scope_attr_val(net, idx); switch (attr->type) { case IVL_ATT_VOID: fprintf(out, " (* %s *)\n", attr->key); break; case IVL_ATT_STR: fprintf(out, " (* %s = \"%s\" *)\n", attr->key, attr->val.str); break; case IVL_ATT_NUM: fprintf(out, " (* %s = %ld *)\n", attr->key, attr->val.num); break; } } for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) show_parameter(ivl_scope_param(net, idx)); for (idx = 0 ; idx < ivl_scope_enumerates(net) ; idx += 1) show_enumerate(ivl_scope_enumerate(net, idx)); for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) show_signal(ivl_scope_sig(net, idx)); for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) show_event(ivl_scope_event(net, idx)); for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) show_logic(ivl_scope_log(net, idx)); for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) show_lpm(ivl_scope_lpm(net, idx)); for (idx = 0 ; idx < ivl_scope_switches(net) ; idx += 1) show_switch(ivl_scope_switch(net, idx)); switch (ivl_scope_type(net)) { case IVL_SCT_FUNCTION: case IVL_SCT_TASK: fprintf(out, " scope function/task definition\n"); if (ivl_scope_def(net) == 0) { fprintf(out, " ERROR: scope missing required task definition\n"); stub_errors += 1; } else { show_statement(ivl_scope_def(net), 6); } break; default: if (ivl_scope_def(net)) { fprintf(out, " ERROR: scope has an attached task definition:\n"); show_statement(ivl_scope_def(net), 6); stub_errors += 1; } break; } fprintf(out, "end scope %s\n", ivl_scope_name(net)); return ivl_scope_children(net, show_scope, 0); }