Exemple #1
0
static void put_vec_to_lval(ivl_statement_t net, struct vec_slice_info*slices)
{
      unsigned lidx;
      unsigned cur_bit;

      unsigned wid = ivl_stmt_lwidth(net);

      cur_bit = 0;
      for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
	    ivl_lval_t lval;
	    unsigned bit_limit = wid - cur_bit;

	    lval = ivl_stmt_lval(net, lidx);

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

	    if (lidx+1 < ivl_stmt_lvals(net))
		  fprintf(vvp_out, "    %%split/vec4 %u;\n", bit_limit);

	    put_vec_to_lval_slice(lval, slices+lidx, bit_limit);

	    cur_bit += bit_limit;
      }
}
static int show_stmt_release(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_signal_t lsig;
      unsigned idx;

	/* If there are no l-vals (the target signal has been elided)
	   then turn the release into a no-op. In other words, we are
	   done before we start. */
      if (ivl_stmt_lvals(net) == 0)
	    return 0;

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

      lsig = ivl_lval_sig(lval);
      assert(lsig != 0);
      assert(ivl_lval_mux(lval) == 0);
      assert(ivl_lval_part_off(lval) == 0);

	/* On release, reg variables hold the value that was forced on
	   to them. */
      for (idx = 0 ;  idx < ivl_lval_pins(lval) ; idx += 1) {
	    if (ivl_signal_type(lsig) == IVL_SIT_REG) {
		  fprintf(vvp_out, "    %%load 4, V_%s[%u];\n",
			  vvp_signal_label(lsig), idx);
		  fprintf(vvp_out, "    %%set V_%s[%u], 4;\n",
			  vvp_signal_label(lsig), idx);
	    }
	    fprintf(vvp_out, "    %%release V_%s[%u];\n",
		    vvp_signal_label(lsig), idx);
      }

      return 0;
}
Exemple #3
0
/*
 * This loads the l-value values into the top of the stack, and also
 * leaves in the slices the information needed to store the slice
 * results back.
 */
static void get_vec_from_lval(ivl_statement_t net, struct vec_slice_info*slices)
{
      unsigned lidx;
      unsigned cur_bit;

      unsigned wid = ivl_stmt_lwidth(net);

      cur_bit = 0;
      for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
	    ivl_lval_t lval;
	    unsigned bit_limit = wid - cur_bit;

	    lval = ivl_stmt_lval(net, lidx);

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

	    get_vec_from_lval_slice(lval, slices+lidx, bit_limit);
	    if (lidx > 0) {
		  fprintf(vvp_out, "    %%concat/vec4;\n");
	    }

	    cur_bit += bit_limit;
      }

}
Exemple #4
0
/*
 * Check to see if the statement L-value is a port in the given scope.
 * If it is return the zero based port number.
 */
