示例#1
0
/*
 * Check to see if the real expression is of the form (expr) * <scale>
 */
static unsigned check_scaled_real_expr(ivl_expr_t expr, double scale)
{
      double scale_val;
      if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
          (ivl_expr_opcode(expr) != '*') ||
          (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_REALNUM)) {
	    fprintf(stderr, "%s:%u: vlog95 error: Variable real time unit "
	                    " expression/value cannot be scaled.\n ",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    return 0;
      }
      scale_val = ivl_expr_dvalue(ivl_expr_oper2(expr));
      if (scale != scale_val) {
	    fprintf(stderr, "%s:%u: vlog95 error: Variable real time unit "
	                    "expression/value scale coefficient did not "
	                    "match expected value (%g != %g).\n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
	                    scale, scale_val);
	    vlog_errors += 1;
	    return 0;
      }
	/* Yes, this expression is of the correct form. */
      return 1;
}
示例#2
0
// HERE: Probably need to pass in a msg string to make this work with
//       indexed part selects.
static unsigned is_scaled_expr(ivl_expr_t expr, int msb, int lsb)
{
      int64_t scale_val;
      int rtype;
	/* This is as easy as removing the addition/subtraction that was
	 * added to scale the value to be zero based, but we need to verify
	 * that the scaling value is correct first. */
      if (msb > lsb) {
	    if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
	        ((ivl_expr_opcode(expr) != '+') &&
	         (ivl_expr_opcode(expr) != '-')) ||
	        (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_NUMBER)) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Scaled "
		                  "expression value cannot be scaled.\n",
		                  ivl_expr_file(expr),
		                  ivl_expr_lineno(expr));
		  vlog_errors += 1;
		  return 0;
	    }
	    scale_val = get_valid_int64_from_number(
	                      ivl_expr_oper2(expr), &rtype,
	                      "expression value scale coefficient");
      } else {
	    if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
	        ((ivl_expr_opcode(expr) != '+') &&
	         (ivl_expr_opcode(expr) != '-')) ||
	        (ivl_expr_type(ivl_expr_oper1(expr)) != IVL_EX_NUMBER)) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Scaled "
		                  "expression value cannot be scaled.\n",
		                  ivl_expr_file(expr),
		                  ivl_expr_lineno(expr));
		  vlog_errors += 1;
		  return 0;
	    }
	    scale_val = get_valid_int64_from_number(
	                      ivl_expr_oper1(expr), &rtype,
	                      "expression value scale coefficient");
      }
      if (rtype) return 0;
      if (ivl_expr_opcode(expr) == '+') scale_val *= -1;
      if (lsb !=  scale_val) {
	    fprintf(vlog_out, "<invalid>");
	    fprintf(stderr, "%s:%u: vlog95 error: Scaled expression value "
	                    "scaling coefficient did not match expected "
	                    "value (%d != %"PRIu64").\n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
	                    lsb, scale_val);
	    vlog_errors += 1;
	    return 0;
      }
      return 1;
}
示例#3
0
static void draw_sfunc_vec4(ivl_expr_t expr)
{
      unsigned parm_count = ivl_expr_parms(expr);

	/* Special case: If there are no arguments to print, then the
	   %vpi_call statement is easy to draw. */
      if (parm_count == 0) {
	    assert(ivl_expr_value(expr)==IVL_VT_LOGIC
		   || ivl_expr_value(expr)==IVL_VT_BOOL);

	    fprintf(vvp_out, "    %%vpi_func %u %u \"%s\" %u {0 0 0};\n",
		    ivl_file_table_index(ivl_expr_file(expr)),
		    ivl_expr_lineno(expr), ivl_expr_name(expr),
		    ivl_expr_width(expr));
	    return;
      }

      if (strcmp(ivl_expr_name(expr), "$ivl_darray_method$pop_back")==0) {
	    draw_darray_pop(expr);
	    return;
      }
      if (strcmp(ivl_expr_name(expr),"$ivl_darray_method$pop_front")==0) {
	    draw_darray_pop(expr);
	    return;
      }

      draw_vpi_func_call(expr);
}
示例#4
0
/*
 * Check to see if the bit based expression is of the form (expr) * <scale>
 */
