Beispiel #1
0
/*
 * Check to see if the statement R-value is a port in the given scope.
 * If it is return the zero based port number.
 */
static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned idx, ports = ivl_scope_ports(scope);
      ivl_expr_t rval = ivl_stmt_rval(stmt);
      ivl_signal_t rsig = 0;
      ivl_expr_type_t expr_type = ivl_expr_type(rval);
      const char *sig_name;
	/* We can have a simple signal. */
      if (expr_type == IVL_EX_SIGNAL) {
	    rsig = ivl_expr_signal(rval);
	/* Or a simple select of a simple signal. */
      } else if (expr_type == IVL_EX_SELECT) {
	    ivl_expr_t expr = ivl_expr_oper1(rval);
	      /* We must have a zero select base. */
	    if (ivl_expr_oper2(rval)) return ports;
	      /* We must be selecting a signal. */
	    if (ivl_expr_type(expr) != IVL_EX_SIGNAL) return ports;
	    rsig = ivl_expr_signal(expr);
      } else return ports;
	/* The R-value must have the same scope as the task. */
      if (scope != ivl_signal_scope(rsig)) return ports;
	/* It must not be an array element. */
      if (ivl_signal_dimensions(rsig)) return ports;
	/* It must be an output or inout port of the task. */
      sig_name = ivl_signal_basename(rsig);
      for (idx = 0; idx < ports; idx += 1) {
	    ivl_signal_t port = ivl_scope_port(scope, idx);
	    ivl_signal_port_t port_type = ivl_signal_port(port);
	    if ((port_type != IVL_SIP_OUTPUT) &&
	        (port_type != IVL_SIP_INOUT)) continue;
	    if (strcmp(sig_name, ivl_signal_basename(port)) == 0) break;
      }
      return idx;
}
Beispiel #2
0
/*
 * Check to see if the statement L-value is a port in the given scope.
 * If it is return the zero based port number.
 */
static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned idx, ports = ivl_scope_ports(scope);
      ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
      ivl_signal_t lsig = ivl_lval_sig(lval);
      const char *sig_name;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(stmt) != 1) return ports;
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return ports;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return ports;
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return ports;
	/* It must have the same scope as the task. */
      if (scope != ivl_signal_scope(lsig)) return ports;
	/* It must be an input or inout port of the task. */
      sig_name = ivl_signal_basename(lsig);
      for (idx = 0; idx < ports; idx += 1) {
	    ivl_signal_t port = ivl_scope_port(scope, idx);
	    ivl_signal_port_t port_type = ivl_signal_port(port);
	    if ((port_type != IVL_SIP_INPUT) &&
	        (port_type != IVL_SIP_INOUT)) continue;
	    if (strcmp(sig_name, ivl_signal_basename(port)) == 0) break;
      }
      return idx;
}
Beispiel #3
0
/*
 * Scoped objects are the signals, reg and wire and what-not. What
 * this function does is draw the objects of the scope, along with a
 * fake scope context so that the hierarchical name remains
 * pertinent.
 */