static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned idx, ports = ivl_scope_ports(scope);
      ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
      ivl_signal_t lsig = ivl_lval_sig(lval);
      const char *sig_name;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(stmt) != 1) return ports;
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return ports;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return ports;
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return ports;
	/* It must have the same scope as the task. */
      if (scope != ivl_signal_scope(lsig)) return ports;
	/* It must be an input or inout port of the task. */
      sig_name = ivl_signal_basename(lsig);
      for (idx = 0; idx < ports; idx += 1) {
	    ivl_signal_t port = ivl_scope_port(scope, idx);
	    ivl_signal_port_t port_type = ivl_signal_port(port);
	    if ((port_type != IVL_SIP_INPUT) &&
	        (port_type != IVL_SIP_INOUT)) continue;
	    if (strcmp(sig_name, ivl_signal_basename(port)) == 0) break;
      }
      return idx;
}
Exemple #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(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;
}
Exemple #6
0
static unsigned emit_stmt_lval(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned count = ivl_stmt_lvals(stmt);
      unsigned wid = 0;
      if (count > 1) {
	    unsigned idx;
	    ivl_lval_t lval;
	    fprintf(vlog_out, "{");
	    for (idx = count - 1; idx > 0; idx -= 1) {
		  lval = ivl_stmt_lval(stmt, idx);
		  wid += ivl_lval_width(lval);
		  emit_stmt_lval_piece(scope, lval);
		  fprintf(vlog_out, ", ");
	    }
	    lval = ivl_stmt_lval(stmt, 0);
	    wid += ivl_lval_width(lval);
	    emit_stmt_lval_piece(scope, lval);
	    fprintf(vlog_out, "}");
      } else {
	    ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
	    wid = ivl_lval_width(lval);
	    emit_stmt_lval_piece(scope, lval);
      }
      return wid;
}
static int show_stmt_force(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_signal_t lsig;
      unsigned idx;
      static unsigned force_functor_label = 0;
      char*tmp_label;

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

      lsig = ivl_lval_sig(lval);
      assert(lsig != 0);
      assert(ivl_lval_mux(lval) == 0);
      assert(ivl_lval_part_off(lval) == 0);

      force_functor_label += 1;
      tmp_label = strdup(vvp_signal_label(lsig));
      for (idx = 0 ;  idx < ivl_lval_pins(lval) ; idx += 1) {
	    fprintf(vvp_out, "f_%u.%u .force V_%s[%u], %s;\n",
		    force_functor_label, idx,
		    tmp_label, idx,
		    draw_net_input(ivl_stmt_nexus(net, idx)));
      } 
      free(tmp_label);

      for (idx = 0 ;  idx < ivl_lval_pins(lval) ; idx += 1) {
	    fprintf(vvp_out, "    %%force f_%u.%u, 1;\n",
		    force_functor_label, idx);
      }
      return 0;
}
Exemple #8
0
static struct vector_info get_vec_from_lval(ivl_statement_t net,
					    struct vec_slice_info*slices)
{
      struct vector_info res;
      unsigned lidx;
      unsigned cur_bit;

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

      cur_bit = 0;
      for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
	    unsigned bidx;
	    ivl_lval_t lval;
	    unsigned bit_limit = res.wid - cur_bit;

	    lval = ivl_stmt_lval(net, lidx);

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

	    bidx = res.base + cur_bit;

	    get_vec_from_lval_slice(lval, slices+lidx, bidx, bit_limit);

	    cur_bit += bit_limit;
      }

      return res;
}
static int show_stmt_cassign(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_signal_t lsig;
      unsigned idx;
      char*tmp_label;

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

      lsig = ivl_lval_sig(lval);
      assert(lsig != 0);
      assert(ivl_lval_mux(lval) == 0);
      assert(ivl_signal_pins(lsig) == ivl_stmt_nexus_count(net));
      assert(ivl_lval_part_off(lval) == 0);

      tmp_label = strdup(vvp_signal_label(lsig));
      for (idx = 0 ;  idx < ivl_stmt_nexus_count(net) ;  idx += 1) {
	    fprintf(vvp_out, "    %%cassign V_%s[%u], %s;\n",
		    tmp_label, idx,
		    draw_net_input(ivl_stmt_nexus(net, idx)));
      }
      free(tmp_label);

      return 0;
}
Exemple #10
0
/*
 * This is a private function to generate %set code for the
 * statement. At this point, the r-value is evaluated and stored in
 * the res vector, I just need to generate the %set statements for the
 * l-values of the assignment.
 */
static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
{
      unsigned wid = res.wid;
      unsigned lidx;
      unsigned cur_rbit = 0;

      for (lidx = 0 ;  lidx < ivl_stmt_lvals(net) ;  lidx += 1) {
	    unsigned bidx;
	    unsigned bit_limit = wid - cur_rbit;

	    ivl_lval_t lval = ivl_stmt_lval(net, lidx);

	      /* Reduce bit_limit to the width of this l-value. */
	    if (bit_limit > ivl_lval_width(lval))
		  bit_limit = ivl_lval_width(lval);

	      /* This is the address within the larger r-value of the
		 bit that this l-value takes. */
	    bidx = res.base < 4? res.base : (res.base+cur_rbit);

	    set_vec_to_lval_slice(lval, bidx, bit_limit);

	      /* Now we've consumed this many r-value bits for the
		 current l-value. */
	    cur_rbit += bit_limit;
      }
}
/*
 * This function handles the case of non-blocking assign to word
 * variables such as real, i.e:
 *
 *     read foo;
 *     foo <= 1.0;
 *
 * In this case we know (by Verilog syntax) that there is only exactly
 * 1 l-value, the target identifier, so it should be relatively easy.
 */
