Пример #1
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. */

      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");

}
Пример #2
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 exressions. */

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

}
Пример #3
0
void draw_ufunc_real(ivl_expr_t expr)
{
      ivl_scope_t def = ivl_expr_def(expr);
      ivl_signal_t retval = ivl_scope_port(def, 0);
      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);
      }

      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");

	/* Return value signal cannot be an array. */
      assert(ivl_signal_dimensions(retval) == 0);

	/* Load the result into a word. */
      fprintf(vvp_out, "  %%load/real v%p_0;\n", retval);

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

}
Пример #4
0
static void string_ex_concat(ivl_expr_t expr)
{
      unsigned repeat;

      assert(ivl_expr_parms(expr) != 0);
      assert(ivl_expr_repeat(expr) != 0);

	/* Push the first string onto the stack, no matter what. */
      draw_eval_string(ivl_expr_parm(expr,0));

      for (repeat = 0 ; repeat < ivl_expr_repeat(expr) ; repeat += 1) {
	    unsigned idx;
	    for (idx = (repeat==0)? 1 : 0 ; idx < ivl_expr_parms(expr) ; idx += 1) {
		  ivl_expr_t sub = ivl_expr_parm(expr,idx);

		    /* Special case: If operand is a string literal,
		       then concat it using the %concati/str
		       instruction. */
		  if (ivl_expr_type(sub) == IVL_EX_STRING) {
			fprintf(vvp_out, "    %%concati/str \"%s\";\n",
				ivl_expr_string(sub));
			continue;
		  }

		  draw_eval_string(sub);
		  fprintf(vvp_out, "    %%concat/str;\n");
	    }
      }
}
Пример #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_array_pattern_expression(ivl_expr_t net, unsigned ind)
{
      size_t idx;
      fprintf(out, "%*sArrayPattern (%s): %u expressions\n",
	      ind, "", vt_type_string(net), ivl_expr_parms(net));
      for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1) {
	    show_expression(ivl_expr_parm(net,idx), ind+4);
      }
}
Пример #7
0
static void show_function_call(ivl_expr_t net, unsigned ind)
{
      ivl_scope_t def = ivl_expr_def(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*vt = vt_type_string(net);
      unsigned idx;

      fprintf(out, "%*s<%s %s function %s with %u arguments (width=%u)>\n",
	      ind, "", vt, sign, ivl_scope_name(def), ivl_expr_parms(net),
	      ivl_expr_width(net));

      for (idx = 0 ;  idx < ivl_expr_parms(net) ;  idx += 1)
	    show_expression(ivl_expr_parm(net,idx), ind+4);
}
Пример #8
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);
}
Пример #9
0
static void draw_concat_vec4(ivl_expr_t expr)
{
	/* Repeat the concatenation this many times to make a
	   super-concatenation. */
      unsigned repeat = ivl_expr_repeat(expr);
	/* This is the number of expressions that go into the
	   concatenation. */
      unsigned num_sube = ivl_expr_parms(expr);
      unsigned sub_idx;

      assert(num_sube > 0);

	/* Start with the most-significant bits. */
      draw_eval_vec4(ivl_expr_parm(expr, 0));

      for (sub_idx = 1 ; sub_idx < num_sube ; sub_idx += 1) {
	      /* Concatenate progressively lower parts. */
	    ivl_expr_t sube = ivl_expr_parm(expr, sub_idx);

	      /* Special case: The next expression is a NUMBER that
		 can be concatenated using %concati/vec4
		 instructions. */
	    if (ivl_expr_type(sube) == IVL_EX_NUMBER) {
		  draw_concat_number_vec4(sube, 1);
		  continue;
	    }

	    draw_eval_vec4(sube);
	    fprintf(vvp_out, "    %%concat/vec4; draw_concat_vec4\n");
      }

      if (repeat > 1) {
	    fprintf(vvp_out, "    %%replicate %u;\n", repeat);
      }
}
Пример #10
0
/*
 * This function handles the special case that we assign an array
 * pattern to a dynamic array. Handle this by assigning each
 * element. The array pattern will have a fixed size.
 */
