Beispiel #1
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;
}
Beispiel #2
0
static void show_array_expression(ivl_expr_t net, unsigned ind)
{
      ivl_signal_t sig = ivl_expr_signal(net);
      const char*name = ivl_signal_basename(sig);
      unsigned width = ivl_signal_width(sig);
      const char*vt   = vt_type_string(net);

      fprintf(out, "%*sArray: %s, word_count=%u (%u dimensions), width=%u, type=%s\n",
	      ind, "", name, ivl_signal_array_count(sig),
	      ivl_signal_dimensions(sig), width, vt);
}
Beispiel #3
0
static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      ivl_signal_t sig = ivl_expr_signal(expr);
      emit_scope_call_path(scope, ivl_signal_scope(sig));
      emit_id(ivl_signal_basename(sig));
      if (ivl_signal_dimensions(sig)) {
	    int lsb = ivl_signal_array_base(sig);
	    int msb = lsb + ivl_signal_array_count(sig);
	    fprintf(vlog_out, "[");
	    emit_scaled_expr(scope, ivl_expr_oper1(expr), msb, lsb);
	    fprintf(vlog_out, "]");
      }
}
Beispiel #4
0
static void show_signal_expression(ivl_expr_t net, unsigned ind)
{
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*vt = vt_type_string(net);
      ivl_expr_t word = ivl_expr_oper1(net);

      ivl_signal_t sig = ivl_expr_signal(net);
      const char*vt_sig = data_type_string(ivl_signal_data_type(sig));
      unsigned dimensions = ivl_signal_dimensions(sig);
      unsigned word_count = ivl_signal_array_count(sig);

      if (dimensions == 0 && word_count != 1) {
	    fprintf(out, "%*sERROR: Word count = %u for non-array object\n",
		    ind, "", word_count);
	    stub_errors += 1;
      }

      fprintf(out, "%*s<signal=%s, words=%u, width=%u, %s type=%s (%s)>\n", ind, "",
	      ivl_expr_name(net), word_count, width, sign, vt, vt_sig);

      /* If the expression refers to a signal array, then there must
         also be a word select expression, and if the signal is not an
         array, there must NOT be a word expression. */
      if (dimensions == 0 && word != 0) {
	    fprintf(out, "%*sERROR: Unexpected word expression\n", ind+2, "");
	    stub_errors += 1;
      }
      if (dimensions >= 1 && word == 0) {
	    fprintf(out, "%*sERROR: Missing word expression\n", ind+2, "");
	    stub_errors += 1;
      }
	/* If this is not an array, then the expression with must
	   match the signal width. We have IVL_EX_SELECT expressions
	   for casting signal widths. */
      if (dimensions == 0 && ivl_signal_width(sig) != width) {
	    fprintf(out, "%*sERROR: Expression width (%u) doesn't match ivl_signal_width(sig)=%u\n",
		    ind+2, "", width, ivl_signal_width(sig));
	    stub_errors += 1;
      }

      if (word != 0) {
	    fprintf(out, "%*sAddress-0 word address:\n", ind+2, "");
	    show_expression(word, ind+2);
      }
}
Beispiel #5
0
static void emit_stmt_lval_name(ivl_scope_t scope, ivl_lval_t lval,
                                ivl_signal_t sig)
{
      ivl_expr_t array_idx = ivl_lval_idx(lval);
      emit_scope_call_path(scope, ivl_signal_scope(sig));
      emit_id(ivl_signal_basename(sig));
      if (array_idx) {
	    int msb, lsb;
	    assert(ivl_signal_dimensions(sig));
	    fprintf(vlog_out, "[");
	      /* For an array the LSB/MSB order is not important. They are
	       * always accessed from base counting up. */
	    lsb = ivl_signal_array_base(sig);
	    msb = lsb + ivl_signal_array_count(sig) - 1;
	    emit_scaled_expr(scope, array_idx, msb, lsb);
	    fprintf(vlog_out, "]");
      }
}
Beispiel #6
0
/*
 * This function draws a reg/int/variable in the scope. This is a very
 * simple device to draw as there are no inputs to connect so no need
 * to scan the nexus. We do have to account for the possibility that
 * the device is arrayed, though, by making a node for each array element.
 */