static int show_stmt_assign_nb_var(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_variable_t var;
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_expr_t del  = ivl_stmt_delay_expr(net);

      int word;
      unsigned long delay;

	/* Must be exactly 1 l-value. */
      assert(ivl_stmt_lvals(net) == 1);

      delay = 0;
      if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
	    delay = ivl_expr_uvalue(del);
	    del = 0;
      }

	/* XXXX For now, presume delays are constant. */
      assert(del == 0);

	/* Evaluate the r-value */
      word = draw_eval_real(rval);

      lval = ivl_stmt_lval(net, 0);
      var = ivl_lval_var(lval);
      assert(var != 0);

      fprintf(vvp_out, "    %%assign/wr W_%s, %lu, %u;\n",
	      vvp_word_label(var), delay, word);

      return 0;
}
Exemple #12
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;
}
Exemple #13
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;
}
Exemple #14
0
static void show_assign_lvals(ivl_statement_t net)
{
      const unsigned cnt = ivl_stmt_lvals(net);

      if (cnt == 1) {
	    show_assign_lval(ivl_stmt_lval(net, 0));

      } else {
	    unsigned idx;
	    fprintf(out, "{");
	    show_assign_lval(ivl_stmt_lval(net, 0));
	    for (idx = 1 ;  idx < cnt ;  idx += 1) {
		  fprintf(out, ", ");
		  show_assign_lval(ivl_stmt_lval(net, idx));
	    }
	    fprintf(out, "}");
      }
}
static int show_stmt_assign_real(ivl_statement_t net)
{
      int res;
      ivl_lval_t lval;
      ivl_variable_t var;

      res = draw_eval_real(ivl_stmt_rval(net));
      clr_word(res);

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

      fprintf(vvp_out, "    %%set/wr W_%s, %d;\n",
	      vvp_word_label(var), res);

      return 0;
}
static int show_stmt_deassign(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_signal_t lsig;
      unsigned idx;

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

      lsig = ivl_lval_sig(lval);
      assert(lsig != 0);
      assert(ivl_lval_mux(lval) == 0);
      assert(ivl_lval_part_off(lval) == 0);

      for (idx = 0 ;  idx < ivl_lval_pins(lval) ; idx += 1) {
	    fprintf(vvp_out, "    %%deassign V_%s[%u], 1;\n",
		    vvp_signal_label(lsig), idx);
      }
      return 0;
}
Exemple #17
0
static void put_vec_to_lval(ivl_statement_t net, struct vec_slice_info*slices,
			    struct vector_info res)
{
      unsigned lidx;
      unsigned cur_bit;

      cur_bit = 0;
      for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
	    unsigned bidx;
	    ivl_lval_t lval;
	    unsigned bit_limit = res.wid - cur_bit;

	    lval = ivl_stmt_lval(net, lidx);

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

	    bidx = res.base + cur_bit;

	    put_vec_to_lval_slice(lval, slices+lidx, bidx, bit_limit);