static int show_stmt_assign_darray_pattern(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 var= ivl_lval_sig(lval);
      ivl_type_t var_type= ivl_signal_net_type(var);
      assert(ivl_type_base(var_type) == IVL_VT_DARRAY);

      ivl_type_t element_type = ivl_type_element(var_type);
      unsigned idx;
#if 0
      unsigned element_width = 1;
      if (ivl_type_base(element_type) == IVL_VT_BOOL)
	    element_width = width_of_packed_type(element_type);
      else if (ivl_type_base(element_type) == IVL_VT_LOGIC)
	    element_width = width_of_packed_type(element_type);
#endif
      assert(ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN);
      for (idx = 0 ; idx < ivl_expr_parms(rval) ; idx += 1) {
	    switch (ivl_type_base(element_type)) {
		case IVL_VT_BOOL:
		case IVL_VT_LOGIC:
		  draw_eval_vec4(ivl_expr_parm(rval,idx));
		  fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
		  fprintf(vvp_out, "    %%store/dar/vec4 v%p_0;\n", var);
		  break;

		case IVL_VT_REAL:
		  draw_eval_real(ivl_expr_parm(rval,idx));
		  fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
		  fprintf(vvp_out, "    %%store/dar/r v%p_0;\n", var);
		  break;

		case IVL_VT_STRING:
		  draw_eval_string(ivl_expr_parm(rval,idx));
		  fprintf(vvp_out, "    %%ix/load 3, %u, 0;\n", idx);
		  fprintf(vvp_out, "    %%store/dar/str v%p_0;\n", var);
		  break;

		default:
		  fprintf(vvp_out, "; ERROR: show_stmt_assign_darray_pattern: type_base=%d not implemented\n", ivl_type_base(element_type));
		  errors += 1;
		  break;
	    }
      }

      return errors;
}
Пример #11
0
/*
 * This routine is used to emit both system and user functions.
 */
static void emit_expr_func(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      unsigned count = ivl_expr_parms(expr);
      if (count) {
	    unsigned idx;
	    fprintf(vlog_out, "(");
	    count -= 1;
	    for (idx = 0; idx < count; idx += 1) {
		  emit_expr(scope, ivl_expr_parm(expr, idx), 0);
		  fprintf(vlog_out, ", ");
	    }
	    emit_expr(scope, ivl_expr_parm(expr, count), 0);
	    fprintf(vlog_out, ")");
      }
}
Пример #12
0
static void emit_expr_concat(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      unsigned repeat = ivl_expr_repeat(expr);
      unsigned idx, count = ivl_expr_parms(expr);

      if (repeat != 1) fprintf(vlog_out, "{%u", repeat);
      fprintf(vlog_out, "{");
      count -= 1;
      for (idx = 0; idx < count; idx += 1) {
	    emit_expr(scope, ivl_expr_parm(expr, idx), 0);
	    fprintf(vlog_out, ", ");
      }
      emit_expr(scope, ivl_expr_parm(expr, count), 0);
      fprintf(vlog_out, "}");
      if (repeat != 1) fprintf(vlog_out, "}");
}
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;
}
Пример #14
0
static void string_ex_substr(ivl_expr_t expr)
{
      ivl_expr_t arg;
      unsigned arg1;
      unsigned arg2;
      assert(ivl_expr_parms(expr) == 3);

      arg = ivl_expr_parm(expr,0);
      draw_eval_string(arg);

	/* Evaluate the arguments... */
      arg = ivl_expr_parm(expr, 1);
      arg1 = allocate_word();
      draw_eval_expr_into_integer(arg, arg1);

      arg = ivl_expr_parm(expr, 2);
      arg2 = allocate_word();
      draw_eval_expr_into_integer(arg, arg2);

      fprintf(vvp_out, "    %%substr %u, %u;\n", arg1, arg2);
      clr_word(arg1);
      clr_word(arg2);
}
Пример #15
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");
}
Пример #16
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;
      }
}
Пример #17
0
static void show_expression(ivl_expr_t net)
{
      if (net == 0)
	    return;

      switch (ivl_expr_type(net)) {

	  case IVL_EX_BINARY: {
		char code = ivl_expr_opcode(net);
		show_expression(ivl_expr_oper1(net));
		switch (code) {
		    case 'e':
		      fprintf(out, "==");
		      break;
		    case 'n':
		      fprintf(out, "!=");
		      break;
		    case 'N':
		      fprintf(out, "!==");
		      break;
		    case 'r':
		      fprintf(out, ">>");
		      break;
		    default:
		      fprintf(out, "%c", code);
		}
		show_expression(ivl_expr_oper2(net));
		break;
	  }

	  case IVL_EX_CONCAT: {
		unsigned idx;
		fprintf(out, "{");
		show_expression(ivl_expr_parm(net, 0));
		for (idx = 1 ;  idx < ivl_expr_parms(net) ;  idx += 1) {
		      fprintf(out, ", ");
		      show_expression(ivl_expr_parm(net, idx));
		}
		fprintf(out, "}");
		break;
	  }

	  case IVL_EX_NUMBER: {
		int sigflag     = ivl_expr_signed(net);
		unsigned idx, width  = ivl_expr_width(net);
		const char*bits = ivl_expr_bits(net);

		fprintf(out, "%u'%sb", width, sigflag? "s" : "");
		for (idx = width ;  idx > 0 ;  idx -= 1)
		      fprintf(out, "%c", bits[idx-1]);
		break;
	  }

	  case IVL_EX_SFUNC:
	    fprintf(out, "%s", ivl_expr_name(net));
	    break;

	  case IVL_EX_STRING:
	    fprintf(out, "\"%s\"", ivl_expr_string(net));
	    break;

	  case IVL_EX_SIGNAL:
	    fprintf(out, "%s", ivl_expr_name(net));
	    break;

	  default:
	    fprintf(out, "...");
      }
}
Пример #18
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;
}
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");
}
Пример #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
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;
      }
}