Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
0
/*
 * 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");
}
Exemplo n.º 3
0
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);
      }
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
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);
}