	    cur_bit += bit_limit;
      }
}
static int show_stmt_assign_nb(ivl_statement_t net)
{
      ivl_lval_t lval;
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_expr_t del  = ivl_stmt_delay_expr(net);
      ivl_memory_t mem;

      unsigned long delay = 0;

	/* Catch the case we are assigning to a real/word
	   l-value. Handle that elsewhere. */
      if (ivl_lval_var(ivl_stmt_lval(net, 0))) {
	    return show_stmt_assign_nb_var(net);
      }

      if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
	    delay = ivl_expr_uvalue(del);
	    del = 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;

	    if (del != 0)
		  calculate_into_x1(del);

	    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));
			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));
			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) {
			      assign_to_memory(mem, idx, 
					       bitchar_to_idx(bits[cur_rbit]),
					       delay);
			      cur_rbit += 1;
			}

			for (idx = bit_limit
				   ; idx < ivl_lval_pins(lval)
				   ; idx += 1) {
			      assign_to_memory(mem, idx, 0, delay);
			}

		  } else if ((del == 0) && (bit_limit > 2)) {

			  /* We have a vector, but no runtime
			     calculated delays, to try to use vector
			     assign instructions. */
			idx = 0;
			while (idx < bit_limit) {
			      unsigned wid = 0;

			      do {
				    wid += 1;
				    if ((idx + wid) == bit_limit)
					  break;

			      } while (bits[cur_rbit] == bits[cur_rbit+wid]);

			      switch (wid) {
				  case 1:
				    assign_to_lvariable(lval, idx,
					       bitchar_to_idx(bits[cur_rbit]),
					       delay, 0);
				    break;
				  case 2:
				    assign_to_lvariable(lval, idx,
					       bitchar_to_idx(bits[cur_rbit]),
					       delay, 0);
				    assign_to_lvariable(lval, idx+1,
					       bitchar_to_idx(bits[cur_rbit]),
					       delay, 0);
				    break;
				  default:
				    assign_to_lvector(lval, idx,
					      bitchar_to_idx(bits[cur_rbit]),
					      delay, wid);
				    break;
			      }

			      idx += wid;
			      cur_rbit += wid;
			}

			if (bit_limit < ivl_lval_pins(lval)) {
			      unsigned wid = ivl_lval_pins(lval) - bit_limit;
			      assign_to_lvector(lval, bit_limit,
						0, delay, wid);
			}

		  } else {
			for (idx = 0 ;  idx < bit_limit ;  idx += 1) {
			      if (del != 0)
				    assign_to_lvariable(lval, idx,
					       bitchar_to_idx(bits[cur_rbit]),
					       1, 1);
			      else
				    assign_to_lvariable(lval, idx,
					       bitchar_to_idx(bits[cur_rbit]),
					       delay, 0);
			      cur_rbit += 1;
			}

			for (idx = bit_limit
				   ; idx < ivl_lval_pins(lval)
				   ; idx += 1) {
			      if (del != 0)
				    assign_to_lvariable(lval, idx, 0,
							1, 1);
			      else
				    assign_to_lvariable(lval, idx, 0,
							delay, 0);
			}
		  }

		  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);
        unsigned wid = res.wid;
	unsigned lidx;
	unsigned cur_rbit = 0;

	if (del != 0)
	      calculate_into_x1(del);

	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));
		    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));
		    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 ((bit_limit > 2) && (mem == 0) && (del == 0)) {

		    unsigned bidx = res.base < 4
			  ? res.base
			  : (res.base+cur_rbit);
		    assign_to_lvector(lval, 0, bidx, delay, bit_limit);
		    cur_rbit += bit_limit;

	      } else {
		    for (idx = 0 ;  idx < bit_limit ;  idx += 1) {
			  unsigned bidx = res.base < 4
				? res.base
				: (res.base+cur_rbit);
			  if (mem)
				assign_to_memory(mem, idx, bidx, delay);
			  else if (del != 0)
				assign_to_lvariable(lval, idx, bidx,
						    1, 1);
			  else
				assign_to_lvariable(lval, idx, bidx,
						    delay, 0);

			  cur_rbit += 1;
		    }
	      }

	      for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
			  if (mem)
				assign_to_memory(mem, idx, 0, delay);
			  else if (del != 0)
				assign_to_lvariable(lval, idx, 0, 1, 1);
			  else
				assign_to_lvariable(lval, idx, 0, delay, 0);


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

	if (res.base > 3)
	      clr_vector(res);
      }

      return 0;
}
Exemple #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;
}
Exemple #20
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;
}
Exemple #21
0
/*
 * Icarus translated <var> = repeat(<count>) <event> <value> into
 *   begin
 *    <tmp> = <value>;
 *    repeat(<count>) <event>;
 *    <var> = <tmp>;
 *   end
 * This routine looks for this pattern and turns it back into the
 * appropriate blocking assignment.
 */
