Example #1
0
static int show_stmt_assign_sig_darray(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_expr_t part = ivl_lval_part_off(lval);
      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);

      ivl_expr_t mux  = ivl_lval_idx(lval);

      assert(ivl_stmt_lvals(net) == 1);
      assert(ivl_stmt_opcode(net) == 0);
      assert(ivl_lval_mux(lval) == 0);
      assert(part == 0);

      if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) {
	    draw_eval_real(rval);

	      /* The %set/dar expects the array index to be in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%store/dar/r v%p_0;\n", var);

      } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) {

	      /* Evaluate the rval into the top of the string stack. */
	    draw_eval_string(rval);

	      /* The %store/dar/s expects the array index to me in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%store/dar/str v%p_0;\n", var);

      } else if (mux) {
	    struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval),
							 STUFF_OK_XZ);
	      /* The %set/dar expects the array index to be in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%set/dar v%p_0, %u, %u;\n",
		    var, rvec.base, rvec.wid);

	    if (rvec.base >= 4) clr_vector(rvec);

      } else {
	      /* There is no l-value mux, so this must be an
		 assignment to the array as a whole. Evaluate the
		 "object", and store the evaluated result. */
	    errors += draw_eval_object(rval);
	    fprintf(vvp_out, "    %%store/obj v%p_0;\n", var);
      }

      return errors;
}
Example #2
0
/*
 * This function assigns a value to a real .variable. This is destined
 * for /dev/null when typed ivl_signal_t takes over all the real
 * variable support.
 */
static int show_stmt_assign_sig_real(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_signal_t var;

      assert(ivl_stmt_opcode(net) == 0);

      draw_eval_real(ivl_stmt_rval(net));

      assert(ivl_stmt_lvals(net) == 1);
      lval = ivl_stmt_lval(net, 0);
      var = ivl_lval_sig(lval);
      assert(var != 0);

      if (ivl_signal_dimensions(var) == 0) {
	    fprintf(vvp_out, "    %%store/real v%p_0;\n", var);
	    return 0;
      }

	// For now, only support 1-dimensional arrays.
      assert(ivl_signal_dimensions(var) == 1);

      ivl_expr_t word_ex = ivl_lval_idx(lval);
      int word_ix = allocate_word();

	/* If the word index is a constant, then we can write
	   directly to the word and save the index calculation.
	   Out-of-bounds and undefined indices are converted to
	   a canonical index of 'bx during elaboration, and we
	   don't try to optimise that case. */
      if (word_ex && number_is_immediate(word_ex, IMM_WID, 0) &&
	  !number_is_unknown(word_ex)) {
	    unsigned long use_word = get_number_immediate(word_ex);
	    assert(use_word < ivl_signal_array_count(var));
	    fprintf(vvp_out, "    %%ix/load %u, %lu, 0;\n",
		    word_ix, use_word);
	    fprintf(vvp_out, "    %%store/reala v%p, %d;\n",
		    var, word_ix);

      } else {
	    unsigned do_store = transient_id++;
	    unsigned end_store = transient_id++;
	    draw_eval_expr_into_integer(word_ex, word_ix);
	    fprintf(vvp_out, "    %%jmp/0 t_%u, 4;\n", do_store);
	    fprintf(vvp_out, "    %%pop/real 1;\n");
	    fprintf(vvp_out, "    %%jmp t_%u;\n", end_store);
	    fprintf(vvp_out, "t_%u ;\n", do_store);
	    fprintf(vvp_out, "    %%store/reala v%p, %d;\n", var, word_ix);
	    fprintf(vvp_out, "t_%u ;\n", end_store);
      }

      clr_word(word_ix);

      return 0;
}
Example #3
0
static int show_stmt_assign_sig_string(ivl_statement_t net)
{
      ivl_lval_t lval = ivl_stmt_lval(net, 0);
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_expr_t part = ivl_lval_part_off(lval);
      ivl_expr_t aidx = ivl_lval_idx(lval);
      ivl_signal_t var= ivl_lval_sig(lval);

      assert(ivl_stmt_lvals(net) == 1);
      assert(ivl_stmt_opcode(net) == 0);
      assert(ivl_lval_mux(lval) == 0);

	/* Simplest case: no mux. Evaluate the r-value as a string and
	   store the result into the variable. Note that the
	   %store/str opcode pops the string result. */
      if (part == 0 && aidx == 0) {
	    draw_eval_string(rval);
	    fprintf(vvp_out, "    %%store/str v%p_0;\n", var);
	    return 0;
      }

	/* Assign to array. The l-value has an index expression
	   expression so we are assigning to an array word. */
      if (aidx != 0) {
	    unsigned ix;
	    assert(part == 0);
	    draw_eval_string(rval);
	    draw_eval_expr_into_integer(aidx, (ix = allocate_word()));
	    fprintf(vvp_out, "    %%store/stra v%p, %u;\n", var, ix);
	    clr_word(ix);
	    return 0;
      }

	/* Calculate the character select for the word. */
      int mux_word = allocate_word();
      draw_eval_expr_into_integer(part, mux_word);

	/* Evaluate the r-value as a vector. */
      struct vector_info rvec = draw_eval_expr_wid(rval, 8, STUFF_OK_XZ);

      assert(rvec.wid == 8);
      fprintf(vvp_out, "    %%putc/str/v v%p_0, %d, %u;\n", var, mux_word, rvec.base);

      clr_vector(rvec);
      clr_word(mux_word);
      return 0;
}
Example #4
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;
}
Example #5
0
static int show_stmt_assign_sig_darray(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_expr_t part = ivl_lval_part_off(lval);
      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);

      ivl_expr_t mux  = ivl_lval_idx(lval);

      assert(ivl_stmt_lvals(net) == 1);
      assert(ivl_stmt_opcode(net) == 0);
      assert(part == 0);

      if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) {
	    draw_eval_real(rval);

	      /* The %set/dar expects the array index to be in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%store/dar/r v%p_0;\n", var);

      } else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) {

	      /* Evaluate the rval into the top of the string stack. */
	    draw_eval_string(rval);

	      /* The %store/dar/s expects the array index to me in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%store/dar/str v%p_0;\n", var);

      } else if (mux) {
	    draw_eval_vec4(rval);

	      /* The %store/dar/vec4 expects the array index to be in index
		 register 3. Calculate the index in place. */
	    draw_eval_expr_into_integer(mux, 3);

	    fprintf(vvp_out, "    %%store/dar/vec4 v%p_0;\n", var);

      } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
	      /* There is no l-value mux, but the r-value is an array
		 pattern. This is a special case of an assignment to
		 elements of the l-value. */
	    errors += show_stmt_assign_darray_pattern(net);

      } else {
	      /* There is no l-value mux, so this must be an
		 assignment to the array as a whole. Evaluate the
		 "object", and store the evaluated result. */
	    errors += draw_eval_object(rval);
	    fprintf(vvp_out, "    %%store/obj v%p_0;\n", var);
      }

      return errors;
}
Example #6
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;
}