static unsigned check_scaled_expr(ivl_expr_t expr, uint64_t scale,
                                  const char *msg, unsigned must_match)
{
      uint64_t scale_val;
      int rtype;
      if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
          (ivl_expr_opcode(expr) != '*') ||
          (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_NUMBER)) {
	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
	                    "cannot be scaled.\n ",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
	    vlog_errors += 1;
	    return 0;
      }
      scale_val = get_uint64_from_number(ivl_expr_oper2(expr), &rtype);
      if (rtype > 0) {
	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
	                    "scale coefficient was greater than 64 bits "
	                    "(%d).\n", ivl_expr_file(expr),
	                    ivl_expr_lineno(expr), msg, rtype);
	    vlog_errors += 1;
	    return 0;
      }
      if (rtype < 0) {
	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
	                    "scale coefficient has an undefined bit.\n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
	    vlog_errors += 1;
	    return 0;
      }
      if (scale != scale_val) {
	    if (must_match) {
		  fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
		                  "scale coefficient did not match expected "
		                  "value (%"PRIu64" != %"PRIu64").\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr),
		                  msg, scale, scale_val);
		  vlog_errors += 1;
		  return 0;
	    }
	    return 2;
      }
	/* Yes, this expression is of the correct form. */
      return 1;
}
示例#5
0
static int64_t get_valid_int64_from_number(ivl_expr_t expr, int *rtype,
                                           const char *msg)
{
      int64_t value = get_int64_from_number(expr, rtype);
      if (*rtype > 0) {
	    fprintf(vlog_out, "<invalid>");
	    fprintf(stderr, "%s:%u: vlog95 error: Scaled %s is greater than "
	                    "64 bits (%d) and cannot be safely represented.\n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
	                    msg, *rtype);
	    vlog_errors += 1;
	    return 0;
      } else if (*rtype < 0) {
	    fprintf(vlog_out, "<invalid>");
	    fprintf(stderr, "%s:%u: vlog95 error: Scaled %s has an undefined "
	                    "bit and cannot be represented.\n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
	    vlog_errors += 1;
	    return 0;
      }
      return value;
}
示例#6
0
int draw_vpi_rfunc_call(ivl_expr_t fnet)
{
      char call_string[1024];
      int res = allocate_word();

      sprintf(call_string, "    %%vpi_func/r %u %u \"%s\", %d",
              ivl_file_table_index(ivl_expr_file(fnet)),
	      ivl_expr_lineno(fnet), ivl_expr_name(fnet), res);

      draw_vpi_taskfunc_args(call_string, 0, fnet);

      return res;
}
示例#7
0
struct vector_info draw_vpi_func_call(ivl_expr_t fnet, unsigned wid)
{
      char call_string[1024];
      struct vector_info res;

      res.base = allocate_vector(wid);
      res.wid  = wid;
      if (res.base == 0) {
	    fprintf(stderr, "%s:%u: vvp.tgt error: "
		    "Unable to allocate %u thread bits for system function result.\n",
		    ivl_expr_file(fnet), ivl_expr_lineno(fnet), wid);
	    vvp_errors += 1;
      }

      sprintf(call_string, "    %%vpi_func %u %u \"%s\", %u, %u",
              ivl_file_table_index(ivl_expr_file(fnet)),
	      ivl_expr_lineno(fnet), ivl_expr_name(fnet), res.base, res.wid);

      draw_vpi_taskfunc_args(call_string, 0, fnet);

      return res;
}
示例#8
0
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;
}
示例#9
0
struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid)
{
      unsigned swid = ivl_expr_width(expr);
      ivl_scope_t def = ivl_expr_def(expr);
      ivl_signal_t retval = ivl_scope_port(def, 0);
      struct vector_info res;
      unsigned load_wid;

	/* Take in arguments to function and call function code. */
      draw_ufunc_preamble(expr);

	/* Fresh basic block starts after the join. */
      clear_expression_lookaside();

	/* The return value is in a signal that has the name of the
	   expression. Load that into the thread and return the
	   vector result. */

      res.base = allocate_vector(wid);
      res.wid  = wid;
      if (res.base == 0) {
	    fprintf(stderr, "%s:%u: vvp.tgt error: "
		    "Unable to allocate %u thread bits for function result.\n",
		    ivl_expr_file(expr), ivl_expr_lineno(expr), wid);
	    vvp_errors += 1;
	    return res;
      }

      assert(res.base != 0);

      load_wid = swid;
      if (load_wid > ivl_signal_width(retval))
	    load_wid = ivl_signal_width(retval);

      assert(ivl_signal_dimensions(retval) == 0);
      fprintf(vvp_out, "    %%load/v  %u, v%p_0, %u;\n",
	      res.base, retval, load_wid);

	/* Pad the signal value with zeros. */
      if (load_wid < wid)
	    pad_expr_in_place(expr, res, swid);

      draw_ufunc_epilogue(expr);
      return res;
}
示例#10
0
文件: expr.c 项目: nickg/iverilog
static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      char *oper = "invalid";
      switch (ivl_expr_opcode(expr)) {
	case '-': oper = "-"; break;
	case '~': oper = "~"; break;
	case '&': oper = "&"; break;
	case '|': oper = "|"; break;
	case '^': oper = "^"; break;
	case 'A': oper = "~&"; break;
	case 'N': oper = "~|"; break;
	case 'X': oper = "~^"; break;
	case '!': oper = "!"; break;
      }
      switch (ivl_expr_opcode(expr)) {
	case '-':
	case '~':
	case '&':
	case '|':
	case '^':
	case 'A':
	case 'N':
	case 'X':
	case '!':
	    fprintf(vlog_out, "(%s", oper);
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, ")");
	    break;
	case '2':
	case 'i':
	case 'r':
	    /* A cast is a noop. */
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    break;
	default:
	    fprintf(vlog_out, "<unknown>");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown unary "
	                    "operator (%c).\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr),
	                    ivl_expr_opcode(expr));
	    break;
      }
}
示例#11
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);
      }
}
示例#12
0
static void draw_unary_vec4(ivl_expr_t expr)
{
      ivl_expr_t sub = ivl_expr_oper1(expr);

      if (debug_draw) {
	    fprintf(vvp_out, " ; %s:%u:draw_unary_vec4: opcode=%c\n",
		    ivl_expr_file(expr), ivl_expr_lineno(expr),
		    ivl_expr_opcode(expr));
      }

      switch (ivl_expr_opcode(expr)) {
	  case '&':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%and/r;\n");
	    break;

	  case '|':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%or/r;\n");
	    break;

	  case '^':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%xor/r;\n");
	    break;

	  case '~':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%inv;\n");
	    break;

	  case '!':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%nor/r;\n");
	    break;

	  case '-':
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%inv;\n");
	    fprintf(vvp_out, "    %%pushi/vec4 1, 0, %u;\n", ivl_expr_width(sub));
	    fprintf(vvp_out, "    %%add;\n");
	    break;

	  case 'A': /* nand (~&) */
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%nand/r;\n");
	    break;

	  case 'D': /* pre-decrement (--x) */
	    draw_unary_inc_dec(sub, false, true);
	    break;

	  case 'd': /* post_decrement (x--) */
	    draw_unary_inc_dec(sub, false, false);
	    break;

	  case 'I': /* pre-increment (++x) */
	    draw_unary_inc_dec(sub, true, true);
	    break;

	  case 'i': /* post-increment (x++) */
	    draw_unary_inc_dec(sub, true, false);
	    break;

	  case 'N': /* nor (~|) */
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%nor/r;\n");
	    break;

	  case 'X': /* xnor (~^) */
	    draw_eval_vec4(sub);
	    fprintf(vvp_out, "    %%xnor/r;\n");
	    break;

	  case 'm': /* abs(m) */
	    draw_eval_vec4(sub);
	    if (! ivl_expr_signed(sub))
		  break;

	      /* Test if (m) < 0 */
	    fprintf(vvp_out, "    %%dup/vec4;\n");
	    fprintf(vvp_out, "    %%pushi/vec4 0, 0, %u;\n", ivl_expr_width(sub));
	    fprintf(vvp_out, "    %%cmp/s;\n");
	    fprintf(vvp_out, "    %%jmp/0xz T_%u.%u, 5;\n", thread_count, local_count);
	      /* If so, calculate -(m) */
	    fprintf(vvp_out, "    %%inv;\n");
	    fprintf(vvp_out, "    %%pushi/vec4 1, 0, %u;\n", ivl_expr_width(sub));
	    fprintf(vvp_out, "    %%add;\n");
	    fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_count);
	    local_count += 1;
	    break;

	  case 'v': /* Cast real to vec4 */
	    assert(ivl_expr_value(sub) == IVL_VT_REAL);
	    draw_eval_real(sub);
	    fprintf(vvp_out, "    %%cvt/vr %u;\n", ivl_expr_width(expr));
	    break;

	  case '2': /* Cast expression to bool */
	    switch (ivl_expr_value(sub)) {
		case IVL_VT_LOGIC:
		  draw_eval_vec4(sub);
		  fprintf(vvp_out, "    %%cast2;\n");
		  resize_vec4_wid(sub, ivl_expr_width(expr));
		  break;
		case IVL_VT_BOOL:
		  draw_eval_vec4(sub);
		  resize_vec4_wid(sub, ivl_expr_width(expr));
		  break;
		case IVL_VT_REAL:
		  draw_eval_real(sub);
		  fprintf(vvp_out, "    %%cvt/vr %u;\n", ivl_expr_width(expr));
		  break;
		default:
		  assert(0);
		  break;
	    }
	    break;

	  default:
	    fprintf(stderr, "XXXX Unary operator %c not implemented\n", ivl_expr_opcode(expr));
	    break;
      }
}
示例#13
0
struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid)
{
      unsigned idx;
      unsigned swid = ivl_expr_width(expr);
      ivl_scope_t def = ivl_expr_def(expr);
      ivl_signal_t retval = ivl_scope_port(def, 0);
      struct vector_info res;
      unsigned load_wid;

        /* If this is an automatic function, allocate the local storage. */
      if (ivl_scope_is_auto(def)) {
            fprintf(vvp_out, "    %%alloc S_%p;\n", def);
      }

	/* evaluate the expressions and send the results to the
	   function ports. */

      assert(ivl_expr_parms(expr) == (ivl_scope_ports(def)-1));
      for (idx = 0 ;  idx < ivl_expr_parms(expr) ;  idx += 1) {
	    ivl_signal_t port = ivl_scope_port(def, idx+1);
	    draw_function_argument(port, ivl_expr_parm(expr, idx));
      }


	/* Call the function */
      fprintf(vvp_out, "    %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
      fprintf(vvp_out, ", S_%p;\n", def);
      fprintf(vvp_out, "    %%join;\n");

	/* Fresh basic block starts after the join. */
      clear_expression_lookaside();

	/* The return value is in a signal that has the name of the
	   expression. Load that into the thread and return the
	   vector result. */

      res.base = allocate_vector(wid);
      res.wid  = wid;
      if (res.base == 0) {
	    fprintf(stderr, "%s:%u: vvp.tgt error: "
		    "Unable to allocate %u thread bits for function result.\n",
		    ivl_expr_file(expr), ivl_expr_lineno(expr), wid);
	    vvp_errors += 1;
	    return res;
      }

      assert(res.base != 0);

      load_wid = swid;
      if (load_wid > ivl_signal_width(retval))
	    load_wid = ivl_signal_width(retval);

      assert(ivl_signal_dimensions(retval) == 0);
      fprintf(vvp_out, "    %%load/v  %u, v%p_0, %u;\n",
	      res.base, retval, load_wid);

	/* Pad the signal value with zeros. */
      if (load_wid < wid)
	    pad_expr_in_place(expr, res, swid);

        /* If this is an automatic function, free the local storage. */
      if (ivl_scope_is_auto(def)) {
            fprintf(vvp_out, "    %%free S_%p;\n", def);
      }

      return res;
}
示例#14
0
static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      char *oper = "invalid";
      switch (ivl_expr_opcode(expr)) {
	case '-': oper = "-"; break;
	case '~': oper = "~"; break;
	case '&': oper = "&"; break;
	case '|': oper = "|"; break;
	case '^': oper = "^"; break;
	case 'A': oper = "~&"; break;
	case 'N': oper = "~|"; break;
	case 'X': oper = "~^"; break;
	case '!': oper = "!"; break;
      }
      switch (ivl_expr_opcode(expr)) {
	case '-':
	case '~':
	case '&':
	case '|':
	case '^':
	case 'A':
	case 'N':
	case 'X':
	case '!':
	    fprintf(vlog_out, "(%s", oper);
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, ")");
	    break;
	case '2':
	case 'v':
	case 'r':
	    /* A cast is a noop. */
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    break;
	case 'I':
	    fprintf(vlog_out, "(++");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, ")");
	    fprintf(stderr, "%s:%u: vlog95 sorry: Pre-increment "
	                    "operator is not currently translated.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	case 'i':
	    fprintf(vlog_out, "(");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, "++)");
	    fprintf(stderr, "%s:%u: vlog95 sorry: Pre-increment "
	                    "operator is not currently translated.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	case 'D':
	    fprintf(vlog_out, "(--");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, ")");
	    fprintf(stderr, "%s:%u: vlog95 sorry: Pre-decrement "
	                    "operator is not currently translated.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	case 'd':
	    fprintf(vlog_out, "(");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, "--)");
	    fprintf(stderr, "%s:%u: vlog95 sorry: Pre-decrement "
	                    "operator is not currently translated.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	default:
	    fprintf(vlog_out, "<unknown>");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown unary "
	                    "operator (%c).\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr),
	                    ivl_expr_opcode(expr));
	    vlog_errors += 1;
	    break;
      }
}
示例#15
0
/*
 * Emit a constant or variable delay that has been rescaled to the given
 * scopes timescale.
 */
