示例#1
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);
}
示例#2
0
static void draw_select_vec4(ivl_expr_t expr)
{
	// This is the sub-expression to part-select.
      ivl_expr_t subexpr = ivl_expr_oper1(expr);
	// This is the base of the part select
      ivl_expr_t base = ivl_expr_oper2(expr);
	// This is the part select width
      unsigned wid = ivl_expr_width(expr);
	// Is the select base expression signed or unsigned?
      char sign_suff = ivl_expr_signed(base)? 's' : 'u';

	// Special Case: If the sub-expression is a STRING, then this
	// is a select from that string.
      if (ivl_expr_value(subexpr)==IVL_VT_STRING) {
	    assert(base);
	    assert(wid==8);
	    draw_eval_string(subexpr);
	    int base_idx = allocate_word();
	    draw_eval_expr_into_integer(base, base_idx);
	    fprintf(vvp_out, "    %%substr/vec4 %d, %u;\n", base_idx, wid);
	    fprintf(vvp_out, "    %%pop/str 1;\n");
	    clr_word(base_idx);
	    return;
      }

      if (ivl_expr_value(subexpr)==IVL_VT_DARRAY) {
	    ivl_signal_t sig = ivl_expr_signal(subexpr);
	    assert(sig);
	    assert( (ivl_signal_data_type(sig)==IVL_VT_DARRAY)
		    || (ivl_signal_data_type(sig)==IVL_VT_QUEUE) );

	    assert(base);
	    draw_eval_expr_into_integer(base, 3);
	    fprintf(vvp_out, "    %%load/dar/vec4 v%p_0;\n", sig);

	    return;
      }

      if (test_immediate_vec4_ok(base)) {
	    unsigned long val0, valx;
	    unsigned base_wid;
	    make_immediate_vec4_words(base, &val0, &valx, &base_wid);
	    assert(valx == 0);

	    draw_eval_vec4(subexpr);
	    fprintf(vvp_out, "    %%parti/%c %u, %lu, %u;\n",
		    sign_suff, wid, val0, base_wid);

      } else {
	    draw_eval_vec4(subexpr);
	    draw_eval_vec4(base);
	    fprintf(vvp_out, "    %%part/%c %u;\n", sign_suff, wid);
      }
}
示例#3
0
void show_unary_expression(ivl_expr_t net, unsigned ind)
{
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*vt = vt_type_string(net);

      char name[8];
      switch (ivl_expr_opcode(net)) {
	  default:
	    snprintf(name, sizeof name, "%c", ivl_expr_opcode(net));
	    break;

	  case 'm':
	    snprintf(name, sizeof name, "abs()");
	    break;
      }

      if (ivl_expr_opcode(net) == '!' && ivl_expr_value(net) == IVL_VT_REAL) {
	    fprintf(out, "%*sERROR: Real argument to unary ! !?\n", ind,"");
	    stub_errors += 1;
      }

      fprintf(out, "%*s<unary \"%s\" width=%u, %s, type=%s>\n", ind, "",
	      name, width, sign, vt);
      show_expression(ivl_expr_oper1(net), ind+4);
}
/*
 * The delayx statement is slightly more complex in that it is
 * necessary to calculate the delay first. Load the calculated delay
 * into and index register and use the %delayx instruction to do the
 * actual delay.
 */