static void draw_scoped_objects(ivl_design_t des)
{
      ivl_scope_t root = ivl_design_root(des);
      unsigned cnt, idx;

      cnt = ivl_scope_sigs(root);
      for (idx = 0 ;  idx < cnt ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(root, idx);

	    switch (ivl_signal_type(sig)) {
		case IVL_SIT_REG:
		  if (ivl_signal_pins(sig) > 1)
			fprintf(out, "    reg [%u:0] %s;\n",
				ivl_signal_pins(sig),
				ivl_signal_basename(sig));
		  else
			fprintf(out, "    reg %s;\n",
				ivl_signal_basename(sig));
		  break;
		case IVL_SIT_TRI:
		  fprintf(out, "    wire %s;\n", ivl_signal_basename(sig));
		  break;
		default:
		  assert(0);
	    }
      }

}
Beispiel #4
0
static unsigned find_driving_signal(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t sig = 0;
      unsigned is_array = 0;
      int64_t array_idx = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! t_sig) continue;
	    if (ivl_signal_local(t_sig)) continue;
	      /* An output can be used if it is driven by this nexus. */
	    if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
	        (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ) &&
	        (ivl_signal_port(t_sig) != IVL_SIP_OUTPUT)) {
		  continue;
	    }
	      /* We have a signal that can be used to find the name. */
	    if (sig) {
// HERE: Which one should we use? For now it's the first one found.
//       I believe this needs to be solved (see above).
		  fprintf(stderr, "%s:%u: vlog95 warning: Duplicate name (%s",
		          ivl_signal_file(t_sig), ivl_signal_lineno(t_sig),
		          ivl_signal_basename(t_sig));
		  if (ivl_signal_dimensions(t_sig) > 0) {
			int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
			tmp_idx += ivl_signal_array_base(t_sig);
			fprintf(stderr, "[%"PRId64"]", tmp_idx);
		  }
		  fprintf(stderr, ") found for nexus (%s",
		          ivl_signal_basename(sig));
		  if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
		  fprintf(stderr, ")\n");
	    } else {
		  sig = t_sig;
		  if (ivl_signal_dimensions(sig) > 0) {
			is_array = 1;
			array_idx = ivl_nexus_ptr_pin(nex_ptr);
			array_idx += ivl_signal_array_base(sig);
		  }
	    }
      }

      if (sig) {
	    emit_scope_call_path(scope, ivl_signal_scope(sig));
	    emit_id(ivl_signal_basename(sig));
	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
	    return 1;
      }

      return 0;
}
Beispiel #5
0
static void show_lpm_array(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      unsigned width = ivl_lpm_width(net);
      ivl_signal_t array = ivl_lpm_array(net);

      fprintf(out, "  LPM_ARRAY: <width=%u, signal=%s>\n",
	      width, ivl_signal_basename(array));
      nex = ivl_lpm_q(net);
      assert(nex);
      fprintf(out, "    Q: %p\n", nex);
      nex = ivl_lpm_select(net);
      assert(nex);
      fprintf(out, "    Address: %p (address width=%u)\n",
	      nex, ivl_lpm_selects(net));

      if (width_of_nexus(ivl_lpm_q(net)) != width) {
	    fprintf(out, "    ERROR: Data Q width doesn't match "
		    "nexus width=%u\n", width_of_nexus(ivl_lpm_q(net)));
	    stub_errors += 1;
      }

      if (ivl_signal_width(array) != width) {
	    fprintf(out, "    ERROR: Data  width doesn't match "
		    "word width=%u\n", ivl_signal_width(array));
	    stub_errors += 1;
      }
}
Beispiel #6
0
static void show_root_ports_xnf(ivl_scope_t root)
{
    unsigned cnt = ivl_scope_sigs(root);
    unsigned idx;

    for (idx = 0 ;  idx < cnt ;  idx += 1) {
        ivl_signal_t sig = ivl_scope_sig(root, idx);
        const char*use_name;

        if (ivl_signal_port(sig) == IVL_SIP_NONE)
            continue;

        use_name = ivl_signal_basename(sig);
        if (ivl_signal_pins(sig) == 1) {
            ivl_nexus_t nex = ivl_signal_pin(sig, 0);
            fprintf(xnf, "SIG, %s, PIN=%s\n",
                    xnf_mangle_nexus_name(nex), use_name);

        } else {
            unsigned pin;

            for (pin = 0 ; pin < ivl_signal_pins(sig); pin += 1) {
                ivl_nexus_t nex = ivl_signal_pin(sig, pin);
                fprintf(xnf, "SIG, %s, PIN=%s%u\n",
                        xnf_mangle_nexus_name(nex), use_name,
                        pin);
            }
        }
    }
}
Beispiel #7
0
static void draw_eval_function_argument(ivl_signal_t port, ivl_expr_t expr)
{
    ivl_variable_type_t dtype = ivl_signal_data_type(port);
    switch (dtype) {
    case IVL_VT_BOOL:
    /* For now, treat bit2 variables as bit4 variables. */
    case IVL_VT_LOGIC:
        function_argument_logic(port, expr);
        break;
    case IVL_VT_REAL:
        function_argument_real(port, expr);
        break;
    case IVL_VT_CLASS:
        vvp_errors += draw_eval_object(expr);
        break;
    case IVL_VT_STRING:
        draw_eval_string(expr);
        break;
    case IVL_VT_DARRAY:
        vvp_errors += draw_eval_object(expr);
        break;
    default:
        fprintf(stderr, "XXXX function argument %s type=%d?!\n",
                ivl_signal_basename(port), dtype);
        assert(0);
    }
}
Beispiel #8
0
static void draw_send_function_argument(ivl_signal_t port)
{
    ivl_variable_type_t dtype = ivl_signal_data_type(port);
    switch (dtype) {
    case IVL_VT_BOOL:
    /* For now, treat bit2 variables as bit4 variables. */
    case IVL_VT_LOGIC:
        fprintf(vvp_out, "    %%store/vec4 v%p_0, 0, %u;\n",
                port, ivl_signal_width(port));
        break;
    case IVL_VT_REAL:
        fprintf(vvp_out, "    %%store/real v%p_0;\n", port);
        break;
    case IVL_VT_CLASS:
        fprintf(vvp_out, "    %%store/obj v%p_0;\n", port);
        break;
    case IVL_VT_STRING:
        fprintf(vvp_out, "    %%store/str v%p_0;\n", port);
        break;
    case IVL_VT_DARRAY:
        fprintf(vvp_out, "    %%store/obj v%p_0;\n", port);
        break;
    default:
        fprintf(stderr, "XXXX function argument %s type=%d?!\n",
                ivl_signal_basename(port), dtype);
        assert(0);
    }
}
Beispiel #9
0
static unsigned emit_as_input(ivl_scope_t scope, ivl_net_const_t net_const)
{
      ivl_scope_t const_scope = ivl_const_scope(net_const);
      ivl_scope_t parent = ivl_scope_parent(scope);

	/* Look to see if the constant scope is a parent of this scope. */
      while (parent) {
	    if (parent == const_scope) break;
	    parent = ivl_scope_parent(parent);
      }

	/* If the constant scope is a parent then look for an input in
	 * this scope and use that for the name. */
      if (parent) {
	    ivl_nexus_t nex = ivl_const_nex(net_const);
	    unsigned idx, count = ivl_nexus_ptrs(nex);
	    for (idx = 0; idx < count; idx += 1) {
		  ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
		  ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
		  if (sig && (ivl_signal_port(sig) == IVL_SIP_INPUT)) {
			emit_id(ivl_signal_basename(sig));
			return 1;
		  }
	    }
      }

      return 0;
}
Beispiel #10
0
static void display_multi_driver_error(ivl_nexus_t nex, unsigned ndrivers,
                                       mdriver_type_t type)
{
      unsigned idx;
      unsigned scope_len = UINT_MAX;
      ivl_signal_t sig = 0;
	/* Find the signal. */
      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t tsig = ivl_nexus_ptr_sig(ptr);
	    if (tsig != 0) {
		  ivl_scope_t scope;
		  unsigned len;
		  if (ivl_signal_local(tsig)) continue;

		    /* If this is not a local signal then find the signal
		     * that has the shortest scope (is the furthest up
		     * the hierarchy). */
		  scope = ivl_signal_scope(tsig);
		  assert(scope);
		  len = strlen(ivl_scope_name(scope));
		  if (len < scope_len) {
			scope_len = len;
			sig = tsig;
		  }
	    }
      }
      assert(sig);

      fprintf(stderr, "%s:%u: vvp.tgt error: ",
                      ivl_signal_file(sig), ivl_signal_lineno(sig));
      switch (type) {
	  case MDRV_UWIRE:
	    if (ivl_signal_type(sig) != IVL_SIT_UWIRE) {
		  fprintf(stderr, "(implicit) ");
	    }
	    fprintf(stderr, "uwire");
	    break;

	  case MDRV_REAL:
	    assert(ivl_signal_type(sig) == IVL_SIT_TRI);
	    if (ivl_signal_data_type(sig) != IVL_VT_REAL) {
		  fprintf(stderr, "(implicit) ");
	    }
	    fprintf(stderr, "wire real");
	    break;

	  default:
	    assert(0);;
      }
      fprintf(stderr, " \"%s\" must have a single driver, found (%u).\n",
                      ivl_signal_basename(sig), ndrivers);
      vvp_errors += 1;
}
Beispiel #11
0
static void show_array_expression(ivl_expr_t net, unsigned ind)
{
      ivl_signal_t sig = ivl_expr_signal(net);
      const char*name = ivl_signal_basename(sig);
      unsigned width = ivl_signal_width(sig);
      const char*vt   = vt_type_string(net);

      fprintf(out, "%*sArray: %s, word_count=%u (%u dimensions), width=%u, type=%s\n",
	      ind, "", name, ivl_signal_array_count(sig),
	      ivl_signal_dimensions(sig), width, vt);
}
Beispiel #12
0
static void show_property_expression(ivl_expr_t net, unsigned ind)
{
      ivl_signal_t sig = ivl_expr_signal(net);
      const char* pnam = ivl_expr_name(net);
      char*signed_flag = ivl_expr_signed(net)? "signed" : "unsigned";

      if (ivl_expr_value(net) == IVL_VT_REAL) {
	    fprintf(out, "%*s<property base=%s, prop=%s, real>\n", ind, "",
		    ivl_signal_basename(sig), pnam);
      } else if (ivl_expr_value(net) == IVL_VT_STRING) {
	    fprintf(out, "%*s<property base=%s, prop=%s, string>\n", ind, "",
		    ivl_signal_basename(sig), pnam);
      } else {
	    fprintf(out, "%*s<property base=%s, prop=%s, width=%u, %s>\n", ind, "",
		    ivl_signal_basename(sig), pnam, ivl_expr_width(net), signed_flag);
      }
      if (ivl_signal_data_type(sig) != IVL_VT_CLASS) {
	    fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n",
		    ind+3, "", data_type_string(ivl_signal_data_type(sig)));
      }
}
Beispiel #13
0
static void show_root_ports_edif(ivl_scope_t root)
{
      char jbuf[1024];
      unsigned cnt = ivl_scope_sigs(root);
      unsigned idx;

      for (idx = 0 ;  idx < cnt ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(root, idx);
	    const char*use_name;
	    const char*dir = 0;

	    if (ivl_signal_attr(sig, "PAD") != 0)
		  continue;

	    switch (ivl_signal_port(sig)) {
		case IVL_SIP_NONE:
		  continue;

		case IVL_SIP_INPUT:
		  dir = "INPUT";
		  break;

		case IVL_SIP_OUTPUT:
		  dir = "OUTPUT";
		  break;

		case IVL_SIP_INOUT:
		  dir = "INOUT";
		  break;
	    }

	    use_name = ivl_signal_basename(sig);
	    if (ivl_signal_pins(sig) == 1) {
		  fprintf(xnf, "            (port %s (direction %s))\n",
			  use_name, dir);

		  sprintf(jbuf, "(portRef %s)", use_name);
		  edif_set_nexus_joint(ivl_signal_pin(sig, 0), jbuf);

	    } else {
		  unsigned pin;

		  for (pin = 0 ; pin < ivl_signal_pins(sig); pin += 1) {
			fprintf(xnf, "            (port (rename %s_%u "
				"\"%s[%u]\") (direction %s))\n", use_name,
				pin, use_name, pin, dir);
			sprintf(jbuf, "(portRef %s_%u)", use_name, pin);
			edif_set_nexus_joint(ivl_signal_pin(sig, pin), jbuf);
		  }
	    }
      }
}
Beispiel #14
0
static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      ivl_signal_t sig = ivl_expr_signal(expr);
      emit_scope_call_path(scope, ivl_signal_scope(sig));
      emit_id(ivl_signal_basename(sig));
      if (ivl_signal_dimensions(sig)) {
	    int lsb = ivl_signal_array_base(sig);
	    int msb = lsb + ivl_signal_array_count(sig);
	    fprintf(vlog_out, "[");
	    emit_scaled_expr(scope, ivl_expr_oper1(expr), msb, lsb);
	    fprintf(vlog_out, "]");
      }
}
Beispiel #15
0
/*
 * This function draws a reg/int/variable in the scope. This is a very
 * simple device to draw as there are no inputs to connect so no need
 * to scan the nexus. We do have to account for the possibility that
 * the device is arrayed, though, by making a node for each array element.
 */