static unsigned is_repeat_event_assign(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned wid;
      ivl_statement_t assign, event, event_assign, repeat;
      ivl_lval_t lval;
      ivl_expr_t rval;
      ivl_signal_t lsig, rsig;

	/* We must have three block elements. */
      if (ivl_stmt_block_count(stmt) != 3) return 0;
	/* The first must be an assign. */
      assign = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
	/* The second must be a repeat with an event or an event. */
      repeat = ivl_stmt_block_stmt(stmt, 1);
      if (ivl_statement_type(repeat) != IVL_ST_REPEAT) return 0;
	/* The repeat must have an event statement. */
      event = ivl_stmt_sub_stmt(repeat);
      if (ivl_statement_type(event) != IVL_ST_WAIT) return 0;
	/* The third must be an assign. */
      event_assign = ivl_stmt_block_stmt(stmt, 2);
      if (ivl_statement_type(event_assign) != IVL_ST_ASSIGN) return 0;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(assign) != 1) return 0;
      lval = ivl_stmt_lval(assign, 0);
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return 0;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return 0;
      lsig = ivl_lval_sig(lval);
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
	/* The R-value must be a single signal. */
      rval = ivl_stmt_rval(event_assign);
      if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
	/* It must not be an array word. */
      if (ivl_expr_oper1(rval)) return 0;
      rsig = ivl_expr_signal(rval);
	/* The two signals must be the same. */
      if (lsig != rsig) return 0;
	/* And finally the four statements must have the same line number
	 * as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(repeat)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event_assign))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*c", get_indent(), ' ');
      wid = emit_stmt_lval(scope, event_assign);
      fprintf(vlog_out, " =");
      if (repeat) {
	    fprintf(vlog_out, " repeat (");
	    emit_expr(scope, ivl_stmt_cond_expr(repeat), 0);
	    fprintf(vlog_out, ")");
      }
      fprintf(vlog_out, " @(");
      emit_event(scope, event);
      fprintf(vlog_out, ") ");
      emit_expr(scope, ivl_stmt_rval(assign), wid);
      fprintf(vlog_out, ";");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");

      return 1;
}
Exemple #22
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;
}
Exemple #23
0
/*
 * Icarus translated <var> = <delay or event> <value> into
 *   begin
 *    <tmp> = <value>;
 *    <delay or event> <var> = <tmp>;
 *   end
 * This routine looks for this pattern and turns it back into the
 * appropriate blocking assignment.
 */
static unsigned is_delayed_or_event_assign(ivl_scope_t scope,
                                           ivl_statement_t stmt)
{
      unsigned wid;
      ivl_statement_t assign, delay, delayed_assign;
      ivl_statement_type_t delay_type;
      ivl_lval_t lval;
      ivl_expr_t rval;
      ivl_signal_t lsig, rsig;

	/* We must have two block elements. */
      if (ivl_stmt_block_count(stmt) != 2) return 0;
	/* The first must be an assign. */
      assign = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
	/* The second must be a delayx. */
      delay = ivl_stmt_block_stmt(stmt, 1);
      delay_type = ivl_statement_type(delay);
      if ((delay_type != IVL_ST_DELAYX) &&
          (delay_type != IVL_ST_WAIT)) return 0;
	/* The statement for the delayx must be an assign. */
      delayed_assign = ivl_stmt_sub_stmt(delay);
      if (ivl_statement_type(delayed_assign) != IVL_ST_ASSIGN) return 0;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(assign) != 1) return 0;
      lval = ivl_stmt_lval(assign, 0);
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return 0;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return 0;
      lsig = ivl_lval_sig(lval);
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
	/* The R-value must be a single signal. */
      rval = ivl_stmt_rval(delayed_assign);
      if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
	/* It must not be an array word. */
      if (ivl_expr_oper1(rval)) return 0;
      rsig = ivl_expr_signal(rval);
	/* The two signals must be the same. */
      if (lsig != rsig) return 0;
	/* And finally the three statements must have the same line number
	 * as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delay)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delayed_assign))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*c", get_indent(), ' ');
      wid = emit_stmt_lval(scope, delayed_assign);
      fprintf(vlog_out, " = ");
      if (delay_type == IVL_ST_DELAYX) {
	    fprintf(vlog_out, "#(");
	    emit_scaled_delayx(scope, ivl_stmt_delay_expr(delay), 1);
      } else {
	    fprintf(vlog_out, "@(");
	    emit_event(scope, delay);
      }
      fprintf(vlog_out, ") ");
      emit_expr(scope, ivl_stmt_rval(assign), wid);
      fprintf(vlog_out, ";");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");

      return 1;
}
/*
 * This is a private function to generate %set code for the
 * statement. At this point, the r-value is evaluated and stored in
 * the res vector, I just need to generate the %set statements for the
 * l-values of the assignment.
 */