static void draw_reg_in_scope(ivl_signal_t sig)
{
      int msb = ivl_signal_msb(sig);
      int lsb = ivl_signal_lsb(sig);

      const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
			       ivl_signal_signed(sig)? "/s" : "";
      const char*local_flag = ivl_signal_local(sig)? "*" : "";

      switch (ivl_signal_data_type(sig)) {
	  case IVL_VT_REAL:
	    datatype_flag = "/real";
	    break;
	  default:
	    break;
      }

	/* If the reg objects are collected into an array, then first
	   write out the .array record to declare the array indices. */
      if (ivl_signal_dimensions(sig) > 0) {
	    unsigned word_count = ivl_signal_array_count(sig);
	    int last = ivl_signal_array_base(sig)+word_count-1;
	    int first = ivl_signal_array_base(sig);
	    fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
		    sig, datatype_flag,
		    vvp_mangle_name(ivl_signal_basename(sig)),
		    last, first, msb, lsb);

      } else {

	    fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
		    sig, datatype_flag, local_flag,
		    vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb,
		    ivl_signal_local(sig)? " Local signal" : "");
      }
}
Beispiel #7
0
static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
				    unsigned bit, unsigned wid)
{
      ivl_signal_t sig = ivl_lval_sig(lval);
      ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
      unsigned long part_off = 0;

	/* Although Verilog doesn't support it, we'll handle
	   here the case of an l-value part select of an array
	   word if the address is constant. */
      ivl_expr_t word_ix = ivl_lval_idx(lval);
      unsigned long use_word = 0;

      if (part_off_ex == 0) {
	    part_off = 0;
      } else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
                 !number_is_unknown(part_off_ex)) {
	    part_off = get_number_immediate(part_off_ex);
	    part_off_ex = 0;
      }

	/* If the word index is a constant expression, then evaluate
	   it to select the word, and pay no further heed to the
	   expression itself. */
      if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
	    assert(! number_is_unknown(word_ix));
	    use_word = get_number_immediate(word_ix);
	    word_ix = 0;
      }

      if (ivl_lval_mux(lval))
	    part_off_ex = ivl_lval_mux(lval);

      if (ivl_signal_dimensions(sig)==0 && part_off_ex==0 && word_ix==0
	  && part_off==0 && wid==ivl_signal_width(sig)) {

	    slice->type = SLICE_SIMPLE_VECTOR;
	    slice->u_.simple_vector.use_word = use_word;
	    fprintf(vvp_out, "    %%load/v %u, v%p_%lu, %u;\n",
		    bit, sig, use_word, wid);

      } else if (ivl_signal_dimensions(sig)==0 && part_off_ex==0 && word_ix==0) {

	    assert(use_word == 0);

	    slice->type = SLICE_PART_SELECT_STATIC;
	    slice->u_.part_select_static.part_off = part_off;

	    fprintf(vvp_out, "    %%ix/load 1, %lu, 0;\n", part_off);
	    fprintf(vvp_out, "    %%load/x1p %u, v%p_0, %u;\n", bit, sig, wid);

      } else if (ivl_signal_dimensions(sig)==0 && part_off_ex!=0 && word_ix==0) {

	    unsigned skip_set = transient_id++;
	    unsigned out_set  = transient_id++;

	    assert(use_word == 0);
	    assert(part_off == 0);

	    slice->type = SLICE_PART_SELECT_DYNAMIC;

	    draw_eval_expr_into_integer(part_off_ex, 1);

	    slice->u_.part_select_dynamic.word_idx_reg = allocate_word();
	    slice->u_.part_select_dynamic.x_flag = allocate_vector(1);

	    fprintf(vvp_out, "    %%mov %u, %u, 1;\n",
		    slice->u_.part_select_dynamic.x_flag, 4);
	    fprintf(vvp_out, "    %%mov/wu %d, %d;\n",
		    slice->u_.part_select_dynamic.word_idx_reg, 1);

	    fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
	    fprintf(vvp_out, "    %%load/x1p %u, v%p_0, %u;\n", bit, sig, wid);
	    fprintf(vvp_out, "    %%jmp t_%u;\n", out_set);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);
	    fprintf(vvp_out, "    %%mov %u, 2, %u;\n", bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", out_set);

      } else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {

	    slice->type = SLICE_MEMORY_WORD_STATIC;
	    slice->u_.memory_word_static.use_word = use_word;
	    if (use_word < ivl_signal_array_count(sig)) {
		  fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n",
			  use_word);
		  fprintf(vvp_out, "    %%load/av %u, v%p, %u;\n",
			  bit, sig, wid);
	    } else {
		  fprintf(vvp_out, "    %%mov %u, 2, %u; OUT OF BOUNDS\n",
			  bit, wid);
	    }

      } else if (ivl_signal_dimensions(sig) > 0 && word_ix != 0) {

	    unsigned skip_set = transient_id++;
	    unsigned out_set  = transient_id++;
	    slice->type = SLICE_MEMORY_WORD_DYNAMIC;

	    draw_eval_expr_into_integer(word_ix, 3);
	    slice->u_.memory_word_dynamic.word_idx_reg = allocate_word();
	    slice->u_.memory_word_dynamic.x_flag = allocate_vector(1);
	    fprintf(vvp_out, "    %%mov/wu %d, 3;\n",
		    slice->u_.memory_word_dynamic.word_idx_reg);
	    fprintf(vvp_out, "    %%mov %u, 4, 1;\n",
		    slice->u_.memory_word_dynamic.x_flag);

	    fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
	    fprintf(vvp_out, "    %%ix/load 1, 0, 0;\n");
	    fprintf(vvp_out, "    %%load/av %u, v%p, %u;\n",
		    bit, sig, wid);
	    fprintf(vvp_out, "    %%jmp t_%u;\n", out_set);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);
	    fprintf(vvp_out, "    %%mov %u, 2, %u;\n", bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", out_set);

      } else {
	    assert(0);
      }
}
Beispiel #8
0
static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid)
{
      ivl_signal_t sig  = ivl_lval_sig(lval);
      ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
      unsigned long part_off = 0;

	/* Although Verilog doesn't support it, we'll handle
	   here the case of an l-value part select of an array
	   word if the address is constant. */
      ivl_expr_t word_ix = ivl_lval_idx(lval);
      unsigned long use_word = 0;

      if (part_off_ex == 0) {
	    part_off = 0;
      } else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
                 !number_is_unknown(part_off_ex)) {
	    part_off = get_number_immediate(part_off_ex);
	    part_off_ex = 0;
      }

	/* If the word index is a constant expression, then evaluate
	   it to select the word, and pay no further heed to the
	   expression itself. 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_ix && number_is_immediate(word_ix, IMM_WID, 0) &&
          !number_is_unknown(word_ix)) {
	    use_word = get_number_immediate(word_ix);
	    assert(use_word < ivl_signal_array_count(sig));
	    word_ix = 0;
      }

      if (ivl_lval_mux(lval))
	    part_off_ex = ivl_lval_mux(lval);

      if (part_off_ex && ivl_signal_dimensions(sig) == 0) {
	    unsigned skip_set = transient_id++;

	      /* There is a mux expression, so this must be a write to
		 a bit-select l-val. Presumably, the x0 index register
		 has been loaded wit the result of the evaluated
		 part select base expression. */
	    assert(!word_ix);

	    draw_eval_expr_into_integer(part_off_ex, 0);
	    fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);

	    fprintf(vvp_out, "    %%set/x0 v%p_%lu, %u, %u;\n",
		    sig, use_word, bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);
	      /* save_signal width of 0 CLEARS the signal from the
	         lookaside. */
	    save_signal_lookaside(bit, sig, use_word, 0);

      } else if (part_off_ex && ivl_signal_dimensions(sig) > 0) {

	      /* Here we have a part select write into an array word. */
	    unsigned skip_set = transient_id++;
	    if (word_ix) {
		  draw_eval_expr_into_integer(word_ix, 3);
		  fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
	    } else {
		  fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n", use_word);
	    }
	    draw_eval_expr_into_integer(part_off_ex, 1);
	    fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
	    fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
		    sig, bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);

      } else if ((part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig))
		 && ivl_signal_dimensions(sig) > 0) {

	      /* Here we have a part select write into an array word. */
	    unsigned skip_set = transient_id++;
	    if (word_ix) {
		  draw_eval_expr_into_integer(word_ix, 3);
		  fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
	    } else {
		  fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n", use_word);
	    }
	    fprintf(vvp_out, "    %%ix/load 1, %lu, 0;\n", part_off);
	    fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
		    sig, bit, wid);
	    if (word_ix) /* Only need this label if word_ix is set. */
		  fprintf(vvp_out, "t_%u ;\n", skip_set);

      } else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
	      /* There is no mux expression, but a constant part
		 offset. Load that into index x0 and generate a
		 vector set instruction. */
	    assert(ivl_lval_width(lval) == wid);

	      /* If the word index is a constant, then we can write
	         directly to the word and save the index calculation. */
	    if (word_ix == 0) {
		  fprintf(vvp_out, "    %%ix/load 0, %lu, 0;\n", part_off);
		  fprintf(vvp_out, "    %%set/x0 v%p_%lu, %u, %u;\n",
		          sig, use_word, bit, wid);

	    } else {
		  unsigned skip_set = transient_id++;
		  unsigned index_reg = 3;
		  draw_eval_expr_into_integer(word_ix, index_reg);
		  fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
		  fprintf(vvp_out, "    %%ix/load 1, %lu, 0;\n", part_off);
		  fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
			  sig, bit, wid);
		  fprintf(vvp_out, "t_%u ;\n", skip_set);
	    }
	      /* save_signal width of 0 CLEARS the signal from the
	         lookaside. */
	    save_signal_lookaside(bit, sig, use_word, 0);

      } else if (ivl_signal_dimensions(sig) > 0) {

	      /* If the word index is a constant, then we can write
	         directly to the word and save the index calculation. */
	    if (word_ix == 0) {
		  fprintf(vvp_out, "    %%ix/load 1, 0, 0;\n");
		  fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n", use_word);
		  fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
			  sig, bit, wid);

	    } else {
		  unsigned skip_set = transient_id++;
		  unsigned index_reg = 3;
		  draw_eval_expr_into_integer(word_ix, index_reg);
		  fprintf(vvp_out, "    %%jmp/1 t_%u, 4;\n", skip_set);
		  fprintf(vvp_out, "    %%ix/load 1, 0, 0;\n");
		  fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
			  sig, bit, wid);
		  fprintf(vvp_out, "t_%u ;\n", skip_set);
	    }
	      /* save_signal width of 0 CLEARS the signal from the
	         lookaside. */
	    save_signal_lookaside(bit, sig, use_word, 0);


      } else {
	    fprintf(vvp_out, "    %%set/v v%p_%lu, %u, %u;\n",
		    sig, use_word, bit, wid);
	      /* save_signal width of 0 CLEARS the signal from the
	         lookaside. */
	    save_signal_lookaside(bit, sig, use_word, 0);

      }
}
Beispiel #9
0
static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
				  unsigned bit, unsigned wid)
{
      unsigned skip_set = transient_id++;
      struct vector_info tmp;
      ivl_signal_t sig = ivl_lval_sig(lval);

	/* If the slice of the l-value is a BOOL variable, then cast
	   the data to a BOOL vector so that the stores can be valid. */
      if (ivl_signal_data_type(sig) == IVL_VT_BOOL) {
	    fprintf(vvp_out, "    %%cast2 %u, %u, %u;\n", bit, bit, wid);
      }

      switch (slice->type) {
	  default:
	    assert(0);
	    break;

	  case SLICE_SIMPLE_VECTOR:
	    fprintf(vvp_out, "    %%set/v v%p_%lu, %u, %u;\n",
		    sig, slice->u_.simple_vector.use_word, bit, wid);
	    break;

	  case SLICE_PART_SELECT_STATIC:
	    fprintf(vvp_out, "    %%ix/load 0, %lu, 0;\n",
		    slice->u_.part_select_static.part_off);
	    fprintf(vvp_out, "    %%set/x0 v%p_0, %u, %u;\n", sig, bit, wid);
	    break;

	  case SLICE_PART_SELECT_DYNAMIC:
	    fprintf(vvp_out, "    %%jmp/1 t_%u, %u;\n", skip_set,
		    slice->u_.part_select_dynamic.x_flag);
	    fprintf(vvp_out, "    %%mov/wu 0, %d;\n",
		    slice->u_.part_select_dynamic.word_idx_reg);
	    fprintf(vvp_out, "    %%set/x0 v%p_0, %u, %u;\n", sig, bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);
	    break;

	  case SLICE_MEMORY_WORD_STATIC:
	    if (slice->u_.simple_vector.use_word >= ivl_signal_array_count(sig))
		  break;
	    fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n",
		    slice->u_.simple_vector.use_word);
	    fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
		    sig, bit, wid);
	    break;

	  case SLICE_MEMORY_WORD_DYNAMIC:
	    fprintf(vvp_out, "    %%jmp/1 t_%u, %u;\n", skip_set,
		    slice->u_.memory_word_dynamic.x_flag);
	    fprintf(vvp_out, "    %%mov/wu 3, %d;\n",
		    slice->u_.memory_word_dynamic.word_idx_reg);
	    fprintf(vvp_out, "    %%set/av v%p, %u, %u;\n",
		    ivl_lval_sig(lval), bit, wid);
	    fprintf(vvp_out, "t_%u ;\n", skip_set);

	    tmp.base = slice->u_.memory_word_dynamic.x_flag;
	    tmp.wid = 1;
	    clr_vector(tmp);
	    clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
	    break;
      }
}
Beispiel #10
0
/*
 * This function draws a net. This is a bit more complicated as we
 * have to find an appropriate functor to connect to the input.
 */