static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
{
      int rc = 0;
      ivl_expr_t exp = ivl_stmt_delay_expr(net);
      ivl_statement_t stmt = ivl_stmt_sub_stmt(net);

      switch (ivl_expr_value(exp)) {

	  case IVL_VT_VECTOR: {
		struct vector_info del = draw_eval_expr(exp, 0);
		fprintf(vvp_out, "    %%ix/get 0, %u, %u;\n",
			del.base, del.wid);
		clr_vector(del);
		break;
	  }

	  case IVL_VT_REAL: {
		int word = draw_eval_real(exp);
		fprintf(vvp_out, "    %%cvt/ir 0, %d;\n", word);
		clr_word(word);
		break;
	  }

	  default:
	    assert(0);
      }

      fprintf(vvp_out, "    %%delayx 0;\n");
	/* Lots of things can happen during a delay. */
      clear_expression_lookaside();

      rc += show_statement(stmt, sscope);
      return rc;
}
示例#5
0
static void draw_ufunc_preamble(ivl_expr_t expr)
{
    ivl_scope_t def = ivl_expr_def(expr);
    unsigned idx;

    /* 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. Do this in two passes - evaluate,
       then send - this avoids the function input variables
       being overwritten if the same (non-automatic) function
       is called in one of the expressions. */

    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_eval_function_argument(port, ivl_expr_parm(expr, idx));
    }
    for (idx = ivl_expr_parms(expr) ;  idx > 0 ;  idx -= 1) {
        ivl_signal_t port = ivl_scope_port(def, idx);
        draw_send_function_argument(port);
    }

    /* Call the function */
    switch (ivl_expr_value(expr)) {
    case IVL_VT_VOID:
        fprintf(vvp_out, "    %%callf/void TD_%s", vvp_mangle_id(ivl_scope_name(def)));
        fprintf(vvp_out, ", S_%p;\n", def);
        break;
    case IVL_VT_REAL:
        fprintf(vvp_out, "    %%callf/real TD_%s", vvp_mangle_id(ivl_scope_name(def)));
        fprintf(vvp_out, ", S_%p;\n", def);
        break;
    case IVL_VT_BOOL:
    case IVL_VT_LOGIC:
        fprintf(vvp_out, "    %%callf/vec4 TD_%s", vvp_mangle_id(ivl_scope_name(def)));
        fprintf(vvp_out, ", S_%p;\n", def);
        break;
    case IVL_VT_STRING:
        fprintf(vvp_out, "    %%callf/str TD_%s", vvp_mangle_id(ivl_scope_name(def)));
        fprintf(vvp_out, ", S_%p;\n", def);
        break;
    case IVL_VT_CLASS:
    case IVL_VT_DARRAY:
    case IVL_VT_QUEUE:
        fprintf(vvp_out, "    %%callf/obj TD_%s", vvp_mangle_id(ivl_scope_name(def)));
        fprintf(vvp_out, ", S_%p;\n", def);
        break;
    default:
        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");
        break;
    }
}
示例#6
0
static void show_null_expression(ivl_expr_t net, unsigned ind)
{
      fprintf(out, "%*s<null>\n", ind, "");
      if (ivl_expr_value(net) != IVL_VT_CLASS) {
	    fprintf(out, "%*sERROR: null expression must be IVL_VT_CLASS, got %s.\n",
		    ind+3, "", vt_type_string(net));
	    stub_errors += 1;
      }
}
示例#7
0
static void show_shallowcopy(ivl_expr_t net, unsigned ind)
{
      ivl_expr_t oper1 = ivl_expr_oper1(net);
      ivl_expr_t oper2 = ivl_expr_oper2(net);
      fprintf(out, "%*s<shallow_copy>\n", ind, "");
      show_expression(oper1, ind+3);
      show_expression(oper2, ind+3);

      if (ivl_expr_value(oper1) != ivl_expr_value(oper2)) {
	    fprintf(out, "%*sERROR: Shallow copy operand types must match.\n", ind+3,"");
	    stub_errors += 1;
      }

      if (ivl_expr_value(oper1)!=IVL_VT_CLASS && ivl_expr_value(oper1)!=IVL_VT_DARRAY) {
	    fprintf(out, "%*sERROR: Operand 1 type is %s\n", ind+3, "", vt_type_string(oper1));
	    stub_errors += 1;
      }
}
示例#8
0
static void show_binary_expression(ivl_expr_t net, unsigned ind)
{
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*vt   = vt_type_string(net);

      ivl_expr_t oper1 = ivl_expr_oper1(net);
      ivl_expr_t oper2 = ivl_expr_oper2(net);

      fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
	      ivl_expr_opcode(net), width, sign, vt);
      if (oper1) {
	    show_expression(oper1, ind+3);
      } else {
	    fprintf(out, "%*sERROR: Missing operand 1\n", ind+3, "");
	    stub_errors += 1;
      }
      if (oper2) {
	    show_expression(oper2, ind+3);
      } else {
	    fprintf(out, "%*sERROR: Missing operand 2\n", ind+3, "");
	    stub_errors += 1;
      }

      switch (ivl_expr_opcode(net)) {

	  case '*':
	    if (ivl_expr_value(net) == IVL_VT_REAL) {
		  if (ivl_expr_width(net) != 1) {
			fprintf(out, "%*sERROR: Result width incorrect. Expecting 1, got %u\n",
				ind+3, "", ivl_expr_width(net));
			stub_errors += 1;
		  }
	    } else {
		    /* The width of a multiply may be any width. The
		       implicit assumption is that the multiply
		       returns a width that is the sum of the widths
		       of the arguments, that is then truncated to the
		       desired width, never padded. The compiler will
		       automatically take care of sign extensions of
		       arguments, so that the code generator need only
		       generate an UNSIGNED multiply, and the result
		       will come out right. */
		  unsigned max_width = ivl_expr_width(oper1) + ivl_expr_width(oper2);
		  if (ivl_expr_width(net) > max_width) {
			fprintf(out, "%*sERROR: Result width to width. Expecting <= %u, got %u\n",
				ind+3, "", max_width, ivl_expr_width(net));
			stub_errors += 1;
		  }
	    }
	    break;

	  default:
	    break;
      }
}
int draw_eval_real(ivl_expr_t exp)
{
      int res = 0;

      switch (ivl_expr_type(exp)) {

	  case IVL_EX_BINARY:
	    res = draw_binary_real(exp);
	    break;

	  case IVL_EX_NUMBER:
	    res = draw_number_real(exp);
	    break;

	  case IVL_EX_REALNUM:
	    res = draw_realnum_real(exp);
	    break;

	  case IVL_EX_VARIABLE:
	    res = draw_variable_real(exp);
	    break;

	  case IVL_EX_SFUNC:
	    res = draw_sfunc_real(exp);
	    break;

	  case IVL_EX_SIGNAL:
	    res = draw_signal_real(exp);
	    break;

	  default:
	    if (ivl_expr_value(exp) == IVL_VT_VECTOR) {
		  struct vector_info sv = draw_eval_expr(exp, 0);

		  clr_vector(sv);
		  res = allocate_word();

		  fprintf(vvp_out, "    %%ix/get %d, %u, %u;\n", res,
			  sv.base, sv.wid);

		  fprintf(vvp_out, "    %%cvt/ri %d, %d;\n", res, res);

	    } else {
		  fprintf(stderr, "XXXX Evaluate real expression (%d)\n",
			  ivl_expr_type(exp));
		  fprintf(vvp_out, " ; XXXX Evaluate real expression (%d)\n",
			  ivl_expr_type(exp));
		  return 0;
	    }
	    break;
      }

      return res;
}
示例#10
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)));
      }
}
示例#11
0
int draw_eval_object(ivl_expr_t ex)
{
      switch (ivl_expr_type(ex)) {

	  case IVL_EX_NEW:
	    switch (ivl_expr_value(ex)) {
		case IVL_VT_CLASS:
		  return eval_class_new(ex);
		case IVL_VT_DARRAY:
		  return eval_darray_new(ex);
		default:
		  fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid type (%d) for <new>\n",
			  ivl_expr_value(ex));
		  return 0;
	    }

	  case IVL_EX_NULL:
	    return eval_object_null(ex);

	  case IVL_EX_PROPERTY:
	    return eval_object_property(ex);

	  case IVL_EX_SHALLOWCOPY:
	    return eval_object_shallowcopy(ex);

	  case IVL_EX_SIGNAL:
	    return eval_object_signal(ex);

	  case IVL_EX_UFUNC:
	    return eval_object_ufunc(ex);

	  default:
	    fprintf(vvp_out, "; ERROR: draw_eval_object: Invalid expression type %d\n", ivl_expr_type(ex));
	    return 1;

      }
}
示例#12
0
static void show_select_expression(ivl_expr_t net, unsigned ind)
{
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*vt = vt_type_string(net);
      ivl_expr_t oper1 = ivl_expr_oper1(net);
      ivl_expr_t oper2 = ivl_expr_oper2(net);

      if (ivl_expr_value(oper1) == IVL_VT_STRING) {
	      /* If the sub-expression is a STRING, then this is a
		 substring and the code generator will handle it
		 differently. */
	    fprintf(out, "%*s<substring: width=%u bits, %u bytes>\n", ind, "", width, width/8);
	    if (width%8 != 0) {
		  fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, "");
		  stub_errors += 1;
	    }
	    assert(oper1);
	    show_expression(oper1, ind+3);

	    if (oper2) {
		  show_expression(oper2, ind+3);
	    } else {
		  fprintf(out, "%*sERROR: oper2 missing! Pad makes no sense for IVL_VT_STRING expressions.\n", ind+3, "");
		  stub_errors += 1;
	    }

      } else if (oper2) {
	      /* If oper2 is present, then it is the base of a part
		 select. The width of the expression defines the range
		 of the part select. */
	    fprintf(out, "%*s<select: width=%u, %s, type=%s>\n", ind, "",
		    width, sign, vt);
	    show_expression(oper1, ind+3);
	    show_expression(oper2, ind+3);

      } else {
	      /* There is no base expression so this is a pad
		 operation. The sub-expression is padded (signed or
		 unsigned as appropriate) to the expression width. */
	    fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
		    width, sign);
	    show_expression(oper1, ind+3);
      }
}
示例#13
0
static void show_new_expression(ivl_expr_t net, unsigned ind)
{
      switch (ivl_expr_value(net)) {
	  case IVL_VT_CLASS:
	    fprintf(out, "%*snew <class_type>\n", ind, "");
	    if (ivl_expr_oper1(net)) {
		  fprintf(out, "%*sERROR: class_new expression has a size!\n",
			  ind+3, "");
		  show_expression(ivl_expr_oper1(net), ind+3);
		  stub_errors += 1;
	    }
	    if (ivl_expr_oper2(net)){
		  fprintf(out, "%*sERROR: class_new with array element initializer!\n",
			  ind+3, "");
		  show_expression(ivl_expr_oper2(net), ind+3);
		  stub_errors += 1;
	    }
	    break;
	  case IVL_VT_DARRAY:
	    fprintf(out, "%*snew [] <type>\n", ind, "");
	    if (ivl_expr_oper1(net)) {
		  show_expression(ivl_expr_oper1(net), ind+3);
	    } else {
		  fprintf(out, "%*sERROR: darray_new missing size expression\n",
			  ind+3, "");
		  stub_errors += 1;
	    }
	      /* The IVL_EX_NEW expression may include an element
		 initializer. This may be an array pattern or simple
		 expression. */
	    if (ivl_expr_oper2(net)) {
		  show_expression(ivl_expr_oper2(net), ind+3);
	    }
	    break;
	  default:
	    fprintf(out, "%*snew ERROR: expression type: %s\n",
		    ind+3, "", vt_type_string(net));
	    stub_errors += 1;
	    break;
      }
}
示例#14
0
static void show_branch_access_expression(ivl_expr_t net, unsigned ind)
{
      ivl_branch_t bra = ivl_expr_branch(net);
      ivl_nature_t nature = ivl_expr_nature(net);
      fprintf(out, "%*s<Access branch %p with nature %s>\n",
	      ind, "", bra, ivl_nature_name(nature));

      if (ivl_expr_value(net) != IVL_VT_REAL) {
	    fprintf(out, "%*sERROR: Expecting type IVL_VT_REAL, got %s\n",
		    ind, "", vt_type_string(net));
	    stub_errors += 1;
      }

      ivl_nexus_t ta = ivl_branch_terminal(bra, 0);
      ivl_nexus_t tb = ivl_branch_terminal(bra, 1);

      ivl_discipline_t ta_disc = discipline_of_nexus(ta);
      if (ta_disc == 0) {
	    fprintf(out, "%*sERROR: Source terminal of branch has no discipline\n",
		    ind, "");
	    stub_errors += 1;
	    return;
      }

      ivl_discipline_t tb_disc = discipline_of_nexus(tb);
      if (ta_disc == 0) {
	    fprintf(out, "%*sERROR: Reference terminal of branch has no discipline\n",
		    ind, "");
	    stub_errors += 1;
	    return;
      }

      if (ta_disc != tb_disc) {
	    fprintf(out, "%*sERROR: Branch terminal disciplines mismatch: %s != %s\n",
		    ind, "", ivl_discipline_name(ta_disc),
		    ivl_discipline_name(tb_disc));
	    stub_errors += 1;
      }
}
static int draw_sfunc_real(ivl_expr_t exp)
{
      struct vector_info sv;
      int res;

      switch (ivl_expr_value(exp)) {

	  case IVL_VT_REAL:
	    if (ivl_expr_parms(exp) == 0) {
		  res = allocate_word();
		  fprintf(vvp_out, "    %%vpi_func/r \"%s\", %d;\n",
			  ivl_expr_name(exp), res);

	    } else {
		  res = draw_vpi_rfunc_call(exp);
	    }
	    break;

	  case IVL_VT_VECTOR:
	      /* If the value of the sfunc is a vector, then evaluate
		 it as a vector, then convert the result to a real
		 (via an index register) for the result. */
	    sv = draw_eval_expr(exp, 0);
	    clr_vector(sv);
	    
	    res = allocate_word();
	    fprintf(vvp_out, "    %%ix/get %d, %u, %u;\n",
		    res, sv.base, sv.wid);

	    fprintf(vvp_out, "    %%cvt/ri %d, %d;\n", res, res);
	    break;

	  default:
	    assert(0);
	    res = -1;
      }

      return res;
}
示例#16
0
static int show_stmt_assign_sig_cobject(ivl_statement_t net)
{
      int errors = 0;
      ivl_lval_t lval = ivl_stmt_lval(net, 0);
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_signal_t sig= ivl_lval_sig(lval);
      unsigned lwid = ivl_lval_width(lval);

      int prop_idx = ivl_lval_property_idx(lval);

      if (prop_idx >= 0) {
	    ivl_type_t sig_type = ivl_signal_net_type(sig);
	    ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);

	    if (ivl_type_base(prop_type) == IVL_VT_BOOL) {
		  assert(ivl_type_packed_dimensions(prop_type) == 1);
		  assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0));

		  draw_eval_vec4(rval);
		  if (ivl_expr_value(rval)!=IVL_VT_BOOL)
			fprintf(vvp_out, "    %%cast2;\n");

		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  fprintf(vvp_out, "    %%store/prop/v %d, %u; Store in bool property %s\n",
			  prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx));
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
		  assert(ivl_type_packed_dimensions(prop_type) == 1);
		  assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0));

		  draw_eval_vec4(rval);

		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  fprintf(vvp_out, "    %%store/prop/v %d, %u; Store in logic property %s\n",
			  prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx));
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else if (ivl_type_base(prop_type) == IVL_VT_REAL) {

		    /* Calculate the real value into the real value
		       stack. The %store/prop/r will pop the stack
		       value. */
		  draw_eval_real(rval);
		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  fprintf(vvp_out, "    %%store/prop/r %d;\n", prop_idx);
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else if (ivl_type_base(prop_type) == IVL_VT_STRING) {

		    /* Calculate the string value into the string value
		       stack. The %store/prop/r will pop the stack
		       value. */
		  draw_eval_string(rval);
		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  fprintf(vvp_out, "    %%store/prop/str %d;\n", prop_idx);
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) {

		  int idx = 0;

		    /* The property is a darray, and there is no mux
		       expression to the assignment is of an entire
		       array object. */
		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  draw_eval_object(rval);
		  fprintf(vvp_out, "    %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else if (ivl_type_base(prop_type) == IVL_VT_CLASS) {

		  int idx = 0;
		  ivl_expr_t idx_expr;
		  if ( (idx_expr = ivl_lval_idx(lval)) ) {
			idx = allocate_word();
		  }

		    /* The property is a class object. */
		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  draw_eval_object(rval);
		  if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
		  fprintf(vvp_out, "    %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

		  if (idx_expr) clr_word(idx);

	    } else {
		  fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
			  ivl_type_base(prop_type));
		  assert(0);
	    }

      } else {
	      /* There is no property select, so evaluate the r-value
		 as an object and assign the entire object to the
		 variable. */
	    errors += draw_eval_object(rval);

	    if (ivl_signal_array_count(sig) > 1) {
		  unsigned ix;
		  ivl_expr_t aidx = ivl_lval_idx(lval);

		  draw_eval_expr_into_integer(aidx, (ix = allocate_word()));
		  fprintf(vvp_out, "    %%store/obja v%p, %u;\n", sig, ix);
		  clr_word(ix);

	    } else {
		    /* Not an array, so no index expression */
		  fprintf(vvp_out, "    %%store/obj v%p_0;\n", sig);
	    }
      }

      return errors;
}
static int show_stmt_assign_vector(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_memory_t mem;

	/* 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) {
	    int word = draw_eval_real(rval);
	      /* This is the accumulated with of the l-value of the
		 assignment. */
	    unsigned wid = ivl_stmt_lwidth(net);

	    struct vector_info vec;

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

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

	    clr_word(word);

	    set_vec_to_lval(net, vec);

	    clr_vector(vec);
	    return 0;
      }

	/* Handle the special case that the r-value is a constant. We
	   can generate the %set statement directly, without any worry
	   about generating code to evaluate the r-value expressions. */

      if (ivl_expr_type(rval) == IVL_EX_NUMBER) {
	    unsigned lidx;
	    const char*bits = ivl_expr_bits(rval);
	    unsigned wid = ivl_expr_width(rval);
	    unsigned cur_rbit = 0;

	    for (lidx = 0 ;  lidx < ivl_stmt_lvals(net) ;  lidx += 1) {
		  unsigned skip_set = transient_id++;
		  unsigned skip_set_flag = 0;
		  unsigned idx;
		  unsigned bit_limit = wid - cur_rbit;
		  lval = ivl_stmt_lval(net, lidx);

		    /* If there is a mux for the lval, calculate the
		       value and write it into index0. */
		  if (ivl_lval_mux(lval)) {
			calculate_into_x0(ivl_lval_mux(lval));
			  /* Generate code to skip around the set
			     if the index has X values. */
			fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
			skip_set_flag = 1;
		  }

		  mem = ivl_lval_mem(lval);
		  if (mem) {
			draw_memory_index_expr(mem, ivl_lval_idx(lval));
			  /* Generate code to skip around the set
			     if the index has X values. */
			fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
			skip_set_flag = 1;
		  }

		  if (bit_limit > ivl_lval_pins(lval))
			bit_limit = ivl_lval_pins(lval);

		  if (mem) {
			for (idx = 0 ;  idx < bit_limit ;  idx += 1) {
			      set_to_memory(mem, idx,
					    bitchar_to_idx(bits[cur_rbit]));

			      cur_rbit += 1;
			}

			for (idx = bit_limit
				   ; idx < ivl_lval_pins(lval) ; idx += 1)
			      set_to_memory(mem, idx, 0);


		  } else {
			idx = 0;
			while (idx < bit_limit) {
			      unsigned cnt = 1;
			      while (((idx + cnt) < bit_limit)
				     && (bits[cur_rbit] == bits[cur_rbit+cnt]))
				    cnt += 1;

			      set_to_lvariable(lval, idx,
					       bitchar_to_idx(bits[cur_rbit]),
					       cnt);

			      cur_rbit += cnt;
			      idx += cnt;
			}


			if (bit_limit < ivl_lval_pins(lval)) {
			      unsigned cnt = ivl_lval_pins(lval) - bit_limit;
			      set_to_lvariable(lval, bit_limit, 0, cnt);
			}
		  }

		  if (skip_set_flag) {
			fprintf(vvp_out, "t_%u ;\n", skip_set);
			clear_expression_lookaside();
		  }
	    }

	    return 0;
      }

      { struct vector_info res = draw_eval_expr(rval, 0);
        set_vec_to_lval(net, res);
	if (res.base > 3)
	      clr_vector(res);
      }


      return 0;
}
static void draw_vpi_taskfunc_args(const char*call_string,
				   ivl_statement_t tnet,
				   ivl_expr_t fnet)
{
      unsigned idx;
      unsigned parm_count = tnet
	    ? ivl_stmt_parm_count(tnet)
	    : ivl_expr_parms(fnet);
      struct vector_info *vec = 0x0;
      unsigned int vecs= 0;
      unsigned int veci= 0;

      ivl_parameter_t par;

	/* Figure out how many expressions are going to be evaluated
	   for this task call. I won't need to evaluate expressions
	   for items that are VPI objects directly. */
      for (idx = 0 ;  idx < parm_count ;  idx += 1) {
	    ivl_expr_t expr = tnet
		  ? ivl_stmt_parm(tnet, idx)
		  : ivl_expr_parm(fnet, idx);
	    
	    switch (ivl_expr_type(expr)) {

		    /* These expression types can be handled directly,
		       with VPI handles of their own. Therefore, skip
		       them in the process of evaluating expressions. */
		case IVL_EX_NONE:
		case IVL_EX_NUMBER:
		case IVL_EX_STRING:
		case IVL_EX_EVENT:
		case IVL_EX_SCOPE:
		case IVL_EX_VARIABLE:
		  continue;

		case IVL_EX_SFUNC:
		  if (is_magic_sfunc(ivl_expr_name(expr)))
			continue;

		  break;

		case IVL_EX_SIGNAL:
		    /* If the signal node is narrower then the signal
		       itself, then this is a part select so I'm going
		       to need to evaluate the expression.

		       Also, if the signedness of the expression is
		       different from the signedness of the
		       signal. This could be caused by a $signed or
		       $unsigned system function.

		       If I don't need to do any evaluating, then skip
		       it as I'll be passing the handle to the signal
		       itself. */
		  if (ivl_expr_width(expr) !=
		      ivl_signal_pins(ivl_expr_signal(expr))) {
			break;

		  } else if (ivl_expr_signed(expr) !=
			     ivl_signal_signed(ivl_expr_signal(expr))) {
			break;

		  } else {
			continue;
		  }


		case IVL_EX_MEMORY:
		  if (!ivl_expr_oper1(expr)) {
			continue;
		  }

		    /* Everything else will need to be evaluated and
		       passed as a constant to the vpi task. */
		default:
		  break;
	    }

	    vec = (struct vector_info *)
		  realloc(vec, (vecs+1)*sizeof(struct vector_info));

	    switch (ivl_expr_value(expr)) {
		case IVL_VT_VECTOR:
		  vec[vecs] = draw_eval_expr(expr, 0);
		  break;
		case IVL_VT_REAL:
		  vec[vecs].base = draw_eval_real(expr);
		  vec[vecs].wid = 0;
		  break;
		default:
		  assert(0);
	    }
	    vecs++;
      }

      fprintf(vvp_out, "%s", call_string);

      for (idx = 0 ;  idx < parm_count ;  idx += 1) {
	    ivl_expr_t expr = tnet
		  ? ivl_stmt_parm(tnet, idx)
		  : ivl_expr_parm(fnet, idx);
	    
	    switch (ivl_expr_type(expr)) {
		case IVL_EX_NONE:
		  fprintf(vvp_out, ", \" \"");
		  continue;

		case IVL_EX_NUMBER: {
		      unsigned bit, wid = ivl_expr_width(expr);
		      const char*bits = ivl_expr_bits(expr);

		      fprintf(vvp_out, ", %u'%sb", wid,
			      ivl_expr_signed(expr)? "s" : "");
		      for (bit = wid ;  bit > 0 ;  bit -= 1)
			    fputc(bits[bit-1], vvp_out);
		      continue;
		}

		case IVL_EX_SIGNAL:
		    /* If this is a part select, then the value was
		       calculated above. Otherwise, just pass the
		       signal. */
		  if (ivl_expr_width(expr) !=
		      ivl_signal_pins(ivl_expr_signal(expr))) {
			break;

		  } else if (ivl_expr_signed(expr) !=
			     ivl_signal_signed(ivl_expr_signal(expr))) {
			break;

		  } else {
			fprintf(vvp_out, ", V_%s", 
				vvp_signal_label(ivl_expr_signal(expr)));
			continue;
		  }

		case IVL_EX_VARIABLE: {
		      ivl_variable_t var = ivl_expr_variable(expr);
		      fprintf(vvp_out, ", W_%s", vvp_word_label(var));
		      continue;
		}

		case IVL_EX_STRING:
		  if (( par = ivl_expr_parameter(expr) )) {
			fprintf(vvp_out, ", P_%p", par);

		  } else {
			fprintf(vvp_out, ", \"%s\"", 
				ivl_expr_string(expr));
		  }
		  continue;

		case IVL_EX_EVENT:
		  fprintf(vvp_out, ", E_%p", ivl_expr_event(expr));
		  continue;

		case IVL_EX_SCOPE:
		  fprintf(vvp_out, ", S_%p", ivl_expr_scope(expr));
		  continue;

		case IVL_EX_SFUNC:
		  if (is_magic_sfunc(ivl_expr_name(expr))) {
			fprintf(vvp_out, ", %s", ivl_expr_name(expr));
			continue;
		  }
		  break;
		  
		case IVL_EX_MEMORY:
		  if (!ivl_expr_oper1(expr)) {
			fprintf(vvp_out, ", M_%s", 
				vvp_memory_label(ivl_expr_memory(expr)));
			continue;
		  }
		  break;

		default:
		  break;
	    }
	    assert(veci < vecs);

	    switch (ivl_expr_value(expr)) {

		case IVL_VT_VECTOR:
		  fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
			  vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
		  break;

		case IVL_VT_REAL:
		  fprintf(vvp_out, ", W<%u,r>", vec[veci].base);
		  break;

		default:
		  assert(0);
	    }
	    veci++;
      }
      
      assert(veci == vecs);

      if (vecs) {
	    for (idx = 0; idx < vecs; idx++) {
		  if (vec[idx].wid > 0)
			clr_vector(vec[idx]);
		  else if (vec[idx].wid == 0)
			clr_word(vec[idx].base);
	    }
	    free(vec);
      }

      fprintf(vvp_out, ";\n");
}
示例#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
static int eval_darray_new(ivl_expr_t ex)
{
      int errors = 0;
      unsigned size_reg = allocate_word();
      ivl_expr_t size_expr = ivl_expr_oper1(ex);
      ivl_expr_t init_expr = ivl_expr_oper2(ex);
      draw_eval_expr_into_integer(size_expr, size_reg);

	// The new function has a net_type that contains the details
	// of the type.
      ivl_type_t net_type = ivl_expr_net_type(ex);
      assert(net_type);

      ivl_type_t element_type = ivl_type_element(net_type);
      assert(element_type);

      switch (ivl_type_base(element_type)) {
	    int msb, lsb, wid;
	  case IVL_VT_REAL:
	      // REAL objects are not packable.
	    assert(ivl_type_packed_dimensions(element_type) == 0);
	    fprintf(vvp_out, "    %%new/darray %u, \"r\";\n", size_reg);
	    break;
	  case IVL_VT_STRING:
	      // STRING objects are not packable.
	    assert(ivl_type_packed_dimensions(element_type) == 0);
	    fprintf(vvp_out, "    %%new/darray %u, \"S\";\n", size_reg);
	    break;
	  case IVL_VT_BOOL:
	      // bool objects are vectorable, but for now only support
	      // a single dimensions.
	    assert(ivl_type_packed_dimensions(element_type) == 1);
	    msb = ivl_type_packed_msb(element_type, 0);
	    lsb = ivl_type_packed_lsb(element_type, 0);
	    wid = msb>=lsb? msb - lsb : lsb - msb;
	    wid += 1;
	    fprintf(vvp_out, "    %%new/darray %u, \"%sb%d\";\n", size_reg,
	                     ivl_type_signed(element_type) ? "s" : "", wid);
	    break;
	  case IVL_VT_LOGIC:
	      // logic objects are vectorable, but for now only support
	      // a single dimensions.
	    assert(ivl_type_packed_dimensions(element_type) == 1);
	    msb = ivl_type_packed_msb(element_type, 0);
	    lsb = ivl_type_packed_lsb(element_type, 0);
	    wid = msb>=lsb? msb - lsb : lsb - msb;
	    wid += 1;
	    fprintf(vvp_out, "    %%new/darray %u, \"%sv%d\";\n", size_reg,
	                     ivl_type_signed(element_type) ? "s" : "", wid);
	    break;

	  default:
	    assert(0);
	    break;
      }
      clr_word(size_reg);

      if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) {
	    unsigned idx;
	    switch (ivl_type_base(element_type)) {
		case IVL_VT_BOOL:
		case IVL_VT_LOGIC:
		  for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
			draw_eval_vec4(ivl_expr_parm(init_expr,idx));
			fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
			fprintf(vvp_out, "    %%set/dar/obj/vec4 3;\n");
			fprintf(vvp_out, "    %%pop/vec4 1;\n");
		  }
		  break;
		case IVL_VT_REAL:
		  for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
			draw_eval_real(ivl_expr_parm(init_expr,idx));
			fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
			fprintf(vvp_out, "    %%set/dar/obj/real 3;\n");
			fprintf(vvp_out, "    %%pop/real 1;\n");
		  }
		  break;
		case IVL_VT_STRING:
		  for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
			draw_eval_string(ivl_expr_parm(init_expr,idx));
			fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
			fprintf(vvp_out, "    %%set/dar/obj/str 3;\n");
			fprintf(vvp_out, "    %%pop/str 1;\n");
		  }
		  break;
		default:
		  fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
		  errors += 1;
		  break;
	    }
      } else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) {
		  ivl_signal_t sig = ivl_expr_signal(init_expr);
		  fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
		  fprintf(vvp_out, "    %%scopy;\n");

      } else if (init_expr && number_is_immediate(size_expr,32,0)) {
	      /* In this case, there is an init expression, the
		 expression is NOT an array_pattern, and the size
		 expression used to calculate the size of the array is
		 a constant. Generate an unrolled set of assignments. */
	    long idx;
	    long cnt = get_number_immediate(size_expr);
	    unsigned wid;
	    switch (ivl_type_base(element_type)) {
		case IVL_VT_BOOL:
		case IVL_VT_LOGIC:
		  wid = width_of_packed_type(element_type);
		  for (idx = 0 ; idx < cnt ; idx += 1) {
			draw_eval_vec4(init_expr);
			fprintf(vvp_out, "    %%parti/%c %u, %ld, 6;\n",
                                ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
			fprintf(vvp_out, "    %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
			fprintf(vvp_out, "    %%set/dar/obj/vec4 3;\n");
			fprintf(vvp_out, "    %%pop/vec4 1;\n");
		  }
		  break;
		case IVL_VT_REAL:
		  draw_eval_real(init_expr);
		  for (idx = 0 ; idx < cnt ; idx += 1) {
			fprintf(vvp_out, "    %%ix/load 3, %ld, 0;\n", idx);
			fprintf(vvp_out, "    %%set/dar/obj/real 3;\n");
		  }
		  fprintf(vvp_out, "    %%pop/real 1;\n");
		  break;
		case IVL_VT_STRING:
		  draw_eval_string(init_expr);
		  for (idx = 0 ; idx < cnt ; idx += 1) {
			fprintf(vvp_out, "    %%ix/load 3, %ld, 0;\n", idx);
			fprintf(vvp_out, "    %%set/dar/obj/str 3;\n");
		  }
		  fprintf(vvp_out, "    %%pop/str 1;\n");
		  break;
		default:
		  fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
		  errors += 1;
		  break;
	    }

      } else if (init_expr) {
	    fprintf(vvp_out, "; ERROR: Sorry, I don't know how to work with this size expr.\n");
	    errors += 1;
      }

      return errors;
}
示例#21
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;
      int idx_reg;

	/* 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));
	    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);

	      /* Convert a calculated real value to a vec4 value of
		 the given width. We need to include the width of the
		 result because real values to not have any inherit
		 width. The real value will be popped, and a vec4
		 value pushed. */
	    fprintf(vvp_out, "    %%cvt/vr %u;\n", wid);

      } else if (ivl_expr_value(rval) == IVL_VT_STRING) {
	    /* Special case: vector to string casting */
	    ivl_lval_t lval = ivl_stmt_lval(net, 0);
	    fprintf(vvp_out, "    %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
		ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
		ivl_expr_signal(rval), ivl_lval_sig(lval));
            return 0;

      } else {
	    unsigned wid = ivl_stmt_lwidth(net);
	    draw_eval_vec4(rval);
	    resize_vec4_wid(rval, wid);
      }

      switch (ivl_stmt_opcode(net)) {
	  case 0:
	    store_vec4_to_lval(net);
	    break;

	  case '+':
	    fprintf(vvp_out, "    %%add;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case '-':
	    fprintf(vvp_out, "    %%sub;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case '*':
	    fprintf(vvp_out, "    %%mul;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case '/':
	    fprintf(vvp_out, "    %%div%s;\n", ivl_expr_signed(rval)? "/s":"");
	    put_vec_to_lval(net, slices);
	    break;

	  case '%':
	    fprintf(vvp_out, "    %%mod%s;\n", ivl_expr_signed(rval)? "/s":"");
	    put_vec_to_lval(net, slices);
	    break;

	  case '&':
	    fprintf(vvp_out, "    %%and;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case '|':
	    fprintf(vvp_out, "    %%or;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case '^':
	    fprintf(vvp_out, "    %%xor;\n");
	    put_vec_to_lval(net, slices);
	    break;

	  case 'l': /* lval <<= expr */
	    idx_reg = allocate_word();
	    fprintf(vvp_out, "    %%ix/vec4 %d;\n", idx_reg);
	    fprintf(vvp_out, "    %%shiftl %d;\n", idx_reg);
	    clr_word(idx_reg);
	    put_vec_to_lval(net, slices);
	    break;

	  case 'r': /* lval >>= expr */
	    idx_reg = allocate_word();
	    fprintf(vvp_out, "    %%ix/vec4 %d;\n", idx_reg);
	    fprintf(vvp_out, "    %%shiftr %d;\n", idx_reg);
	    clr_word(idx_reg);
	    put_vec_to_lval(net, slices);
	    break;

	  case 'R': /* lval >>>= expr */
	    idx_reg = allocate_word();
	    fprintf(vvp_out, "    %%ix/vec4 %d;\n", idx_reg);
	    fprintf(vvp_out, "    %%shiftr/s %d;\n", idx_reg);
	    clr_word(idx_reg);
	    put_vec_to_lval(net, slices);
	    break;

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

      if (slices)
	    free(slices);

      return 0;
}
示例#22
0
static void draw_binary_vec4_le(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);
      ivl_expr_t tmp;

      if ((ivl_expr_value(le) == IVL_VT_REAL)
	  || (ivl_expr_value(re) == IVL_VT_REAL)) {
	    draw_binary_vec4_le_real(expr);
	    return;
      }

      char use_opcode = ivl_expr_opcode(expr);
      char s_flag = (ivl_expr_signed(le) && ivl_expr_signed(re)) ? 's' : 'u';

	/* If this is a > or >=, then convert it to < or <= by
	   swapping the operands. Adjust the opcode to match. */
      switch (use_opcode) {
	  case 'G':
	    tmp = le;
	    le = re;
	    re = tmp;
	    use_opcode = 'L';
	    break;
	  case '>':
	    tmp = le;
	    le = re;
	    re = tmp;
	    use_opcode = '<';
	    break;
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    draw_binary_vec4_le_string(expr);
	    return;
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_type(re)==IVL_EX_STRING)) {
	    draw_binary_vec4_le_string(expr);
	    return;
      }

      if ((ivl_expr_type(le)==IVL_EX_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    draw_binary_vec4_le_string(expr);
	    return;
      }

	/* NOTE: I think I would rather the elaborator handle the
	   operand widths. When that happens, take this code out. */

      unsigned use_wid = ivl_expr_width(le);
      if (ivl_expr_width(re) > use_wid)
	    use_wid = ivl_expr_width(re);

      draw_eval_vec4(le);
      resize_vec4_wid(le, use_wid);

      if (ivl_expr_width(re)==use_wid && test_immediate_vec4_ok(re)) {
	      /* Special case: If the right operand can be handled as
		 an immediate operand, then use that instead. */
	    char opcode[8];
	    snprintf(opcode, sizeof opcode, "%%cmpi/%c", s_flag);
	    draw_immediate_vec4(re, opcode);

      } else {
	    draw_eval_vec4(re);
	    resize_vec4_wid(re, use_wid);

	    fprintf(vvp_out, "    %%cmp/%c;\n", s_flag);
      }

      switch (use_opcode) {
	  case 'L':
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 5;\n");
	    fprintf(vvp_out, "    %%or;\n");
	    break;
	  case '<':
	    fprintf(vvp_out, "    %%flag_get/vec4 5;\n");
	    break;
	  default:
	    assert(0);
	    break;
      }
}
示例#23
0
static void draw_binary_vec4_compare(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);

      if ((ivl_expr_value(le) == IVL_VT_REAL)
	  || (ivl_expr_value(re) == IVL_VT_REAL)) {
	    draw_binary_vec4_compare_real(expr);
	    return;
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    draw_binary_vec4_compare_string(expr);
	    return;
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_type(re)==IVL_EX_STRING)) {
	    draw_binary_vec4_compare_string(expr);
	    return;
      }

      if ((ivl_expr_type(le)==IVL_EX_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    draw_binary_vec4_compare_string(expr);
	    return;
      }

      if ((ivl_expr_value(le)==IVL_VT_CLASS)
	  && (ivl_expr_value(re)==IVL_VT_CLASS)) {
	    draw_binary_vec4_compare_class(expr);
	    return;
      }

      unsigned use_wid = ivl_expr_width(le);
      if (ivl_expr_width(re) > use_wid)
	    use_wid = ivl_expr_width(re);

      draw_eval_vec4(le);
      resize_vec4_wid(le, use_wid);

      draw_eval_vec4(re);
      resize_vec4_wid(re, use_wid);

      switch (ivl_expr_opcode(expr)) {
	  case 'e': /* == */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    break;
	  case 'n': /* != */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_inv 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    break;
	  case 'E': /* === */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 6;\n");
	    break;
	  case 'N': /* !== */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_inv 6;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 6;\n");
	    break;
	  default:
	    assert(0);
      }
}
示例#24
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;
      }
}
示例#25
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>");
	    }
      }
}
示例#26
0
static void draw_vpi_taskfunc_args(const char*call_string,
				   ivl_statement_t tnet,
				   ivl_expr_t fnet)
{
      unsigned idx;
      unsigned parm_count = tnet
	    ? ivl_stmt_parm_count(tnet)
	    : ivl_expr_parms(fnet);

      struct args_info *args = calloc(parm_count, sizeof(struct args_info));

      char buffer[4096];

      ivl_parameter_t par;

	/* Figure out how many expressions are going to be evaluated
	   for this task call. I won't need to evaluate expressions
	   for items that are VPI objects directly. */
      for (idx = 0 ;  idx < parm_count ;  idx += 1) {
	    ivl_expr_t expr = tnet
		  ? ivl_stmt_parm(tnet, idx)
		  : ivl_expr_parm(fnet, idx);

	    switch (ivl_expr_type(expr)) {

		    /* These expression types can be handled directly,
		       with VPI handles of their own. Therefore, skip
		       them in the process of evaluating expressions. */
		case IVL_EX_NONE:
		  args[idx].text = strdup("\" \"");
		  continue;

		case IVL_EX_ARRAY:
		  snprintf(buffer, sizeof buffer,
			   "v%p", ivl_expr_signal(expr));
		  args[idx].text = strdup(buffer);
		  continue;

		case IVL_EX_NUMBER: {
		  if (( par = ivl_expr_parameter(expr) )) {
			snprintf(buffer, sizeof buffer, "P_%p", par);
		  } else {
			unsigned bit, wid = ivl_expr_width(expr);
			const char*bits = ivl_expr_bits(expr);
			char*dp;

			snprintf(buffer, sizeof buffer, "%u'%sb",
			         wid, ivl_expr_signed(expr)? "s" : "");
			dp = buffer + strlen(buffer);
			for (bit = wid ;  bit > 0 ;  bit -= 1)
			      *dp++ = bits[bit-1];
			*dp++ = 0;
			assert(dp >= buffer);
			assert((unsigned)(dp - buffer) <= sizeof buffer);
		  }
		  args[idx].text = strdup(buffer);
		  continue;
		}

		case IVL_EX_STRING:
		  if (( par = ivl_expr_parameter(expr) )) {
			snprintf(buffer, sizeof buffer, "P_%p", par);

		  } else {
			snprintf(buffer, sizeof buffer, "\"%s\"", ivl_expr_string(expr));
		  }
		  args[idx].text = strdup(buffer);
		  continue;

		case IVL_EX_REALNUM:
		  if (( par = ivl_expr_parameter(expr) )) {
			snprintf(buffer, sizeof buffer, "P_%p", par);
			args[idx].text = strdup(buffer);
			continue;
		  }
		  break;

		case IVL_EX_ENUMTYPE:
		  snprintf(buffer, sizeof buffer, "enum%p", ivl_expr_enumtype(expr));
		  args[idx].text = strdup(buffer);
		  continue;
		case IVL_EX_EVENT:
		  snprintf(buffer, sizeof buffer, "E_%p", ivl_expr_event(expr));
		  args[idx].text = strdup(buffer);
		  continue;
		case IVL_EX_SCOPE:
		  snprintf(buffer, sizeof buffer, "S_%p", ivl_expr_scope(expr));
		  args[idx].text = strdup(buffer);
		  continue;

		case IVL_EX_SFUNC:
		  if (is_magic_sfunc(ivl_expr_name(expr))) {
			snprintf(buffer, sizeof buffer, "%s", ivl_expr_name(expr));
			args[idx].text = strdup(buffer);
			continue;
		  }
		  break;

		case IVL_EX_SIGNAL:
		case IVL_EX_SELECT:
		  if (get_vpi_taskfunc_signal_arg(&args[idx], expr)) continue;
		  else break;

		    /* Everything else will need to be evaluated and
		       passed as a constant to the vpi task. */
		default:
		  break;
	    }

	    switch (ivl_expr_value(expr)) {
		case IVL_VT_LOGIC:
		case IVL_VT_BOOL:
		  args[idx].vec_flag = 1;
		  args[idx].vec = draw_eval_expr(expr, 0);
		  snprintf(buffer, sizeof buffer,
			   "T<%u,%u,%s>", args[idx].vec.base, args[idx].vec.wid,
			   ivl_expr_signed(expr)? "s" : "u");
		  break;
		case IVL_VT_REAL:
		  args[idx].vec_flag = 1;
		  args[idx].vec.base = draw_eval_real(expr);
		  args[idx].vec.wid  = 0;
		  snprintf(buffer, sizeof buffer,
		           "W<%u,r>", args[idx].vec.base);
		  break;
		case IVL_VT_STRING:
		    /* STRING expressions not supported yet. */
		default:
		  assert(0);
	    }
	    args[idx].text = strdup(buffer);
      }

      fprintf(vvp_out, "%s", call_string);

      for (idx = 0 ;  idx < parm_count ;  idx += 1) {
	    struct args_info*ptr;

	    fprintf(vvp_out, ", %s", args[idx].text);
	    free(args[idx].text);
	      /* Clear the nested children vectors. */
	    for (ptr = &args[idx]; ptr != NULL; ptr = ptr->child) {
		  if (ptr->vec_flag) {
			if (ptr->vec.wid > 0) clr_vector(ptr->vec);
			else clr_word(ptr->vec.base);
		  }
	    }
	      /* Free the nested children. */
	    ptr = args[idx].child;
	    while (ptr != NULL) {
		struct args_info*tptr = ptr;
		ptr = ptr->child;
		free(tptr);
	    }
      }

      free(args);

      fprintf(vvp_out, ";\n");
}
示例#27
0
static const char*vt_type_string(ivl_expr_t net)
{
      return data_type_string(ivl_expr_value(net));
}
示例#28
0
static int draw_condition_binary_compare(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);

      if ((ivl_expr_value(le) == IVL_VT_REAL)
	  || (ivl_expr_value(re) == IVL_VT_REAL)) {
	    return draw_condition_fallback(expr);
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    return draw_condition_fallback(expr);
      }

      if ((ivl_expr_value(le)==IVL_VT_STRING)
	  && (ivl_expr_type(re)==IVL_EX_STRING)) {
	    return draw_condition_fallback(expr);
      }

      if ((ivl_expr_type(le)==IVL_EX_STRING)
	  && (ivl_expr_value(re)==IVL_VT_STRING)) {
	    return draw_condition_fallback(expr);
      }

      if ((ivl_expr_value(le)==IVL_VT_CLASS)
	  && (ivl_expr_value(re)==IVL_VT_CLASS)) {
	    return draw_condition_fallback(expr);
      }

      unsigned use_wid = ivl_expr_width(le);
      if (ivl_expr_width(re) > use_wid)
	    use_wid = ivl_expr_width(re);

	/* If the le is constant, then swap the operands so that we
	   can possibly take advantage of the immediate version of the
	   %cmp instruction. */
      if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
	    ivl_expr_t tmp = le;
	    re = le;
	    le = tmp;
      }

      draw_eval_vec4(le);
      resize_vec4_wid(le, use_wid);

      char use_opcode = ivl_expr_opcode(expr);


      if (ivl_expr_width(re)==use_wid && test_immediate_vec4_ok(re)) {
	      /* Special case: If the right operand can be handled as
		 an immediate operand, then use that instead. */
	    if (use_opcode=='n' || use_opcode=='N')
		  draw_immediate_vec4(re, "%cmpi/ne");
	    else
		  draw_immediate_vec4(re, "%cmpi/e");
      } else {
	    draw_eval_vec4(re);
	    resize_vec4_wid(re, use_wid);
	    if (use_opcode=='n' || use_opcode=='N')
		  fprintf(vvp_out, "    %%cmp/ne;\n");
	    else
		  fprintf(vvp_out, "    %%cmp/e;\n");
      }

      switch (ivl_expr_opcode(expr)) {
	  case 'n': /* != */
	  case 'e': /* == */
	    return 4;
	    break;
	  case 'N': /* !== */
	  case 'E': /* === */
	    return 6;
	  default:
	    assert(0);
	    return -1;
      }

}
示例#29
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, ")");
}