static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
{
      ivl_lval_t lval;
      ivl_memory_t mem;

      unsigned wid = res.wid;
      unsigned lidx;
      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));
		  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));
		  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) {
			unsigned bidx = res.base < 4
			      ? res.base
			      : (res.base+cur_rbit);
			set_to_memory(mem, idx, bidx);
			cur_rbit += 1;
		  }

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

	    } else {

		  unsigned bidx = res.base < 4
			? res.base
			: (res.base+cur_rbit);
		  set_to_lvariable(lval, 0, bidx, bit_limit);
		  cur_rbit += bit_limit;

		  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();
	    }
      }
}
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;
}
Exemple #26
0
/*
 * Store a vector from the vec4 stack to the statement l-values. This
 * all assumes that the value to be assigned is already on the top of
 * the stack.
 *
 * NOTE TO SELF: The %store/vec4 takes a width, but the %assign/vec4
 * instructions do not, instead relying on the expression width. I
 * think that it the proper way to do it, so soon I should change the
 * %store/vec4 to not include the width operand.
 */
static void store_vec4_to_lval(ivl_statement_t net)
{
      for (unsigned lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
	    ivl_lval_t lval = ivl_stmt_lval(net,lidx);
	    ivl_signal_t lsig = ivl_lval_sig(lval);
	    ivl_lval_t nest = ivl_lval_nest(lval);
	    unsigned lwid = ivl_lval_width(lval);


	    ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
	      /* This is non-nil if the l-val is the word of a memory,
		 and nil otherwise. */
	    ivl_expr_t word_ex = ivl_lval_idx(lval);

	    if (lidx+1 < ivl_stmt_lvals(net))
		  fprintf(vvp_out, "    %%split/vec4 %u;\n", lwid);

	    if (word_ex) {
		    /* Handle index into an array */
		  int word_index = allocate_word();
		  int part_index = 0;
		    /* Calculate the word address into word_index */
		  draw_eval_expr_into_integer(word_ex, word_index);
		    /* If there is a part_offset, calculate it into part_index. */
		  if (part_off_ex) {
			int flag_index = allocate_flag();
			part_index = allocate_word();
			fprintf(vvp_out, "    %%flag_mov %d, 4;\n", flag_index);
			draw_eval_expr_into_integer(part_off_ex, part_index);
			fprintf(vvp_out, "    %%flag_or 4, %d;\n", flag_index);
			clr_flag(flag_index);
		  }

		  assert(lsig);
		  fprintf(vvp_out, "    %%store/vec4a v%p, %d, %d;\n",
			  lsig, word_index, part_index);

		  clr_word(word_index);
		  if (part_index)
			clr_word(part_index);

	    } else if (part_off_ex) {
		    /* Dynamically calculated part offset */
		  int offset_index = allocate_word();
		  draw_eval_expr_into_integer(part_off_ex, offset_index);
		    /* Note that flag4 is set by the eval above. */
		  assert(lsig);
		  if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) {
			fprintf(vvp_out, "    %%force/vec4/off v%p_0, %u;\n",
				lsig, offset_index);
		  } else {
			fprintf(vvp_out, "    %%store/vec4 v%p_0, %d, %u;\n",
				lsig, offset_index, lwid);
		  }
		  clr_word(offset_index);

	    } else if (nest) {
		    /* No offset expression, but the l-value is
		       nested, which probably means that it is a class
		       member. We will use a property assign
		       function. */
		  assert(!lsig);
		  ivl_type_t sub_type = draw_lval_expr(nest);
		  assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
		  fprintf(vvp_out, "    %%store/prop/v %u, %u;\n",
			  ivl_lval_property_idx(lval), lwid);
		  fprintf(vvp_out, "    %%pop/obj 1, 0;\n");

	    } else {
		    /* No offset expression, so use simpler store function. */
		  assert(lsig);
		  assert(lwid == ivl_signal_width(lsig));
		  fprintf(vvp_out, "    %%store/vec4 v%p_0, 0, %u;\n", lsig, lwid);
	    }
      }
}