static void draw_net_in_scope(ivl_signal_t sig)
{
      int msb = ivl_signal_msb(sig);
      int lsb = ivl_signal_lsb(sig);

      const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
      const char*local_flag = ivl_signal_local(sig)? "*" : "";
      unsigned iword;

      switch (ivl_signal_data_type(sig)) {
	  case IVL_VT_REAL:
	    datatype_flag = "/real";
	    break;
	  default:
	    break;
      }

      for (iword = 0 ;  iword < ivl_signal_array_count(sig); iword += 1) {

	    unsigned word_count = ivl_signal_array_count(sig);
	    unsigned dimensions = ivl_signal_dimensions(sig);
	    struct vvp_nexus_data*nex_data;

	      /* Connect the pin of the signal to something. */
	    ivl_nexus_t nex = ivl_signal_nex(sig, iword);
	    const char*driver = draw_net_input(nex);

	    nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
	    assert(nex_data);

	    if (nex_data->net == 0) {
		  int strength_aware_flag = 0;
		  const char*vec8 = "";
		  if (nex_data->flags&VVP_NEXUS_DATA_STR)
			strength_aware_flag = 1;
		  if (nex_data->drivers_count > 1)
			vec8 = "8";
		  if (strength_aware_flag)
			vec8 = "8";

		  if (iword == 0 && dimensions > 0) {
			int last = ivl_signal_array_base(sig) + word_count-1;
			int first = ivl_signal_array_base(sig);
			fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				sig, vvp_mangle_name(ivl_signal_basename(sig)),
				last, first);
		  }
		  if (dimensions > 0) {
			/* If this is a word of an array, then use an
			   array reference in place of the net name. */
			fprintf(vvp_out, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, sig,
				iword, msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  } else {
			/* If this is an isolated word, it uses its
			   own name. */
			assert(word_count == 1);
			fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, local_flag,
				vvp_mangle_name(ivl_signal_basename(sig)),
				msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  }
		  nex_data->net = sig;
		  nex_data->net_word = iword;

	    } else if (dimensions > 0) {

		    /* In this case, we have an alias to an existing
		       signal array. this typically is an instance of
		       port collapsing that the elaborator combined to
		       discover that the entire array can be collapsed,
		       so the word count for the signal and the alias
		       *must* match. */

		  if (word_count == ivl_signal_array_count(nex_data->net)) {
		    if (iword == 0) {
		      fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
			      sig, vvp_mangle_name(ivl_signal_basename(sig)),
			      nex_data->net,
			      ivl_signal_basename(nex_data->net));
		    }
		    /* An alias for an individual word. */
		  } else {
			if (iword == 0) {
			      int first = ivl_signal_array_base(sig);
			      int last = first + word_count-1;
			      fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				      sig,
				      vvp_mangle_name(ivl_signal_basename(sig)),
				      last, first);
			}

			fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
			        "v%p_%u; Alias to %s\n", sig, iword,
			        datatype_flag, sig, iword, msb, lsb,
			        nex_data->net, nex_data->net_word,
			        ivl_signal_basename(nex_data->net));
		  }
	    } else {
		    /* Finally, we may have an alias that is a word
		       connected to another word. Again, this is a
		       case of port collapsing. */

		    /* For the alias, create a different kind of node
		       that refers to the alias source data instead of
		       holding our own data. */
		  fprintf(vvp_out, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
			  sig, iword, datatype_flag,
			  vvp_mangle_name(ivl_signal_basename(sig)),
			  msb, lsb, nex_data->net, nex_data->net_word);
	    }
      }
}
Beispiel #11
0
static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
				    unsigned wid)
{
      ivl_signal_t sig = ivl_lval_sig(lval);
      ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
      unsigned long part_off = 0;

	/* Although Verilog doesn't support it, we'll handle
	   here the case of an l-value part select of an array
	   word if the address is constant. */
      ivl_expr_t word_ix = ivl_lval_idx(lval);
      unsigned long use_word = 0;

      if (part_off_ex == 0) {
	    part_off = 0;
      } else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
                 !number_is_unknown(part_off_ex)) {
	    part_off = get_number_immediate(part_off_ex);
	    part_off_ex = 0;
      }

	/* If the word index is a constant expression, then evaluate
	   it to select the word, and pay no further heed to the
	   expression itself. */
      if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
	    assert(! number_is_unknown(word_ix));
	    use_word = get_number_immediate(word_ix);
	    word_ix = 0;
      }

      if (ivl_signal_dimensions(sig)==0 && part_off_ex==0 && word_ix==0
	  && part_off==0 && wid==ivl_signal_width(sig)) {

	    slice->type = SLICE_SIMPLE_VECTOR;
	    slice->u_.simple_vector.use_word = use_word;
	    fprintf(vvp_out, "    %%load/vec4 v%p_%lu;\n", sig, use_word);

      } else if (ivl_signal_dimensions(sig)==0 && part_off_ex==0 && word_ix==0) {

	    assert(use_word == 0);

	    slice->type = SLICE_PART_SELECT_STATIC;
	    slice->u_.part_select_static.part_off = part_off;

	    fprintf(vvp_out, "    %%load/vec4 v%p_%lu;\n", sig, use_word);
	    fprintf(vvp_out, "    %%pushi/vec4 %lu, 0, 32;\n", part_off);
	    fprintf(vvp_out, "    %%part/u %u;\n", wid);

      } else if (ivl_signal_dimensions(sig)==0 && part_off_ex!=0 && word_ix==0) {

	    assert(use_word == 0);
	    assert(part_off == 0);

	    slice->type = SLICE_PART_SELECT_DYNAMIC;

	    slice->u_.part_select_dynamic.word_idx_reg = allocate_word();
	    slice->u_.part_select_dynamic.x_flag = allocate_flag();

	    fprintf(vvp_out, "    %%load/vec4 v%p_%lu;\n", sig, use_word);
	    draw_eval_vec4(part_off_ex);
	    fprintf(vvp_out, "    %%flag_mov %u, 4;\n", slice->u_.part_select_dynamic.x_flag);
	    fprintf(vvp_out, "    %%dup/vec4;\n");
	    fprintf(vvp_out, "    %%ix/vec4 %u;\n", slice->u_.part_select_dynamic.word_idx_reg);
	    fprintf(vvp_out, "    %%part/u %u;\n", wid);

      } else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {

	    slice->type = SLICE_MEMORY_WORD_STATIC;
	    slice->u_.memory_word_static.use_word = use_word;
	    if (use_word < ivl_signal_array_count(sig)) {
		  fprintf(vvp_out, "    %%ix/load 3, %lu, 0;\n",
			  use_word);
		  fprintf(vvp_out, "    %%load/vec4a v%p, 3;\n", sig);
	    } else {
		  assert(wid <= 32);
		  fprintf(vvp_out, "    %%pushi/vec4 4294967295, 4294967295, %u;\n", wid);
	    }

      } else if (ivl_signal_dimensions(sig) > 0 && word_ix != 0) {

	    slice->type = SLICE_MEMORY_WORD_DYNAMIC;

	    slice->u_.memory_word_dynamic.word_idx_reg = allocate_word();
	    slice->u_.memory_word_dynamic.x_flag = allocate_flag();

	    draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
	    fprintf(vvp_out, "    %%flag_mov %d, 4;\n", slice->u_.memory_word_dynamic.x_flag);
	    fprintf(vvp_out, "    %%load/vec4a v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);

      } else {
	    assert(0);
      }
}
Beispiel #12
0
static int show_stmt_assign_sig_cobject(ivl_statement_t net)
{
      int errors = 0;
      ivl_lval_t lval = ivl_stmt_lval(net, 0);
      ivl_expr_t rval = ivl_stmt_rval(net);
      ivl_signal_t sig= ivl_lval_sig(lval);
      unsigned lwid = ivl_lval_width(lval);

      int prop_idx = ivl_lval_property_idx(lval);

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

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

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

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

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

		  draw_eval_vec4(rval);

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

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

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

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

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

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

		  int idx = 0;

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

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

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

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

		  if (idx_expr) clr_word(idx);

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

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

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

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

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

      return errors;
}
Beispiel #13
0
static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
				  unsigned wid)
{
	//unsigned skip_set = transient_id++;
      ivl_signal_t sig = ivl_lval_sig(lval);
      int part_off_idx;

	/* If the slice of the l-value is a BOOL variable, then cast
	   the data to a BOOL vector so that the stores can be valid. */
      if (ivl_signal_data_type(sig) == IVL_VT_BOOL) {
	    fprintf(vvp_out, "    %%cast2;\n");
      }

      switch (slice->type) {
	  default:
	    fprintf(vvp_out, " ; XXXX slice->type=%d\n", slice->type);
	    assert(0);
	    break;

	  case SLICE_SIMPLE_VECTOR:
	    fprintf(vvp_out, "    %%store/vec4 v%p_%lu, 0, %u;\n",
		    sig, slice->u_.simple_vector.use_word, wid);
	    break;

	  case SLICE_PART_SELECT_STATIC:
	    part_off_idx = allocate_word();
	    fprintf(vvp_out, "    %%ix/load %d, %lu, 0;\n",
		    part_off_idx, slice->u_.part_select_static.part_off);
	    fprintf(vvp_out, "    %%flag_set/imm 4, 0;\n");
	    fprintf(vvp_out, "    %%store/vec4 v%p_0, %d, %u;\n",
		    sig, part_off_idx, wid);
	    clr_word(part_off_idx);
	    break;

	  case SLICE_PART_SELECT_DYNAMIC:
	    fprintf(vvp_out, "    %%flag_mov 4, %u;\n",
		    slice->u_.part_select_dynamic.x_flag);
	    fprintf(vvp_out, "    %%store/vec4 v%p_0, %d, %u;\n",
		    sig, slice->u_.part_select_dynamic.word_idx_reg, wid);
	    clr_word(slice->u_.part_select_dynamic.word_idx_reg);
	    clr_flag(slice->u_.part_select_dynamic.x_flag);
	    break;

	  case SLICE_MEMORY_WORD_STATIC:
	    if (slice->u_.memory_word_static.use_word < ivl_signal_array_count(sig)) {
		  int word_idx = allocate_word();
		  fprintf(vvp_out,"    %%flag_set/imm 4, 0;\n");
		  fprintf(vvp_out,"    %%ix/load %d, %lu, 0;\n", word_idx, slice->u_.memory_word_static.use_word);
		  fprintf(vvp_out,"    %%store/vec4a v%p, %d, 0;\n", sig, word_idx);
		  clr_word(word_idx);
	    } else {
		  fprintf(vvp_out," ; Skip this slice write to v%p [%lu]\n", sig, slice->u_.memory_word_static.use_word);
	    }
	    break;

	  case SLICE_MEMORY_WORD_DYNAMIC:
	    fprintf(vvp_out, "    %%flag_mov 4, %d;\n", slice->u_.memory_word_dynamic.x_flag);
	    fprintf(vvp_out, "    %%store/vec4a v%p, %d, 0;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
	    clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
	    clr_flag(slice->u_.memory_word_dynamic.x_flag);
	    break;

      }
}
Beispiel #14
0
static void show_signal(ivl_signal_t net)
{
      unsigned idx;

      const char*type = "?";
      const char*port = "";
      const char*data_type = "?";
      const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";

      switch (ivl_signal_type(net)) {
	  case IVL_SIT_REG:
	    type = "reg";
	    break;
	  case IVL_SIT_TRI:
	    type = "tri";
	    break;
	  case IVL_SIT_TRI0:
	    type = "tri0";
	    break;
	  case IVL_SIT_TRI1:
	    type = "tri1";
	    break;
	  case IVL_SIT_UWIRE:
	    type = "uwire";
	    break;
	  default:
	    break;
      }

      switch (ivl_signal_port(net)) {

	  case IVL_SIP_INPUT:
	    port = "input ";
	    break;

	  case IVL_SIP_OUTPUT:
	    port = "output ";
	    break;

	  case IVL_SIP_INOUT:
	    port = "inout ";
	    break;

	  case IVL_SIP_NONE:
	    break;
      }

      switch (ivl_signal_data_type(net)) {

	  case IVL_VT_BOOL:
	    data_type = "bool";
	    break;

	  case IVL_VT_LOGIC:
	    data_type = "logic";
	    break;

	  case IVL_VT_REAL:
	    data_type = "real";
	    break;

	  default:
	    data_type = "?data?";
	    break;
      }

      const char*discipline_txt = "NONE";
      if (ivl_signal_discipline(net)) {
	    ivl_discipline_t dis = ivl_signal_discipline(net);
	    discipline_txt = ivl_discipline_name(dis);
      }

      for (idx = 0 ;  idx < ivl_signal_array_count(net) ; idx += 1) {

	    ivl_nexus_t nex = ivl_signal_nex(net, idx);

	    fprintf(out, "  %s %s %s%s[%d:%d] %s[word=%u, adr=%d]  "
		               "<width=%u%s> <discipline=%s> ",
		    type, sign, port, data_type,
		    ivl_signal_msb(net), ivl_signal_lsb(net),
		    ivl_signal_basename(net),
		    idx, ivl_signal_array_base(net)+idx,
		    ivl_signal_width(net),
		    ivl_signal_local(net)? ", local":"",
		    discipline_txt);
	    if (nex == NULL) {
		  fprintf(out, "nexus=<virtual>\n");
		  continue;
	    } else {
		  fprintf(out, "nexus=%p\n", nex);
	    }

	    show_nexus_details(net, nex);
      }

      for (idx = 0 ;  idx < ivl_signal_npath(net) ;  idx += 1) {
	    ivl_delaypath_t path = ivl_signal_path(net,idx);
	    ivl_nexus_t nex = ivl_path_source(path);
	    ivl_nexus_t con = ivl_path_condit(path);
	    int posedge = ivl_path_source_posedge(path);
	    int negedge = ivl_path_source_negedge(path);

	    fprintf(out, "      path %p", nex);
	    if (posedge) fprintf(out, " posedge");
	    if (negedge) fprintf(out, " negedge");
	    if (con) fprintf(out, " (if %p)", con);
	    else if (ivl_path_is_condit(path)) fprintf(out, " (ifnone)");
	    fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64,
		    ivl_path_delay(path, IVL_PE_01),
		    ivl_path_delay(path, IVL_PE_10),
		    ivl_path_delay(path, IVL_PE_0z),
		    ivl_path_delay(path, IVL_PE_z1),
		    ivl_path_delay(path, IVL_PE_1z),
		    ivl_path_delay(path, IVL_PE_z0),
		    ivl_path_delay(path, IVL_PE_0x),
		    ivl_path_delay(path, IVL_PE_x1),
		    ivl_path_delay(path, IVL_PE_1x),
		    ivl_path_delay(path, IVL_PE_x0),
		    ivl_path_delay(path, IVL_PE_xz),
		    ivl_path_delay(path, IVL_PE_zx));
	    fprintf(out, " scope=%s\n", ivl_scope_name(ivl_path_scope(path)));
      }

      for (idx = 0 ;  idx < ivl_signal_attr_cnt(net) ;  idx += 1) {
	    ivl_attribute_t atr = ivl_signal_attr_val(net, idx);

	    switch (atr->type) {
		case IVL_ATT_STR:
		  fprintf(out, "    %s = %s\n", atr->key, atr->val.str);
		  break;
		case IVL_ATT_NUM:
		  fprintf(out, "    %s = %ld\n", atr->key, atr->val.num);
		  break;
		case IVL_ATT_VOID:
		  fprintf(out, "    %s\n", atr->key);
		  break;
	    }
      }

}