static void draw_reg_in_scope(ivl_signal_t sig)
{
      int msb = ivl_signal_msb(sig);
      int lsb = ivl_signal_lsb(sig);

      const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
			       ivl_signal_signed(sig)? "/s" : "";
      const char*local_flag = ivl_signal_local(sig)? "*" : "";

      switch (ivl_signal_data_type(sig)) {
	  case IVL_VT_REAL:
	    datatype_flag = "/real";
	    break;
	  default:
	    break;
      }

	/* If the reg objects are collected into an array, then first
	   write out the .array record to declare the array indices. */
      if (ivl_signal_dimensions(sig) > 0) {
	    unsigned word_count = ivl_signal_array_count(sig);
	    int last = ivl_signal_array_base(sig)+word_count-1;
	    int first = ivl_signal_array_base(sig);
	    fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
		    sig, datatype_flag,
		    vvp_mangle_name(ivl_signal_basename(sig)),
		    last, first, msb, lsb);

      } else {

	    fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
		    sig, datatype_flag, local_flag,
		    vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb,
		    ivl_signal_local(sig)? " Local signal" : "");
      }
}
Beispiel #16
0
static void emit_stmt_lval_name(ivl_scope_t scope, ivl_lval_t lval,
                                ivl_signal_t sig)
{
      ivl_expr_t array_idx = ivl_lval_idx(lval);
      emit_scope_call_path(scope, ivl_signal_scope(sig));
      emit_id(ivl_signal_basename(sig));
      if (array_idx) {
	    int msb, lsb;
	    assert(ivl_signal_dimensions(sig));
	    fprintf(vlog_out, "[");
	      /* For an array the LSB/MSB order is not important. They are
	       * always accessed from base counting up. */
	    lsb = ivl_signal_array_base(sig);
	    msb = lsb + ivl_signal_array_count(sig) - 1;
	    emit_scaled_expr(scope, array_idx, msb, lsb);
	    fprintf(vlog_out, "]");
      }
}
Beispiel #17
0
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
{
      ivl_variable_type_t dtype = ivl_signal_data_type(port);
      switch (dtype) {
	  case IVL_VT_LOGIC:
	    function_argument_logic(port, expr);
	    break;
	  case IVL_VT_REAL:
	    function_argument_real(port, expr);
	    break;
	  case IVL_VT_BOOL:
	    function_argument_bool(port, expr);
	    break;
	  default:
	    fprintf(stderr, "XXXX function argument %s type=%d?!\n",
		    ivl_signal_basename(port), dtype);
	    assert(0);
      }
}
Beispiel #18
0
static unsigned is_local_input(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t sig = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! t_sig) continue;
	    if (! ivl_signal_local(t_sig)) continue;
	    if (ivl_signal_port(t_sig) != IVL_SIP_INPUT) continue;
	    assert(! sig);
	    assert(ivl_signal_dimensions(t_sig) == 0);
	    sig = t_sig;
      }
      if (sig) {
	    fprintf(vlog_out, "ivlog%s", ivl_signal_basename(sig));
	    return 1;
      }
      return 0;
}
Beispiel #19
0
edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
				     ivl_scope_t scope)
{
      unsigned port_count, idx;
      edif_cell_t cur;

	/* Check to see if the cell is already somehow defined. */
      cur = edif_xlibrary_findcell(xlib, ivl_scope_tname(scope));
      if (cur) return cur;

	/* Count the ports of the scope. */
      port_count = 0;
      for (idx = 0 ;  idx < ivl_scope_sigs(scope) ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(scope, idx);

	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
		  continue;

	    port_count += 1;
      }

      cur = edif_xcell_create(xlib, ivl_scope_tname(scope), port_count);

      port_count = 0;
      for (idx = 0 ;  idx < ivl_scope_sigs(scope) ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(scope, idx);

	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
		  continue;

	    edif_cell_portconfig(cur, port_count,
				 ivl_signal_basename(sig),
				 ivl_signal_port(sig));
	    port_count += 1;
      }

      return cur;
}
Beispiel #20
0
// Build the design hierarchy.
int build_hierarchy(ivl_scope_t scope, void* cd)
{
  int return_code;
  unsigned i, j;

  indent();
  fprintf(output, "(scope ");
  quoted_string(ivl_scope_tname(scope));
  fprintf(output, " ");
  quoted_string(ivl_scope_basename(scope));
  fprintf(output, " (\n");

  // Constants (root scope only)
  if (! level)
    for (i = 0; i < ivl_design_consts(design); i++) {
      ivl_net_const_t constant = ivl_design_const(design, i);
      const char* bits = ivl_const_bits(constant);
      unsigned pins = ivl_const_pins(constant);
      unsigned id = new_id();
      indent();
      fprintf(output, "  (const  %i \"", id);
      for (j = pins - 1; j < pins; j--)
        fprintf(output, "%c", bits[j]);
      fprintf(output, "\")\n");
      for (j = 0; j < pins; j++)
        create_bit_select(id_of_nexus(ivl_const_pin(constant, j), 1), pins, j, id);
    }

  // Parameters
  for (i = 0; i < ivl_scope_params(scope); i++) {
    ivl_parameter_t param = ivl_scope_param(scope, i);
    ivl_expr_t param_value = ivl_parameter_expr(param);
    unsigned width = ivl_expr_width(param_value);
    const char* bits;
    unsigned id = new_id();
    indent();
    fprintf(output, "  (const  %i \"", id);
    switch (ivl_expr_type(param_value)) {
      case IVL_EX_STRING : bits = ivl_expr_string(param_value); break;
      case IVL_EX_NUMBER : bits = ivl_expr_bits(param_value);   break;
      default            : fprintf(output, "** ERROR: Unknown parameter type."); return -1;
    }
    for (j = width - 1; j < width; j--)
      fprintf(output, "%c", bits[j]);
    fprintf(output, "\")\n");
    indent();
    fprintf(output, "  (name   %i ", new_id());
    quoted_string(ivl_parameter_basename(param));
    fprintf(output, " %i %i)\n", width, id);
  }

  // Signals
  for (i = 0; i < ivl_scope_sigs(scope); i++) {
    ivl_signal_t sig = ivl_scope_sig(scope, i);
    unsigned pins = ivl_signal_pins(sig);
    ivl_signal_port_t type = ivl_signal_port(sig);
    const char* name = ivl_signal_basename(sig);
    unsigned id;
    if (! level && type == IVL_SIP_INPUT) {
      id = new_id();
      fprintf(output, "  (input  %i \"%s\" %i)\n", id, name, pins);
      for (j = 0; j < pins; j++)
        create_bit_select(id_of_nexus(ivl_signal_pin(sig, j), 1), pins, j, id);
    }
    else if (! level && type == IVL_SIP_INOUT) {
      printf("** ERROR: Inout ports not supported.\n");
    }
    else if (! level && type == IVL_SIP_OUTPUT) {
      id = id_of_nexus(ivl_signal_pin(sig, 0), 0);
      for (j = 1; j < pins; j++) {
        id = create_bit_concat(id, j, ivl_signal_pin(sig, j));
      }
      fprintf(output, "  (output %i \"%s\" %i %i)\n", new_id(), name, pins, id);
    }
    else {
      id = id_of_nexus(ivl_signal_pin(sig, 0), 0);
      for (j = 1; j < pins; j++) {
        id = create_bit_concat(id, j, ivl_signal_pin(sig, j));
      }
      indent();
      fprintf(output, "  (name   %i ", new_id());  //XXX Why is "_s22" getting named?
      quoted_string(name);
      fprintf(output, " %i %i)\n", pins, id);
    }
  }

  // Logic
  for (i = 0; i < ivl_scope_logs(scope); i++) {
    unsigned id;
    ivl_net_logic_t log = ivl_scope_log(scope, i);
    switch (ivl_logic_type(log)) {
      case IVL_LO_BUF:
        indent();
        fprintf(output, "  (buf    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0));
        break;

      case IVL_LO_NOT:
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0));
        break;

      case IVL_LO_AND:
        indent();
        create_multi_gate("and ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_NAND:
        id = new_id();
        indent();
        create_multi_gate("and ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;
      
      case IVL_LO_XOR:
        indent();
        create_multi_gate("xor ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_XNOR:
        id = new_id();
        indent();
        create_multi_gate("xor ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;
      
      case IVL_LO_OR:
        indent();
        create_multi_gate("or  ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_NOR:
        id = new_id();
        indent();
        create_multi_gate("or  ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;

      default:
        printf("** ERROR: Unsupported logic type: %i.\n", ivl_logic_type(log));
        return -1;
    }
  }
  
  // LPMs
  for (i = 0; i < ivl_scope_lpms(scope); i++) {
    ivl_lpm_t lpm = ivl_scope_lpm(scope, i);
    ivl_lpm_type_t lpm_t = ivl_lpm_type(lpm);
    unsigned width   = ivl_lpm_width(lpm);
    unsigned selects;
    unsigned size;
    unsigned id, id1, id2, id3;
    switch (lpm_t) {
      case IVL_LPM_ADD:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (add    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_SUB:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (sub    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_MULT:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (mul    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_CMP_EQ:
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (eq     %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id1, id2);
        break;

      case IVL_LPM_CMP_NE:
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        id  = new_id();
        indent();
        fprintf(output, "  (eq     %i %i %i %i)\n", id, width, id1, id2);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id);
        break;

      case IVL_LPM_CMP_GT:
        // XXX Check for signed.
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (lt     %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id2, id1);
        break;

      case IVL_LPM_CMP_GE:
        // XXX Check for signed.
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        id  = new_id();
        indent();
        fprintf(output, "  (lt     %i %i %i %i)\n", id, width, id1, id2);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id);
        break;

      case IVL_LPM_FF:
        {
          ivl_nexus_t async_clr = ivl_lpm_async_clr(lpm);
          ivl_nexus_t async_set = ivl_lpm_async_set(lpm);
          ivl_nexus_t sync_clr = ivl_lpm_sync_clr(lpm);
          ivl_nexus_t sync_set = ivl_lpm_sync_set(lpm);
          ivl_nexus_t clk = ivl_lpm_clk(lpm);
          ivl_nexus_t enable = ivl_lpm_enable(lpm);
          if (async_set || sync_set) { perror("** ERROR: Does not support registers with async or sync sets.\n"); return -1; }
          id = new_id();
          id1 = create_concat_lpm_data(lpm);
          if (enable) {
            id2 = new_id();
            indent();
            fprintf(output, "  (mux    %i %i %i %i %i)\n", id2, width, id_of_nexus(enable, 0), id, id1);
            id1 = id2;
          }
          if (sync_clr) {
            id2 = new_id();
            id3 = new_id();
            indent();
            fprintf(output, "  (const  %i \"", id3);
            for (j = 0; j < width; j++)
              fprintf(output, "0");
            fprintf(output, "\")\n");
            indent();
            fprintf(output, "  (mux    %i %i %i %i %i)\n", id2, width, id_of_nexus(sync_clr, 0), id1, id3);
            id1 = id2;
          }
          // XXX Default to posedge sensitivity.
          if (async_clr) {
            indent();
            fprintf(output, "  (ffc    %i %i %i %i %i)\n", id, width, id_of_nexus(async_clr, 0), id_of_nexus(clk, 0), id1);
          }
          else {
            indent();
            fprintf(output, "  (ff     %i %i %i %i)\n", id, width, id_of_nexus(clk, 0), id1);
          }
          create_split_lpm_q(lpm, id);
        }
        break;

      case IVL_LPM_MUX:
        {
          unsigned t = 1;
          selects = ivl_lpm_selects(lpm);
          size    = ivl_lpm_size(lpm);
          for (j = 0; j < selects; j++)
            t = t * 2;
          assert(t == size); // General case.
          id = create_mux(lpm, selects, 0);
          create_split_lpm_q(lpm, id);
        }
        break;

      default:
        perror("** ERROR: Unsupported LPM type.\n");
        return -1;
    }
  }
  level = level + 1;
  return_code = ivl_scope_children(scope, build_hierarchy, 0);
  level = level - 1;
  if (! level)
    delete_nexus_table(nexus_table);
  indent();
  fprintf(output, "))\n");
  return return_code;
}
Beispiel #21
0
static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t use_sig = 0;
      unsigned is_driver = 0;
      unsigned is_array = 0;
      int64_t array_idx = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! sig) continue;
	    if (ivl_signal_local(sig)) {
		    /* If the local signal is another receiver skip it. */
		  if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
		      (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
			continue;
		  }
	          assert(0);
	    }
	      /* We have a signal that can be used to find the name. */
	    if (scope == ivl_signal_scope(sig)) {
		  if (use_sig) {
			  /* Swap a receiver for a driver. */
			if (is_driver &&
			    (ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
			    (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
			      use_sig = sig;
			      is_driver = 0;
			      if (ivl_signal_dimensions(sig) > 0) {
				    is_array = 1;
				    array_idx = ivl_nexus_ptr_pin(nex_ptr);
				    array_idx += ivl_signal_array_base(sig);
			      }
			      continue;
			}
// HERE: Which one should we use? For now it's the first one found.
//       I believe this needs to be solved (see the inout.v test).
			fprintf(stderr, "%s:%u: vlog95 warning: Duplicate "
			                "name (%s",
			                ivl_signal_file(sig),
			                ivl_signal_lineno(sig),
			                ivl_signal_basename(sig));
			if (ivl_signal_dimensions(sig) > 0) {
			      int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
			      tmp_idx += ivl_signal_array_base(sig);
			      fprintf(stderr, "[%"PRId64"]", tmp_idx);
			}
			fprintf(stderr, ") found for nexus (%s",
			                ivl_signal_basename(use_sig));
			if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
			fprintf(stderr, ")\n");
		  } else {
			use_sig = sig;
			  /* This signal is a driver. */
			if ((ivl_nexus_ptr_drive1(nex_ptr) != IVL_DR_HiZ) ||
			    (ivl_nexus_ptr_drive0(nex_ptr) != IVL_DR_HiZ)) {
			      is_driver = 1;
			}
			if (ivl_signal_dimensions(sig) > 0) {
			      is_array = 1;
			      array_idx = ivl_nexus_ptr_pin(nex_ptr);
			      array_idx += ivl_signal_array_base(sig);
			}
		  }
	    }
      }

      if (use_sig) {
	    emit_id(ivl_signal_basename(use_sig));
	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
	    return 1;
      }

      return 0;
}
Beispiel #22
0
/*
 * This function draws a net. This is a bit more complicated as we
 * have to find an appropriate functor to connect to the input.
 */
static void draw_net_in_scope(ivl_signal_t sig)
{
      int msb = ivl_signal_msb(sig);
      int lsb = ivl_signal_lsb(sig);

      const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
      const char*local_flag = ivl_signal_local(sig)? "*" : "";
      unsigned iword;

      switch (ivl_signal_data_type(sig)) {
	  case IVL_VT_REAL:
	    datatype_flag = "/real";
	    break;
	  default:
	    break;
      }

      for (iword = 0 ;  iword < ivl_signal_array_count(sig); iword += 1) {

	    unsigned word_count = ivl_signal_array_count(sig);
	    unsigned dimensions = ivl_signal_dimensions(sig);
	    struct vvp_nexus_data*nex_data;

	      /* Connect the pin of the signal to something. */
	    ivl_nexus_t nex = ivl_signal_nex(sig, iword);
	    const char*driver = draw_net_input(nex);

	    nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
	    assert(nex_data);

	    if (nex_data->net == 0) {
		  int strength_aware_flag = 0;
		  const char*vec8 = "";
		  if (nex_data->flags&VVP_NEXUS_DATA_STR)
			strength_aware_flag = 1;
		  if (nex_data->drivers_count > 1)
			vec8 = "8";
		  if (strength_aware_flag)
			vec8 = "8";

		  if (iword == 0 && dimensions > 0) {
			int last = ivl_signal_array_base(sig) + word_count-1;
			int first = ivl_signal_array_base(sig);
			fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				sig, vvp_mangle_name(ivl_signal_basename(sig)),
				last, first);
		  }
		  if (dimensions > 0) {
			/* If this is a word of an array, then use an
			   array reference in place of the net name. */
			fprintf(vvp_out, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, sig,
				iword, msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  } else {
			/* If this is an isolated word, it uses its
			   own name. */
			assert(word_count == 1);
			fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, local_flag,
				vvp_mangle_name(ivl_signal_basename(sig)),
				msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  }
		  nex_data->net = sig;
		  nex_data->net_word = iword;

	    } else if (dimensions > 0) {

		    /* In this case, we have an alias to an existing
		       signal array. this typically is an instance of
		       port collapsing that the elaborator combined to
		       discover that the entire array can be collapsed,
		       so the word count for the signal and the alias
		       *must* match. */

		  if (word_count == ivl_signal_array_count(nex_data->net)) {
		    if (iword == 0) {
		      fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
			      sig, vvp_mangle_name(ivl_signal_basename(sig)),
			      nex_data->net,
			      ivl_signal_basename(nex_data->net));
		    }
		    /* An alias for an individual word. */
		  } else {
			if (iword == 0) {
			      int first = ivl_signal_array_base(sig);
			      int last = first + word_count-1;
			      fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				      sig,
				      vvp_mangle_name(ivl_signal_basename(sig)),
				      last, first);
			}

			fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
			        "v%p_%u; Alias to %s\n", sig, iword,
			        datatype_flag, sig, iword, msb, lsb,
			        nex_data->net, nex_data->net_word,
			        ivl_signal_basename(nex_data->net));
		  }
	    } else {
		    /* Finally, we may have an alias that is a word
		       connected to another word. Again, this is a
		       case of port collapsing. */

		    /* For the alias, create a different kind of node
		       that refers to the alias source data instead of
		       holding our own data. */
		  fprintf(vvp_out, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
			  sig, iword, datatype_flag,
			  vvp_mangle_name(ivl_signal_basename(sig)),
			  msb, lsb, nex_data->net, nex_data->net_word);
	    }
      }
}
Beispiel #23
0
static void emit_expr_array(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      ivl_signal_t sig = ivl_expr_signal(expr);
      emit_scope_call_path(scope, ivl_signal_scope(sig));
      emit_id(ivl_signal_basename(sig));
}
Beispiel #24
0
static void lpm_show_header(ivl_design_t des)
{
      unsigned idx;
      ivl_scope_t root = ivl_design_root(des);
      unsigned sig_cnt = ivl_scope_sigs(root);
      unsigned nports = 0, pidx;

	/* Count the ports I'm going to use. */
      for (idx = 0 ;  idx < sig_cnt ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(root, idx);

	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
		  continue;

	    if (ivl_signal_attr(sig, "PAD") != 0)
		  continue;

	    nports += ivl_signal_pins(sig);
      }

	/* Create the base edf object. */
      edf = edif_create(ivl_scope_basename(root), nports);


      pidx = 0;
      for (idx = 0 ;  idx < sig_cnt ;  idx += 1) {
	    edif_joint_t jnt;
	    ivl_signal_t sig = ivl_scope_sig(root, idx);

	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
		  continue;

	    if (ivl_signal_attr(sig, "PAD") != 0)
		  continue;

	    if (ivl_signal_pins(sig) == 1) {
		  edif_portconfig(edf, pidx, ivl_signal_basename(sig),
				  ivl_signal_port(sig));

		  assert(ivl_signal_pins(sig) == 1);
		  jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
		  edif_port_to_joint(jnt, edf, pidx);

	    } else {
		  const char*name = ivl_signal_basename(sig);
		  ivl_signal_port_t dir = ivl_signal_port(sig);
		  char buf[128];
		  unsigned bit;
		  for (bit = 0 ;  bit < ivl_signal_pins(sig) ; bit += 1) {
			const char*tmp;
			sprintf(buf, "%s[%u]", name, bit);
			tmp = strdup(buf);
			edif_portconfig(edf, pidx+bit, tmp, dir);

			jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
			edif_port_to_joint(jnt, edf, pidx+bit);
		  }
	    }

	    pidx += ivl_signal_pins(sig);
      }

      assert(pidx == nports);

      xlib = edif_xlibrary_create(edf, "LPM_LIBRARY");
}
Beispiel #25
0
static void show_signal(ivl_signal_t net)
{
      unsigned idx;

      const char*type = "?";
      const char*port = "";
      const char*data_type = "?";
      const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";

      switch (ivl_signal_type(net)) {
	  case IVL_SIT_REG:
	    type = "reg";
	    break;
	  case IVL_SIT_TRI:
	    type = "tri";
	    break;
	  case IVL_SIT_TRI0:
	    type = "tri0";
	    break;
	  case IVL_SIT_TRI1:
	    type = "tri1";
	    break;
	  case IVL_SIT_UWIRE:
	    type = "uwire";
	    break;
	  default:
	    break;
      }

      switch (ivl_signal_port(net)) {

	  case IVL_SIP_INPUT:
	    port = "input ";
	    break;

	  case IVL_SIP_OUTPUT:
	    port = "output ";
	    break;

	  case IVL_SIP_INOUT:
	    port = "inout ";
	    break;

	  case IVL_SIP_NONE:
	    break;
      }

      switch (ivl_signal_data_type(net)) {

	  case IVL_VT_BOOL:
	    data_type = "bool";
	    break;

	  case IVL_VT_LOGIC:
	    data_type = "logic";
	    break;

	  case IVL_VT_REAL:
	    data_type = "real";
	    break;

	  default:
	    data_type = "?data?";
	    break;
      }

      const char*discipline_txt = "NONE";
      if (ivl_signal_discipline(net)) {
	    ivl_discipline_t dis = ivl_signal_discipline(net);
	    discipline_txt = ivl_discipline_name(dis);
      }

      for (idx = 0 ;  idx < ivl_signal_array_count(net) ; idx += 1) {

	    ivl_nexus_t nex = ivl_signal_nex(net, idx);

	    fprintf(out, "  %s %s %s%s[%d:%d] %s[word=%u, adr=%d]  "
		               "<width=%u%s> <discipline=%s> ",
		    type, sign, port, data_type,
		    ivl_signal_msb(net), ivl_signal_lsb(net),
		    ivl_signal_basename(net),
		    idx, ivl_signal_array_base(net)+idx,
		    ivl_signal_width(net),
		    ivl_signal_local(net)? ", local":"",
		    discipline_txt);
	    if (nex == NULL) {
		  fprintf(out, "nexus=<virtual>\n");
		  continue;
	    } else {
		  fprintf(out, "nexus=%p\n", nex);
	    }

	    show_nexus_details(net, nex);
      }

      for (idx = 0 ;  idx < ivl_signal_npath(net) ;  idx += 1) {
	    ivl_delaypath_t path = ivl_signal_path(net,idx);
	    ivl_nexus_t nex = ivl_path_source(path);
	    ivl_nexus_t con = ivl_path_condit(path);
	    int posedge = ivl_path_source_posedge(path);
	    int negedge = ivl_path_source_negedge(path);

	    fprintf(out, "      path %p", nex);
	    if (posedge) fprintf(out, " posedge");
	    if (negedge) fprintf(out, " negedge");
	    if (con) fprintf(out, " (if %p)", con);
	    else if (ivl_path_is_condit(path)) fprintf(out, " (ifnone)");
	    fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64,
		    ivl_path_delay(path, IVL_PE_01),
		    ivl_path_delay(path, IVL_PE_10),
		    ivl_path_delay(path, IVL_PE_0z),
		    ivl_path_delay(path, IVL_PE_z1),
		    ivl_path_delay(path, IVL_PE_1z),
		    ivl_path_delay(path, IVL_PE_z0),
		    ivl_path_delay(path, IVL_PE_0x),
		    ivl_path_delay(path, IVL_PE_x1),
		    ivl_path_delay(path, IVL_PE_1x),
		    ivl_path_delay(path, IVL_PE_x0),
		    ivl_path_delay(path, IVL_PE_xz),
		    ivl_path_delay(path, IVL_PE_zx));
	    fprintf(out, " scope=%s\n", ivl_scope_name(ivl_path_scope(path)));
      }

      for (idx = 0 ;  idx < ivl_signal_attr_cnt(net) ;  idx += 1) {
	    ivl_attribute_t atr = ivl_signal_attr_val(net, idx);

	    switch (atr->type) {
		case IVL_ATT_STR:
		  fprintf(out, "    %s = %s\n", atr->key, atr->val.str);
		  break;
		case IVL_ATT_NUM:
		  fprintf(out, "    %s = %ld\n", atr->key, atr->val.num);
		  break;
		case IVL_ATT_VOID:
		  fprintf(out, "    %s\n", atr->key);
		  break;
	    }
      }

}