void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
{
      ivl_expr_type_t type = ivl_expr_type(expr);
      if (type == IVL_EX_DELAY) {
	    emit_scaled_delay(scope, ivl_expr_delay_val(expr));
      } else if (type == IVL_EX_NUMBER) {
	    assert(! ivl_expr_signed(expr));
	    int rtype;
	    uint64_t value = get_uint64_from_number(expr, &rtype);
	    if (rtype > 0) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Time value is "
		                  "greater than 64 bits (%u) and cannot be "
		                  "safely represented.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr),
		                  rtype);
		  vlog_errors += 1;
		  return;
	    }
	    if (rtype < 0) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Time value has an "
		                  "undefined bit and cannot be represented.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
		  vlog_errors += 1;
		  return;
	    }
	    emit_scaled_delay(scope, value);
      } else {
	    int exponent = ivl_scope_time_units(scope) - sim_precision;
	    assert(exponent >= 0);
	    if ((exponent == 0) && (type == IVL_EX_SIGNAL)) {
		  emit_delay(scope, expr, is_stmt);
	      /* A real delay variable is not scaled by the compiler. */
	    } else if (type == IVL_EX_SIGNAL) {
		  if (is_stmt) {
			fprintf(vlog_out, "<invalid>");
			fprintf(stderr, "%s:%u: vlog95 error: Only continuous "
			                "assignment delay variables are scaled "
			                "at run time.\n", ivl_expr_file(expr),
			                ivl_expr_lineno(expr));
			vlog_errors += 1;
			return;
		  }
		  emit_delay(scope, expr, is_stmt);
	    } else {
		  uint64_t iscale = 1;
		  unsigned rtn;
		  assert(! ivl_expr_signed(expr));
		    /* Calculate the integer time scaling coefficient. */
		  while (exponent > 0) {
			iscale *= 10;
			exponent -= 1;
		  }
		    /* Check to see if this is an integer time value. */
		  rtn = check_scaled_expr(expr, iscale, "Variable time", 0);
		    /* This may be a scaled real value. */
		  if (rtn == 2){
			ivl_expr_t tmp_expr;
			uint64_t rprec = 1;
			  /* This could be a scaled real time so calculate
			   * the real time scaling coefficients and check
			   * that the expression matches (statements only). */
			exponent = ivl_scope_time_precision(scope) -
			           sim_precision;
			assert(exponent >= 0);
			while (exponent > 0) {
			      rprec *= 10;
			      exponent -= 1;
			}
			  /* Verify that the precision scaling is correct. */
			if (! check_scaled_expr(expr, rprec,
			                        "Variable real time prec.",
			                        1)) {
			      fprintf(vlog_out, "<invalid>");
			      return;
			}
			  /* Verify that the left operator is a real to
			   * integer cast. */
			tmp_expr = ivl_expr_oper1(expr);
			if ((ivl_expr_type(tmp_expr) != IVL_EX_UNARY) ||
		            (ivl_expr_opcode(tmp_expr) != 'v')) {
			      fprintf(vlog_out, "<invalid>");
			      fprintf(stderr, "%s:%u: vlog95 error: Real time "
			                      "value does not have a cast to "
			                      "integer.\n",
			                      ivl_expr_file(expr),
			                      ivl_expr_lineno(expr));
			      vlog_errors += 1;
			      return;
			}
			  /* Check that the cast value is scaled correctly. */
			assert(iscale >= rprec);
			tmp_expr = ivl_expr_oper1(tmp_expr);
			assert(ivl_expr_value(tmp_expr) == IVL_VT_REAL);
			if (! check_scaled_real_expr(tmp_expr, iscale/rprec)) {
			      fprintf(vlog_out, "<invalid>");
			      return;
			}
			assert(is_stmt);
			emit_delay(scope, ivl_expr_oper1(tmp_expr), is_stmt);
			return;
		  } else if (rtn == 1) {
			emit_delay(scope, ivl_expr_oper1(expr), is_stmt);
			return;
		  }
		  fprintf(vlog_out, "<invalid>");
	    }
      }
}
示例#16
0
void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      switch (ivl_expr_type(expr)) {
	case IVL_EX_ARRAY:
	    emit_expr_array(scope, expr, wid);
	    break;
	case IVL_EX_BINARY:
	    emit_expr_binary(scope, expr, wid);
	    break;
	case IVL_EX_CONCAT:
	    emit_expr_concat(scope, expr, wid);
	    break;
	case IVL_EX_DELAY:
	    emit_expr_delay(scope, expr, wid);
	    break;
	case IVL_EX_ENUMTYPE:
	    fprintf(vlog_out, "<enum>");
	    fprintf(stderr, "%s:%u: vlog95 error: Enum expressions "
	                    "are not supported.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	case IVL_EX_EVENT:
	    emit_expr_event(scope, expr, wid);
	    break;
	case IVL_EX_NUMBER:
	    emit_number(ivl_expr_bits(expr), ivl_expr_width(expr),
	                ivl_expr_signed(expr), ivl_expr_file(expr),
	                ivl_expr_lineno(expr));
	    break;
	case IVL_EX_REALNUM:
	    emit_real_number(ivl_expr_dvalue(expr));
	    break;
	case IVL_EX_SCOPE:
	    emit_expr_scope(scope, expr, wid);
	    break;
	case IVL_EX_SELECT:
	    emit_expr_select(scope, expr, wid);
	    break;
	case IVL_EX_SFUNC:
	    fprintf(vlog_out, "%s", ivl_expr_name(expr));
	    emit_expr_func(scope, expr, wid);
	    break;
	case IVL_EX_SIGNAL:
	    emit_expr_signal(scope, expr, wid);
	    break;
	case IVL_EX_STRING:
	    emit_string(ivl_expr_string(expr));
	    break;
	case IVL_EX_TERNARY:
	    emit_expr_ternary(scope, expr, wid);
	    break;
	case IVL_EX_UFUNC:
	    emit_scope_path(scope, ivl_expr_def(expr));
	    emit_expr_func(scope, expr, wid);
	    break;
	case IVL_EX_UNARY:
	    emit_expr_unary(scope, expr, wid);
	    break;
	default:
	    fprintf(vlog_out, "<unknown>");
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown expression "
	                    "type (%d).\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr),
	                    (int)ivl_expr_type(expr));
	    vlog_errors += 1;
	    break;
      }
}
示例#17
0
void show_expression(ivl_expr_t net, unsigned ind)
{
      assert(net);
      unsigned idx;
      ivl_parameter_t par = ivl_expr_parameter(net);
      const ivl_expr_type_t code = ivl_expr_type(net);
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*sized = ivl_expr_sized(net)? "sized" : "unsized";
      const char*vt = vt_type_string(net);

      switch (code) {

	  case IVL_EX_ARRAY:
	    show_array_expression(net, ind);
	    break;

	  case IVL_EX_ARRAY_PATTERN:
	    show_array_pattern_expression(net, ind);
	    break;

	  case IVL_EX_BACCESS:
	    show_branch_access_expression(net, ind);
	    break;

	  case IVL_EX_BINARY:
	    show_binary_expression(net, ind);
	    break;

	  case IVL_EX_CONCAT:
	    fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
		    ind, "", ivl_expr_repeat(net), width, sign, vt);
	    for (idx = 0 ;  idx < ivl_expr_parms(net) ;  idx += 1)
		  show_expression(ivl_expr_parm(net, idx), ind+3);

	    break;

	  case IVL_EX_ENUMTYPE:
	    show_enumtype_expression(net, ind);
	    break;

	  case IVL_EX_MEMORY:
	    show_memory_expression(net, ind);
	    break;

	  case IVL_EX_NEW:
	    show_new_expression(net, ind);
	    break;

	  case IVL_EX_NULL:
	    show_null_expression(net, ind);
	    break;

	  case IVL_EX_PROPERTY:
	    show_property_expression(net, ind);
	    break;

	  case IVL_EX_NUMBER: {
		const char*bits = ivl_expr_bits(net);

		fprintf(out, "%*s<number=%u'b", ind, "", width);
		for (idx = width ;  idx > 0 ;  idx -= 1)
		      fprintf(out, "%c", bits[idx-1]);

		fprintf(out, ", %s %s %s", sign, sized, vt);
		if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

		fprintf(out, ">\n");
		break;
	  }

	  case IVL_EX_SELECT:
	    show_select_expression(net, ind);
	    break;

	  case IVL_EX_STRING:
	    fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
		    ivl_expr_string(net), ivl_expr_width(net));
	    if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

	    fprintf(out, ", type=%s>\n", vt);
	    break;

	  case IVL_EX_SFUNC:
	    fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s file=%s:%u>\n",
		    ind, "", ivl_expr_name(net), width, sign, vt,
		    ivl_expr_file(net), ivl_expr_lineno(net));
	    { unsigned cnt = ivl_expr_parms(net);
	      unsigned jdx;
	      for (jdx = 0 ;  jdx < cnt ;  jdx += 1)
		    show_expression(ivl_expr_parm(net, jdx), ind+3);
	    }
	    break;

	  case IVL_EX_SIGNAL:
	    show_signal_expression(net, ind);
	    break;

	  case IVL_EX_TERNARY:
	    show_ternary_expression(net, ind);
	    break;

	  case IVL_EX_UNARY:
	    show_unary_expression(net, ind);
	    break;

	  case IVL_EX_UFUNC:
	    show_function_call(net, ind);
	    break;

	  case IVL_EX_REALNUM:
	      {
		    int jdx;
		    union foo {
			  double rv;
			  unsigned char bv[sizeof(double)];
		    } tmp;
		    tmp.rv = ivl_expr_dvalue(net);
		    fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
		    for (jdx = sizeof(double) ;  jdx > 0 ;  jdx -= 1)
			  fprintf(out, "%02x", tmp.bv[jdx-1]);
		    fprintf(out, ")");
		    if (par != 0)
			  fprintf(out, ", parameter=%s",
				  ivl_parameter_basename(par));

		    fprintf(out, ">\n");
	      }
	      break;

	  case IVL_EX_SHALLOWCOPY:
	    show_shallowcopy(net, ind);
	    break;

	  default:
	    fprintf(out, "%*s<expr_type=%d>\n", ind, "", code);
	    break;
      }
}
示例#18
0
static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      char *oper = "<invalid>";
      switch (ivl_expr_opcode(expr)) {
	case '+': oper = "+"; break;
	case '-': oper = "-"; break;
	case '*': oper = "*"; break;
	case '/': oper = "/"; break;
	case '%': oper = "%"; break;
	case 'p': oper = "**"; break;
	case 'E': oper = "==="; break;
	case 'e': oper = "=="; break;
	case 'N': oper = "!=="; break;
	case 'n': oper = "!="; break;
	case '<': oper = "<"; break;
	case 'L': oper = "<="; break;
	case '>': oper = ">"; break;
	case 'G': oper = ">="; break;
	case '&': oper = "&"; break;
	case '|': oper = "|"; break;
	case '^': oper = "^"; break;
	case 'A': oper = "&"; break;
	case 'O': oper = "|"; break;
	case 'X': oper = "~^"; break;
	case 'a': oper = "&&"; break;
	case 'o': oper = "||"; break;
	case 'l': oper = "<<"; break;
	case 'r': oper = ">>"; break;
	case 'R': oper = ">>>"; break;
      }

      fprintf(vlog_out, "(");
      switch (ivl_expr_opcode(expr)) {
	case '%':
	    if (ivl_expr_value(expr) == IVL_VT_REAL) {
		  fprintf(stderr, "%s:%u: vlog95 error: Real modulus operator "
		                  "is not supported.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
		  vlog_errors += 1;
	    }
	case '+':
	case '-':
	case '*':
	case '/':
	case 'E':
	case 'e':
	case 'N':
	case 'n':
	case '<':
	case 'L':
	case '>':
	case 'G':
	case '&':
	case '|':
	case '^':
	case 'X':
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, " %s ", oper);
	    emit_expr(scope, ivl_expr_oper2(expr), wid);
	    break;
	case 'a':
	case 'o':
	    emit_expr(scope, ivl_expr_oper1(expr), 0);
	    fprintf(vlog_out, " %s ", oper);
	    emit_expr(scope, ivl_expr_oper2(expr), 0);
	    break;
	case 'R':
	    if (! allow_signed) {
		  fprintf(stderr, "%s:%u: vlog95 error: >>> operator is not "
		                  "supported.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
		  vlog_errors += 1;
	    }
	case 'l':
	case 'r':
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, " %s ", oper);
	    emit_expr(scope, ivl_expr_oper2(expr), 0);
	    break;
	case 'A':
	case 'O':
	    fprintf(vlog_out, "~(");
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, " %s ", oper);
	    emit_expr(scope, ivl_expr_oper2(expr), wid);
	    fprintf(vlog_out, ")");
	    break;
	case 'p':
	    if (! emit_power_as_shift(scope, expr, wid)) {
		  emit_expr(scope, ivl_expr_oper1(expr), wid);
		  fprintf(vlog_out, " ** ");
		  emit_expr(scope, ivl_expr_oper2(expr), 0);
		  fprintf(stderr, "%s:%u: vlog95 error: Power operator is not "
		                  "supported.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
		  vlog_errors += 1;
	    }
	    break;
	default:
	    emit_expr(scope, ivl_expr_oper1(expr), wid);
	    fprintf(vlog_out, "<unknown>");
	    emit_expr(scope, ivl_expr_oper2(expr), wid);
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown expression "
	                    "operator (%c).\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr),
	                    ivl_expr_opcode(expr));
	    vlog_errors += 1;
	    break;
      }
      fprintf(vlog_out, ")");
}
示例#19
0
static int show_stmt_assign_vector(ivl_statement_t net)
{
      ivl_expr_t rval = ivl_stmt_rval(net);
      struct vector_info res;
      struct vector_info lres = {0, 0};
      struct vec_slice_info*slices = 0;

	/* If this is a compressed assignment, then get the contents
	   of the l-value. We need these values as part of the r-value
	   calculation. */
      if (ivl_stmt_opcode(net) != 0) {
	    slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info));
	    lres = get_vec_from_lval(net, slices);
      }

	/* Handle the special case that the expression is a real
	   value. Evaluate the real expression, then convert the
	   result to a vector. Then store that vector into the
	   l-value. */
      if (ivl_expr_value(rval) == IVL_VT_REAL) {
	    draw_eval_real(rval);
	      /* This is the accumulated with of the l-value of the
		 assignment. */
	    unsigned wid = ivl_stmt_lwidth(net);

	    res.base = allocate_vector(wid);
	    res.wid = wid;

	    if (res.base == 0) {
		  fprintf(stderr, "%s:%u: vvp.tgt error: "
			  "Unable to allocate %u thread bits for "
			  "r-value expression.\n", ivl_expr_file(rval),
			  ivl_expr_lineno(rval), wid);
		  vvp_errors += 1;
	    }

	    fprintf(vvp_out, "    %%cvt/vr %u, %u;\n", res.base, res.wid);

      } else {
	    res = draw_eval_expr(rval, 0);
      }

      switch (ivl_stmt_opcode(net)) {
	  case 0:
	    set_vec_to_lval(net, res);
	    break;

	  case '+':
	    if (res.base > 3) {
		  fprintf(vvp_out, "    %%add %u, %u, %u;\n",
			  res.base, lres.base, res.wid);
		  clr_vector(lres);
	    } else {
		  fprintf(vvp_out, "    %%add %u, %u, %u;\n",
			  lres.base, res.base, res.wid);
		  res.base = lres.base;
	    }
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '-':
	    fprintf(vvp_out, "    %%sub %u, %u, %u;\n",
		    lres.base, res.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    clr_vector(lres);
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '*':
	    if (res.base > 3) {
		  fprintf(vvp_out, "    %%mul %u, %u, %u;\n",
			  res.base, lres.base, res.wid);
		  clr_vector(lres);
	    } else {
		  fprintf(vvp_out, "    %%mul %u, %u, %u;\n",
			  lres.base, res.base, res.wid);
		  res.base = lres.base;
	    }
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '/':
	    fprintf(vvp_out, "    %%div%s %u, %u, %u;\n",
		    ivl_expr_signed(rval)? "/s" : "",
		    lres.base, res.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    clr_vector(lres);
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '%':
	    fprintf(vvp_out, "    %%mod%s %u, %u, %u;\n",
		    ivl_expr_signed(rval)? "/s" : "",
		    lres.base, res.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    clr_vector(lres);
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '&':
	    if (res.base > 3) {
		  fprintf(vvp_out, "    %%and %u, %u, %u;\n",
			  res.base, lres.base, res.wid);
		  clr_vector(lres);
	    } else {
		  fprintf(vvp_out, "    %%and %u, %u, %u;\n",
			  lres.base, res.base, res.wid);
		  res.base = lres.base;
	    }
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '|':
	    if (res.base > 3) {
		  fprintf(vvp_out, "    %%or %u, %u, %u;\n",
			  res.base, lres.base, res.wid);
		  clr_vector(lres);
	    } else {
		  fprintf(vvp_out, "    %%or %u, %u, %u;\n",
			  lres.base, res.base, res.wid);
		  res.base = lres.base;
	    }
	    put_vec_to_lval(net, slices, res);
	    break;

	  case '^':
	    if (res.base > 3) {
		  fprintf(vvp_out, "    %%xor %u, %u, %u;\n",
			  res.base, lres.base, res.wid);
		  clr_vector(lres);
	    } else {
		  fprintf(vvp_out, "    %%xor %u, %u, %u;\n",
			  lres.base, res.base, res.wid);
		  res.base = lres.base;
	    }
	    put_vec_to_lval(net, slices, res);
	    break;

	  case 'l': /* lres <<= res */
	    fprintf(vvp_out, "    %%ix/get 0, %u, %u;\n", res.base, res.wid);
	    fprintf(vvp_out, "    %%shiftl/i0 %u, %u;\n", lres.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    break;

	  case 'r': /* lres >>= res */
	    fprintf(vvp_out, "    %%ix/get 0, %u, %u;\n", res.base, res.wid);
	    fprintf(vvp_out, "    %%shiftr/i0 %u, %u;\n", lres.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    break;

	  case 'R': /* lres >>>= res */
	    fprintf(vvp_out, "    %%ix/get 0, %u, %u;\n", res.base, res.wid);
	    fprintf(vvp_out, "    %%shiftr/s/i0 %u, %u;\n", lres.base, res.wid);
	    fprintf(vvp_out, "    %%mov %u, %u, %u;\n",
		    res.base, lres.base, res.wid);
	    break;

	  default:
	    fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
	    assert(0);
	    break;
      }

      if (slices)
	    free(slices);
      if (res.base > 3)
	    clr_vector(res);

      return 0;
}
示例#20
0
void draw_eval_vec4(ivl_expr_t expr)
{
      if (debug_draw) {
	    fprintf(vvp_out, " ; %s:%u:draw_eval_vec4: expr_type=%d\n",
		    ivl_expr_file(expr), ivl_expr_lineno(expr),
		    ivl_expr_type(expr));
      }

      switch (ivl_expr_type(expr)) {
	  case IVL_EX_BINARY:
	    draw_binary_vec4(expr);
	    return;

	  case IVL_EX_CONCAT:
	    draw_concat_vec4(expr);
	    return;

	  case IVL_EX_NUMBER:
	    draw_number_vec4(expr);
	    return;

	  case IVL_EX_SELECT:
	    if (ivl_expr_oper2(expr)==0)
		  draw_select_pad_vec4(expr);
	    else
		  draw_select_vec4(expr);
	    return;

	  case IVL_EX_SFUNC:
	    draw_sfunc_vec4(expr);
	    return;

	  case IVL_EX_SIGNAL:
	    draw_signal_vec4(expr);
	    return;

	  case IVL_EX_STRING:
	    draw_string_vec4(expr);
	    return;

	  case IVL_EX_TERNARY:
	    draw_ternary_vec4(expr);
	    return;

	  case IVL_EX_UFUNC:
	    draw_ufunc_vec4(expr);
	    return;

	  case IVL_EX_UNARY:
	    draw_unary_vec4(expr);
	    return;

	  case IVL_EX_PROPERTY:
	    draw_property_vec4(expr);
	    return;

	  default:
	    break;
      }

      fprintf(stderr, "XXXX Evaluate VEC4 expression (%d)\n", ivl_expr_type(expr));
      fprintf(vvp_out, "; XXXX Evaluate VEC4 expression (%d)\n", ivl_expr_type(expr));
}
示例#21
0
void show_expression(ivl_expr_t net, unsigned ind)
{
      unsigned idx;
      const ivl_expr_type_t code = ivl_expr_type(net);
      ivl_parameter_t par = ivl_expr_parameter(net);
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*sized = ivl_expr_sized(net)? "sized" : "unsized";
      const char*vt = vt_type_string(net);

      switch (code) {

	  case IVL_EX_ARRAY:
	    show_array_expression(net, ind);
	    break;

	  case IVL_EX_BACCESS:
	    show_branch_access_expression(net, ind);
	    break;

	  case IVL_EX_BINARY:
	    show_binary_expression(net, ind);
	    break;

	  case IVL_EX_CONCAT:
	    fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
		    ind, "", ivl_expr_repeat(net), width, sign, vt);
	    for (idx = 0 ;  idx < ivl_expr_parms(net) ;  idx += 1)
		  show_expression(ivl_expr_parm(net, idx), ind+3);

	    break;

	  case IVL_EX_MEMORY:
	    show_memory_expression(net, ind);
	    break;

	  case IVL_EX_NUMBER: {
		const char*bits = ivl_expr_bits(net);

		fprintf(out, "%*s<number=%u'b", ind, "", width);
		for (idx = width ;  idx > 0 ;  idx -= 1)
		      fprintf(out, "%c", bits[idx-1]);

		fprintf(out, ", %s %s %s", sign, sized, vt);
		if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

		fprintf(out, ">\n");
		break;
	  }

	  case IVL_EX_SELECT:
	      /* The SELECT expression can be used to express part
		 select, or if the base is null vector extension. */
	    if (ivl_expr_oper2(net)) {
		  fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
			  width, sign);
		  show_expression(ivl_expr_oper1(net), ind+3);
		  show_expression(ivl_expr_oper2(net), ind+3);
	    } else {
		  fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
			  width, sign);
		  show_expression(ivl_expr_oper1(net), ind+3);
	    }
	    break;

	  case IVL_EX_STRING:
	    fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
		    ivl_expr_string(net), ivl_expr_width(net));
	    if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

	    fprintf(out, ", type=%s>\n", vt);
	    break;

	  case IVL_EX_SFUNC:
	    fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s file=%s:%u>\n",
		    ind, "", ivl_expr_name(net), width, sign, vt,
		    ivl_expr_file(net), ivl_expr_lineno(net));
	    { unsigned cnt = ivl_expr_parms(net);
	      unsigned jdx;
	      for (jdx = 0 ;  jdx < cnt ;  jdx += 1)
		    show_expression(ivl_expr_parm(net, jdx), ind+3);
	    }
	    break;

	  case IVL_EX_SIGNAL:
	    show_signal_expression(net, ind);
	    break;

	  case IVL_EX_TERNARY:
	    show_ternary_expression(net, ind);
	    break;

	  case IVL_EX_UNARY:
	    show_unary_expression(net, ind);
	    break;

	  case IVL_EX_UFUNC:
	    show_function_call(net, ind);
	    break;

	  case IVL_EX_REALNUM:
	      {
		    int jdx;
		    union foo {
			  double rv;
			  unsigned char bv[sizeof(double)];
		    } tmp;
		    tmp.rv = ivl_expr_dvalue(net);
		    fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
		    for (jdx = sizeof(double) ;  jdx > 0 ;  jdx -= 1)
			  fprintf(out, "%02x", tmp.bv[jdx-1]);
		    fprintf(out, ")");
		    if (par != 0)
			  fprintf(out, ", parameter=%s",
				  ivl_parameter_basename(par));

		    fprintf(out, ">\n");
	      }
	      break;

	  default:
	    fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
	    break;
      }
}