Ejemplo n.º 1
0
void draw_eval_string(ivl_expr_t expr)
{

      switch (ivl_expr_type(expr)) {
	  case IVL_EX_STRING:
	    string_ex_string(expr);
	    break;

	  case IVL_EX_SIGNAL:
	    string_ex_signal(expr);
	    break;

	  case IVL_EX_CONCAT:
	    string_ex_concat(expr);
	    break;

	  case IVL_EX_PROPERTY:
	    string_ex_property(expr);
	    break;

	  case IVL_EX_SELECT:
	    string_ex_select(expr);
	    break;

	  case IVL_EX_SFUNC:
	    if (strcmp(ivl_expr_name(expr), "$ivl_string_method$substr") == 0)
		  string_ex_substr(expr);
	    else
		  fallback_eval(expr);
	    break;

	  default:
	    fallback_eval(expr);
	    break;
      }
}
Ejemplo n.º 2
0
static void emit_select_name(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
	/* A select of a number is really a parameter select. */
      if (ivl_expr_type(expr) == IVL_EX_NUMBER) {
	      /* Look in the current scope. */
	    if (emit_param_name_in_scope(scope, expr)) return;
	      /* Now look in the enclosing module scope if this is not a
	       * module scope. */
	    if (ivl_scope_type(scope) != IVL_SCT_MODULE) {
		  if (emit_param_name_in_scope(get_module_scope(scope),
		                               expr)) return;
	    }
// HERE: For now we only look in the current and module scope for the
//       parameter that is being selected. We need to also look in other
//       scopes, but that involves a big search.
	    fprintf(vlog_out, "<missing>");
	    fprintf(stderr, "%s:%u: vlog95 error: Unable to find parameter "
	                    "for select expression \n",
	                    ivl_expr_file(expr), ivl_expr_lineno(expr));
	    vlog_errors += 1;
      } else {
	    emit_expr(scope, expr, wid);
      }
}
static void draw_vpi_taskfunc_args(const char*call_string,
				   ivl_statement_t tnet,
				   ivl_expr_t fnet)
{
      unsigned idx;
      unsigned parm_count = tnet
	    ? ivl_stmt_parm_count(tnet)
	    : ivl_expr_parms(fnet);
      struct vector_info *vec = 0x0;
      unsigned int vecs= 0;
      unsigned int veci= 0;

      ivl_parameter_t par;

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

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

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

		  break;

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

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

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

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

		  } else {
			continue;
		  }


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	    switch (ivl_expr_value(expr)) {

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

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

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

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

      fprintf(vvp_out, ";\n");
}
Ejemplo n.º 4
0
static int draw_condition_binary_compare(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);

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

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

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

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

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

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

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

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

      char use_opcode = ivl_expr_opcode(expr);


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

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

}
Ejemplo n.º 5
0
static int get_vpi_taskfunc_signal_arg(struct args_info *result,
                                       ivl_expr_t expr)
{
      char buffer[4096];

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

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

	         If I don't need to do any evaluating, then skip it as
	         I'll be passing the handle to the signal itself. */
	    if (ivl_expr_width(expr) !=
	        ivl_signal_width(ivl_expr_signal(expr))) {
		    /* This should never happen since we have IVL_EX_SELECT. */
		  return 0;

	    } else if (ivl_expr_signed(expr) !=
	               ivl_signal_signed(ivl_expr_signal(expr))) {
		  return 0;
	    } else if (is_fixed_memory_word(expr)) {
		  /* This is a word of a non-array, or a word of a net
		     array, so we can address the word directly. */
		  ivl_signal_t sig = ivl_expr_signal(expr);
		  unsigned use_word = 0;
		  ivl_expr_t word_ex = ivl_expr_oper1(expr);
		  if (word_ex) {
			  /* Some array select have been evaluated. */
			if (number_is_immediate(word_ex,IMM_WID, 0)) {
			      assert(! number_is_unknown(word_ex));
			      use_word = get_number_immediate(word_ex);
			      word_ex = 0;
			}
		  }
		  if (word_ex) return 0;

		  assert(word_ex == 0);
		  snprintf(buffer, sizeof buffer, "v%p_%u", sig, use_word);
		  result->text = strdup(buffer);
		  return 1;

	    } else {
		  /* What's left, this is the work of a var array.
		     Create the right code to handle it. */
		  ivl_signal_t sig = ivl_expr_signal(expr);
		  unsigned use_word = 0;
		  unsigned use_word_defined = 0;
		  ivl_expr_t word_ex = ivl_expr_oper1(expr);
		  if (word_ex) {
			  /* Some array select have been evaluated. */
			if (number_is_immediate(word_ex, IMM_WID, 0)) {
			      assert(! number_is_unknown(word_ex));
			      use_word = get_number_immediate(word_ex);
			      use_word_defined = 1;
			      word_ex = 0;
			}
		  }
		  if (word_ex && (ivl_expr_type(word_ex)==IVL_EX_SIGNAL ||
		                  ivl_expr_type(word_ex)==IVL_EX_SELECT)) {
			  /* Special case: the index is a signal/select. */
			result->child = calloc(1, sizeof(struct args_info));
			if (get_vpi_taskfunc_signal_arg(result->child,
			                                word_ex)) {
			      snprintf(buffer, sizeof buffer, "&A<v%p, %s >",
			               sig, result->child->text);
			      free(result->child->text);
			} else {
			      free(result->child);
			      result->child = NULL;
			      return 0;
			}
		  } else if (word_ex) {
			/* Fallback case: evaluate expression. */
			struct vector_info av;
			av = draw_eval_expr(word_ex, STUFF_OK_XZ);
			snprintf(buffer, sizeof buffer, "&A<v%p, %u %u \"%s\">",
			         sig, av.base, av.wid,
			         (ivl_expr_signed(word_ex) ? "s" : "u"));
			result->vec = av;
			result->vec_flag = 1;
		  } else {
			assert(use_word_defined);
			snprintf(buffer, sizeof buffer, "&A<v%p, %u>",
			         sig, use_word);
		  }
		  result->text = strdup(buffer);
		  return 1;
	    }

	  case IVL_EX_SELECT: {
	    ivl_expr_t vexpr = ivl_expr_oper1(expr);
	    ivl_expr_t bexpr;
	    ivl_expr_t wexpr;

	    assert(vexpr);

	      /* This code is only for signals or selects. */
	    if (ivl_expr_type(vexpr) != IVL_EX_SIGNAL &&
	        ivl_expr_type(vexpr) != IVL_EX_SELECT) return 0;

	      /* The signal is part of an array. */
	      /* Add &APV<> code here when it is finished. */
	    bexpr = ivl_expr_oper2(expr);

              /* This is a pad operation. */
	    if (!bexpr) return 0;

	    wexpr = ivl_expr_oper1(vexpr);

	      /* If vexpr has an operand, then that operand is a word
		 index and we are taking a select from an array
		 word. This would come up in expressions like
		 "array[<word>][<part>]" where wexpr is <word> */
	    if (wexpr && number_is_immediate(wexpr, 64, 1)
		&& number_is_immediate(bexpr, 64, 1)) {
		  assert(! number_is_unknown(bexpr));
		  assert(! number_is_unknown(wexpr));
		  snprintf(buffer, sizeof buffer, "&APV<v%p, %ld, %ld, %u>",
			   ivl_expr_signal(vexpr),
			   get_number_immediate(wexpr),
			   get_number_immediate(bexpr),
			   ivl_expr_width(expr));

	    } else if (wexpr) {
		  return 0;

	      /* This is a constant bit/part select. */
	    } else if (number_is_immediate(bexpr, 64, 1)) {
		  assert(! number_is_unknown(bexpr));
		  snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
		           ivl_expr_signal(vexpr),
		           get_number_immediate(bexpr),
		           ivl_expr_width(expr));

	      /* This is an indexed bit/part select. */
	    } else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL ||
	               ivl_expr_type(bexpr) == IVL_EX_SELECT) {
		    /* Special case: the base is a signal/select. */
		  result->child = calloc(1, sizeof(struct args_info));
		  if (get_vpi_taskfunc_signal_arg(result->child, bexpr)) {
			snprintf(buffer, sizeof buffer, "&PV<v%p_0, %s, %u>",
			         ivl_expr_signal(vexpr),
			         result->child->text,
			         ivl_expr_width(expr));
			free(result->child->text);
		  } else {
			free(result->child);
			result->child = NULL;
			return 0;
		  }
	    } else {
		    /* Fallback case: evaluate the expression. */
		  struct vector_info rv;
		  rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
		  snprintf(buffer, sizeof buffer,
		           "&PV<v%p_0, %u %u \"%s\", %u>",
		           ivl_expr_signal(vexpr),
		           rv.base, rv.wid,
		           (ivl_expr_signed(bexpr) ? "s" : "u"),
		           ivl_expr_width(expr));
		  result->vec = rv;
		  result->vec_flag = 1;
	    }
	    result->text = strdup(buffer);
	    return 1;
	  }

	  default:
	    return 0;
      }
}
Ejemplo n.º 6
0
/*
 * Emit a constant or variable delay that has been rescaled to the given
 * scopes timescale.
 */
void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
{
      ivl_expr_type_t type = ivl_expr_type(expr);
      if (type == IVL_EX_DELAY) {
	    emit_scaled_delay(scope, ivl_expr_delay_val(expr));
      } else if (type == IVL_EX_NUMBER) {
	    assert(! ivl_expr_signed(expr));
	    int rtype;
	    uint64_t value = get_uint64_from_number(expr, &rtype);
	    if (rtype > 0) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Time value is "
		                  "greater than 64 bits (%u) and cannot be "
		                  "safely represented.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr),
		                  rtype);
		  vlog_errors += 1;
		  return;
	    }
	    if (rtype < 0) {
		  fprintf(vlog_out, "<invalid>");
		  fprintf(stderr, "%s:%u: vlog95 error: Time value has an "
		                  "undefined bit and cannot be represented.\n",
		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
		  vlog_errors += 1;
		  return;
	    }
	    emit_scaled_delay(scope, value);
      } else {
	    int exponent = ivl_scope_time_units(scope) - sim_precision;
	    assert(exponent >= 0);
	    if ((exponent == 0) && (type == IVL_EX_SIGNAL)) {
		  emit_delay(scope, expr, is_stmt);
	      /* A real delay variable is not scaled by the compiler. */
	    } else if (type == IVL_EX_SIGNAL) {
		  if (is_stmt) {
			fprintf(vlog_out, "<invalid>");
			fprintf(stderr, "%s:%u: vlog95 error: Only continuous "
			                "assignment delay variables are scaled "
			                "at run time.\n", ivl_expr_file(expr),
			                ivl_expr_lineno(expr));
			vlog_errors += 1;
			return;
		  }
		  emit_delay(scope, expr, is_stmt);
	    } else {
		  uint64_t iscale = 1;
		  unsigned rtn;
		  assert(! ivl_expr_signed(expr));
		    /* Calculate the integer time scaling coefficient. */
		  while (exponent > 0) {
			iscale *= 10;
			exponent -= 1;
		  }
		    /* Check to see if this is an integer time value. */
		  rtn = check_scaled_expr(expr, iscale, "Variable time", 0);
		    /* This may be a scaled real value. */
		  if (rtn == 2){
			ivl_expr_t tmp_expr;
			uint64_t rprec = 1;
			  /* This could be a scaled real time so calculate
			   * the real time scaling coefficients and check
			   * that the expression matches (statements only). */
			exponent = ivl_scope_time_precision(scope) -
			           sim_precision;
			assert(exponent >= 0);
			while (exponent > 0) {
			      rprec *= 10;
			      exponent -= 1;
			}
			  /* Verify that the precision scaling is correct. */
			if (! check_scaled_expr(expr, rprec,
			                        "Variable real time prec.",
			                        1)) {
			      fprintf(vlog_out, "<invalid>");
			      return;
			}
			  /* Verify that the left operator is a real to
			   * integer cast. */
			tmp_expr = ivl_expr_oper1(expr);
			if ((ivl_expr_type(tmp_expr) != IVL_EX_UNARY) ||
		            (ivl_expr_opcode(tmp_expr) != 'v')) {
			      fprintf(vlog_out, "<invalid>");
			      fprintf(stderr, "%s:%u: vlog95 error: Real time "
			                      "value does not have a cast to "
			                      "integer.\n",
			                      ivl_expr_file(expr),
			                      ivl_expr_lineno(expr));
			      vlog_errors += 1;
			      return;
			}
			  /* Check that the cast value is scaled correctly. */
			assert(iscale >= rprec);
			tmp_expr = ivl_expr_oper1(tmp_expr);
			assert(ivl_expr_value(tmp_expr) == IVL_VT_REAL);
			if (! check_scaled_real_expr(tmp_expr, iscale/rprec)) {
			      fprintf(vlog_out, "<invalid>");
			      return;
			}
			assert(is_stmt);
			emit_delay(scope, ivl_expr_oper1(tmp_expr), is_stmt);
			return;
		  } else if (rtn == 1) {
			emit_delay(scope, ivl_expr_oper1(expr), is_stmt);
			return;
		  }
		  fprintf(vlog_out, "<invalid>");
	    }
      }
}
Ejemplo n.º 7
0
static void draw_binary_vec4_le(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);
      ivl_expr_t tmp;

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

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

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

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

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

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

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

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

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

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

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

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

      switch (use_opcode) {
	  case 'L':
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 5;\n");
	    fprintf(vvp_out, "    %%or;\n");
	    break;
	  case '<':
	    fprintf(vvp_out, "    %%flag_get/vec4 5;\n");
	    break;
	  default:
	    assert(0);
	    break;
      }
}
Ejemplo n.º 8
0
static void draw_binary_vec4_compare_class(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);

      if (ivl_expr_type(le) == IVL_EX_NULL) {
	    ivl_expr_t tmp = le;
	    le = re;
	    re = tmp;
      }

	/* Special case: If both operands are null, then the
	   expression has a constant value. */
      if (ivl_expr_type(le)==IVL_EX_NULL && ivl_expr_type(re)==IVL_EX_NULL) {
	    switch (ivl_expr_opcode(expr)) {
		case 'e': /* == */
		  fprintf(vvp_out, "    %%pushi/vec4 1, 0, 1;\n");
		  break;
		case 'n': /* != */
		  fprintf(vvp_out, "    %%pushi/vec4 0, 0, 1;\n");
		  break;
		default:
		  assert(0);
		  break;
	    }
	    return;
      }

	/* A signal/variable is compared to null. Implement this with
	   the %test_nul statement, which peeks at the variable
	   contents directly. */
      if (ivl_expr_type(re)==IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_SIGNAL) {
	    ivl_signal_t sig= ivl_expr_signal(le);

	    if (ivl_signal_dimensions(sig) == 0) {
		  fprintf(vvp_out, "    %%test_nul v%p_0;\n", sig);
	    } else {
		  ivl_expr_t word_ex = ivl_expr_oper1(le);
		  int word_ix = allocate_word();
		  draw_eval_expr_into_integer(word_ex, word_ix);
		  fprintf(vvp_out, "    %%test_nul/a v%p, %d;\n", sig, word_ix);
		  clr_word(word_ix);
	    }
	    if (ivl_expr_opcode(expr) == 'n')
		  fprintf(vvp_out, "    %%flag_inv 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    return;
      }

      if (ivl_expr_type(re)==IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_PROPERTY) {
	    ivl_signal_t sig = ivl_expr_signal(le);
	    unsigned pidx = ivl_expr_property_idx(le);
	    ivl_expr_t idx_expr = ivl_expr_oper1(le);
	    int idx = 0;

	      /* If the property has an array index, then evaluate it
		 into an index register. */
	    if ( idx_expr ) {
		  idx = allocate_word();
		  draw_eval_expr_into_integer(idx_expr, idx);
	    }

	    fprintf(vvp_out, "    %%load/obj v%p_0;\n", sig);
	    fprintf(vvp_out, "    %%test_nul/prop %u, %d;\n", pidx, idx);
	    fprintf(vvp_out, "    %%pop/obj 1, 0;\n");
	    if (ivl_expr_opcode(expr) == 'n')
		  fprintf(vvp_out, "    %%flag_inv 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");

	    if (idx != 0) clr_word(idx);
	    return;
      }

      fprintf(stderr, "SORRY: Compare class handles not implemented\n");
      fprintf(vvp_out, " ; XXXX compare class handles. re-type=%d, le-type=%d\n",
	      ivl_expr_type(re), ivl_expr_type(le));
      vvp_errors += 1;
}
Ejemplo n.º 9
0
void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      switch (ivl_expr_type(expr)) {
	case IVL_EX_ARRAY:
	    emit_expr_array(scope, expr, wid);
	    break;
	case IVL_EX_BINARY:
	    emit_expr_binary(scope, expr, wid);
	    break;
	case IVL_EX_CONCAT:
	    emit_expr_concat(scope, expr, wid);
	    break;
	case IVL_EX_DELAY:
	    emit_expr_delay(scope, expr, wid);
	    break;
	case IVL_EX_ENUMTYPE:
	    fprintf(vlog_out, "<enum>");
	    fprintf(stderr, "%s:%u: vlog95 error: Enum expressions "
	                    "are not supported.\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr));
	    vlog_errors += 1;
	    break;
	case IVL_EX_EVENT:
	    emit_expr_event(scope, expr, wid);
	    break;
	case IVL_EX_NUMBER:
	    emit_number(ivl_expr_bits(expr), ivl_expr_width(expr),
	                ivl_expr_signed(expr), ivl_expr_file(expr),
	                ivl_expr_lineno(expr));
	    break;
	case IVL_EX_REALNUM:
	    emit_real_number(ivl_expr_dvalue(expr));
	    break;
	case IVL_EX_SCOPE:
	    emit_expr_scope(scope, expr, wid);
	    break;
	case IVL_EX_SELECT:
	    emit_expr_select(scope, expr, wid);
	    break;
	case IVL_EX_SFUNC:
	    fprintf(vlog_out, "%s", ivl_expr_name(expr));
	    emit_expr_func(scope, expr, wid);
	    break;
	case IVL_EX_SIGNAL:
	    emit_expr_signal(scope, expr, wid);
	    break;
	case IVL_EX_STRING:
	    emit_string(ivl_expr_string(expr));
	    break;
	case IVL_EX_TERNARY:
	    emit_expr_ternary(scope, expr, wid);
	    break;
	case IVL_EX_UFUNC:
	    emit_scope_path(scope, ivl_expr_def(expr));
	    emit_expr_func(scope, expr, wid);
	    break;
	case IVL_EX_UNARY:
	    emit_expr_unary(scope, expr, wid);
	    break;
	default:
	    fprintf(vlog_out, "<unknown>");
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown expression "
	                    "type (%d).\n",
	                    ivl_expr_file(expr),
	                    ivl_expr_lineno(expr),
	                    (int)ivl_expr_type(expr));
	    vlog_errors += 1;
	    break;
      }
}
Ejemplo n.º 10
0
static void draw_logic_in_scope(ivl_net_logic_t lptr)
{
      unsigned pdx;
      const char*ltype = "?";
      const char*lcasc = 0;
      char identity_val = '0';

      int need_delay_flag = ivl_logic_delay(lptr,0)? 1 : 0;

      unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0));

      ivl_drive_t str0, str1;

      int level;
      int ninp = ivl_logic_pins(lptr) - 1;
      typedef const char*const_charp;
      const_charp*input_strings = calloc(ninp, sizeof(const_charp));

      for (pdx = 0 ;  pdx < ninp ;  pdx += 1) {
	    ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
	    if (nex == 0) {
		    /* Only UDPs can have unconnected inputs. */
		  assert(ivl_logic_type(lptr) == IVL_LO_UDP);
		  input_strings[pdx] = 0;
	    } else {
		  input_strings[pdx] = draw_net_input(nex);
	    }
      }

      switch (ivl_logic_type(lptr)) {

          case IVL_LO_UDP:
	    free(input_strings);
	    draw_udp_in_scope(lptr);
	    return;

          case IVL_LO_BUFZ: {
		  /* Draw bufz objects, but only if the gate cannot
		     be elided. If I can elide it, then the
		     draw_nex_input will take care of it for me. */
		ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0);

		ltype = "BUFZ";

		if (can_elide_bufz(lptr, nptr))
		      return;

		break;
	  }

	  case IVL_LO_PULLDOWN:
	  case IVL_LO_PULLUP:
	      /* Skip pullup and pulldown objects. Things that have
		 pull objects as inputs will instead generate the
		 appropriate C<?> symbol. */
	    free(input_strings);
	    return;

	  case IVL_LO_AND:
	    ltype = "AND";
	    identity_val = '1';
	    break;

	  case IVL_LO_BUF:
	    ltype = "BUF";
	    break;

	  case IVL_LO_BUFIF0:
	    ltype = "BUFIF0";
	    break;

	  case IVL_LO_BUFIF1:
	    ltype = "BUFIF1";
	    break;

	  case IVL_LO_NAND:
	    ltype = "NAND";
	    lcasc = "AND";
	    identity_val = '1';
	    break;

	  case IVL_LO_NOR:
	    ltype = "NOR";
	    lcasc = "OR";
	    break;

	  case IVL_LO_NOT:
	    ltype = "NOT";
	    break;

	  case IVL_LO_OR:
	    ltype = "OR";
	    break;

	  case IVL_LO_XNOR:
	    ltype = "XNOR";
	    lcasc = "XOR";
	    break;

	  case IVL_LO_XOR:
	    ltype = "XOR";
	    break;

	  case IVL_LO_CMOS:
	    ltype = "CMOS";
	    break;

	  case IVL_LO_PMOS:
	    ltype = "PMOS";
	    break;

	  case IVL_LO_NMOS:
	    ltype = "NMOS";
	    break;

	  case IVL_LO_RCMOS:
	    ltype = "RCMOS";
	    break;

	  case IVL_LO_RPMOS:
	    ltype = "RPMOS";
	    break;

	  case IVL_LO_RNMOS:
	    ltype = "RNMOS";
	    break;

	  case IVL_LO_NOTIF0:
	    ltype = "NOTIF0";
	    break;

	  case IVL_LO_NOTIF1:
	    ltype = "NOTIF1";
	    break;

	  default:
	    fprintf(stderr, "vvp.tgt: error: Unhandled logic type: %u\n",
		    ivl_logic_type(lptr));
	    ltype = "?";
	    break;
      }

      { ivl_nexus_t nex = ivl_logic_pin(lptr, 0);
        ivl_nexus_ptr_t nptr = 0;
        unsigned idx;
	for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	      nptr = ivl_nexus_ptr(nex,idx);
	      if (ivl_nexus_ptr_log(nptr) != lptr)
		    continue;
	      if (ivl_nexus_ptr_pin(nptr) != 0)
		    continue;
	      break;
	}
        str0 = ivl_nexus_ptr_drive0(nptr);
	str1 = ivl_nexus_ptr_drive1(nptr);
      }

      if (!lcasc)
	lcasc = ltype;

	/* Get all the input label that I will use for parameters to
	   the functor that I create later. */
      ninp = ivl_logic_pins(lptr) - 1;
      input_strings = calloc(ninp, sizeof(char*));
      for (pdx = 0 ;  pdx < ninp ;  pdx += 1)
	    input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));

      level = 0;
      ninp = ivl_logic_pins(lptr) - 1;
      while (ninp) {
	    int inst;
	    for (inst = 0; inst < ninp; inst += 4) {
		  if (ninp > 4)
			fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
				lptr, level, inst, lcasc, vector_width);
		  else {
			fprintf(vvp_out, "L_%p%s .functor %s %u",
				lptr, need_delay_flag? "/d" : "",
				ltype, vector_width);

			if (str0 != IVL_DR_STRONG || str1 != IVL_DR_STRONG)
			      fprintf(vvp_out, " [%u %u]", str0, str1);

		  }
		  for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) {
			if (level) {
			      fprintf(vvp_out, ", L_%p/%d/%d",
				      lptr, level - 1, pdx*4);
			} else {
			      fprintf(vvp_out, ", %s", input_strings[pdx]);
			}
		  }
		  for ( ;  pdx < inst+4 ;  pdx += 1) {
			unsigned wdx;
			fprintf(vvp_out, ", C4<");
			for (wdx = 0 ; wdx < vector_width ;  wdx += 1)
			      fprintf(vvp_out, "%c", identity_val);
			fprintf(vvp_out, ">");
		  }

		  fprintf(vvp_out, ";\n");
	    }
	    if (ninp > 4)
		  ninp = (ninp+3) / 4;
	    else
		  ninp = 0;
	    level += 1;
      }

	/* Free the array of char*. The strings themselves are
	   persistent, held by the ivl_nexus_t objects. */
      free(input_strings);

	/* If there are delays, then draw the delay functor to carry
	   that delay. This is the final output. */
      if (need_delay_flag) {
	    ivl_expr_t rise_exp  = ivl_logic_delay(lptr,0);
	    ivl_expr_t fall_exp  = ivl_logic_delay(lptr,1);
	    ivl_expr_t decay_exp = ivl_logic_delay(lptr,2);

	    if (number_is_immediate(rise_exp,64,0)
		&& number_is_immediate(fall_exp,64,0)
		&& number_is_immediate(decay_exp,64,0)) {

		  fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
			  lptr, get_number_immediate(rise_exp),
			  get_number_immediate(rise_exp),
			  get_number_immediate(rise_exp), lptr);
	    } else {
		  ivl_signal_t sig;
		  assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
		  assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
		  assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);

		  fprintf(vvp_out, "L_%p .delay  L_%p/d", lptr, lptr);

		  sig = ivl_expr_signal(rise_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0", sig);

		  sig = ivl_expr_signal(fall_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0", sig);

		  sig = ivl_expr_signal(decay_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0;\n", sig);
	    }
      }
}
Ejemplo n.º 11
0
int draw_scope(ivl_scope_t net, ivl_scope_t parent)
{
      unsigned idx;
      const char *type;

      const char*prefix = ivl_scope_is_auto(net) ? "auto" : "";

      switch (ivl_scope_type(net)) {
      case IVL_SCT_MODULE:   type = "module";   break;
      case IVL_SCT_FUNCTION: type = "function"; break;
      case IVL_SCT_TASK:     type = "task";     break;
      case IVL_SCT_BEGIN:    type = "begin";    break;
      case IVL_SCT_FORK:     type = "fork";     break;
      case IVL_SCT_GENERATE: type = "generate"; break;
      default:               type = "?";        assert(0);
      }

      fprintf(vvp_out, "S_%p .scope %s%s, \"%s\" \"%s\" %d %d",
	      net, prefix, type, vvp_mangle_name(ivl_scope_basename(net)),
              ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)),
              ivl_scope_lineno(net));

      if (parent) {
	    fprintf(vvp_out, ", %d %d, S_%p;\n",
	            ivl_file_table_index(ivl_scope_def_file(net)),
	            ivl_scope_def_lineno(net), parent);
      } else {

	    fprintf(vvp_out, ";\n");
      }

      fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net),
                                               ivl_scope_time_precision(net));

      for (idx = 0 ;  idx < ivl_scope_params(net) ;  idx += 1) {
	    ivl_parameter_t par = ivl_scope_param(net, idx);
	    ivl_expr_t pex = ivl_parameter_expr(par);
	    switch (ivl_expr_type(pex)) {
		case IVL_EX_STRING:
		  fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n",
			  par, ivl_parameter_basename(par),
			  ivl_file_table_index(ivl_parameter_file(par)),
			  ivl_parameter_lineno(par),
			  ivl_expr_string(pex));
		  break;
		case IVL_EX_NUMBER:
		  fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<",
			  par, ivl_parameter_basename(par),
			  ivl_file_table_index(ivl_parameter_file(par)),
			  ivl_parameter_lineno(par),
			  ivl_expr_signed(pex)? "+":"");
		  { const char*bits = ivl_expr_bits(pex);
		    unsigned nbits = ivl_expr_width(pex);
		    unsigned bb;
		    for (bb = 0 ;  bb < nbits;  bb += 1)
			  fprintf(vvp_out, "%c", bits[nbits-bb-1]);
		  }
		  fprintf(vvp_out, ">;\n");
		  break;
		case IVL_EX_REALNUM:
		  fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n",
			  par, ivl_parameter_basename(par),
			  ivl_file_table_index(ivl_parameter_file(par)),
			  ivl_parameter_lineno(par),
			  draw_Cr_to_string(ivl_expr_dvalue(pex)),
			  ivl_expr_dvalue(pex));
		  break;
		default:
		  fprintf(vvp_out, "; parameter type %d unsupported\n",
			  ivl_expr_type(pex));
		  break;
	    }
      }

	/* Scan the scope for logic devices. For each device, draw out
	   a functor that connects pin 0 to the output, and the
	   remaining pins to inputs. */

      for (idx = 0 ;  idx < ivl_scope_logs(net) ;  idx += 1) {
	    ivl_net_logic_t lptr = ivl_scope_log(net, idx);
	    draw_logic_in_scope(lptr);
      }


	/* Scan the signals (reg and net) and draw the appropriate
	   statements to make the signal function. */

      for (idx = 0 ;  idx < ivl_scope_sigs(net) ;  idx += 1) {
	    ivl_signal_t sig = ivl_scope_sig(net, idx);

	    switch (ivl_signal_type(sig)) {
		case IVL_SIT_REG:
		  draw_reg_in_scope(sig);
		  break;
		default:
		  draw_net_in_scope(sig);
		  break;
	    }
      }

      for (idx = 0 ;  idx < ivl_scope_events(net) ;  idx += 1) {
	    ivl_event_t event = ivl_scope_event(net, idx);
	    draw_event_in_scope(event);
      }

      for (idx = 0 ;  idx < ivl_scope_lpms(net) ;  idx += 1) {
	    ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
	    draw_lpm_in_scope(lpm);
      }

      for (idx = 0 ; idx < ivl_scope_switches(net) ; idx += 1) {
	    ivl_switch_t sw = ivl_scope_switch(net, idx);
	    draw_switch_in_scope(sw);
      }

      if (ivl_scope_type(net) == IVL_SCT_TASK)
	    draw_task_definition(net);

      if (ivl_scope_type(net) == IVL_SCT_FUNCTION)
	    draw_func_definition(net);

      ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
      return 0;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
static int eval_darray_new(ivl_expr_t ex)
{
      int errors = 0;
      unsigned size_reg = allocate_word();
      ivl_expr_t size_expr = ivl_expr_oper1(ex);
      ivl_expr_t init_expr = ivl_expr_oper2(ex);
      draw_eval_expr_into_integer(size_expr, size_reg);

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

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

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

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

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

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

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

      return errors;
}
Ejemplo n.º 16
0
static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
      ivl_expr_t sel_expr = ivl_expr_oper2(expr);
      ivl_expr_t sig_expr = ivl_expr_oper1(expr);
      ivl_select_type_t sel_type = ivl_expr_sel_type(expr);
      if (sel_expr) {
	    unsigned width = ivl_expr_width(expr);
	    ivl_expr_type_t type = ivl_expr_type(sig_expr);
	    assert(width > 0);
	      /* The compiler uses selects for some shifts. */
	    if (type != IVL_EX_NUMBER && type != IVL_EX_SIGNAL) {
		  fprintf(vlog_out, "(" );
		  emit_select_name(scope, sig_expr, wid);
		  fprintf(vlog_out, " >> " );
		  emit_scaled_expr(scope, sel_expr, 1, 0);
		  fprintf(vlog_out, ")" );
	    } else {
		    /* A constant/parameter must be zero based in 1364-1995
		     * so keep the compiler generated normalization. This
		     * does not always work for selects before the parameter
		     * since 1364-1995 does not support signed math. */
		  int msb = 1;
		  int lsb = 0;
		  if (type == IVL_EX_SIGNAL) {
			ivl_signal_t sig = ivl_expr_signal(sig_expr);
			msb = ivl_signal_msb(sig);
			lsb = ivl_signal_lsb(sig);
		  }
		    /* A bit select. */
		  if (width == 1) {
			emit_select_name(scope, sig_expr, wid);
			fprintf(vlog_out, "[");
			emit_scaled_expr(scope, sel_expr, msb, lsb);
			fprintf(vlog_out, "]");
		  } else {
			if (ivl_expr_type(sel_expr) == IVL_EX_NUMBER) {
				/* A constant part select. */
			      emit_select_name(scope, sig_expr, wid);
			      emit_scaled_range(scope, sel_expr, width,
			                        msb, lsb);
			} else {
				/* An indexed part select. */
			      assert(sel_type != IVL_SEL_OTHER);
			      emit_expr_ips(scope, sig_expr, sel_expr,
			                    sel_type, width, msb, lsb);
			}
		  }
	    }
      } else {
// HERE: Should this sign extend if the expression is signed?
	    emit_expr(scope, sig_expr, wid);
	      /* Select part of a signal when needed. */
	    if ((ivl_expr_type(sig_expr) == IVL_EX_SIGNAL) &&
	        (ivl_expr_width(expr) < ivl_expr_width(sig_expr))) {
		  ivl_signal_t sig = ivl_expr_signal(sig_expr);
		  int msb = ivl_signal_msb(sig);
		  int lsb = ivl_signal_lsb(sig);
		  int64_t value = lsb;
		  unsigned e_wid = ivl_expr_width(expr) - 1;
		  if (msb >= lsb) value += e_wid;
		  else value -= e_wid;
		  fprintf(vlog_out, "[%"PRId64":%u]", value, lsb);
	    }
      }
}
Ejemplo n.º 17
0
static void show_expression(ivl_expr_t net)
{
      if (net == 0)
	    return;

      switch (ivl_expr_type(net)) {

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

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

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

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

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

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

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

	  default:
	    fprintf(out, "...");
      }
}
Ejemplo n.º 18
0
void draw_eval_vec4(ivl_expr_t expr)
{
      if (debug_draw) {
	    fprintf(vvp_out, " ; %s:%u:draw_eval_vec4: expr_type=%d\n",
		    ivl_expr_file(expr), ivl_expr_lineno(expr),
		    ivl_expr_type(expr));
      }

      switch (ivl_expr_type(expr)) {
	  case IVL_EX_BINARY:
	    draw_binary_vec4(expr);
	    return;

	  case IVL_EX_CONCAT:
	    draw_concat_vec4(expr);
	    return;

	  case IVL_EX_NUMBER:
	    draw_number_vec4(expr);
	    return;

	  case IVL_EX_SELECT:
	    if (ivl_expr_oper2(expr)==0)
		  draw_select_pad_vec4(expr);
	    else
		  draw_select_vec4(expr);
	    return;

	  case IVL_EX_SFUNC:
	    draw_sfunc_vec4(expr);
	    return;

	  case IVL_EX_SIGNAL:
	    draw_signal_vec4(expr);
	    return;

	  case IVL_EX_STRING:
	    draw_string_vec4(expr);
	    return;

	  case IVL_EX_TERNARY:
	    draw_ternary_vec4(expr);
	    return;

	  case IVL_EX_UFUNC:
	    draw_ufunc_vec4(expr);
	    return;

	  case IVL_EX_UNARY:
	    draw_unary_vec4(expr);
	    return;

	  case IVL_EX_PROPERTY:
	    draw_property_vec4(expr);
	    return;

	  default:
	    break;
      }

      fprintf(stderr, "XXXX Evaluate VEC4 expression (%d)\n", ivl_expr_type(expr));
      fprintf(vvp_out, "; XXXX Evaluate VEC4 expression (%d)\n", ivl_expr_type(expr));
}
Ejemplo n.º 19
0
// Build the design hierarchy.
int build_hierarchy(ivl_scope_t scope, void* cd)
{
  int return_code;
  unsigned i, j;

  indent();
  fprintf(output, "(scope ");
  quoted_string(ivl_scope_tname(scope));
  fprintf(output, " ");
  quoted_string(ivl_scope_basename(scope));
  fprintf(output, " (\n");

  // Constants (root scope only)
  if (! level)
    for (i = 0; i < ivl_design_consts(design); i++) {
      ivl_net_const_t constant = ivl_design_const(design, i);
      const char* bits = ivl_const_bits(constant);
      unsigned pins = ivl_const_pins(constant);
      unsigned id = new_id();
      indent();
      fprintf(output, "  (const  %i \"", id);
      for (j = pins - 1; j < pins; j--)
        fprintf(output, "%c", bits[j]);
      fprintf(output, "\")\n");
      for (j = 0; j < pins; j++)
        create_bit_select(id_of_nexus(ivl_const_pin(constant, j), 1), pins, j, id);
    }

  // Parameters
  for (i = 0; i < ivl_scope_params(scope); i++) {
    ivl_parameter_t param = ivl_scope_param(scope, i);
    ivl_expr_t param_value = ivl_parameter_expr(param);
    unsigned width = ivl_expr_width(param_value);
    const char* bits;
    unsigned id = new_id();
    indent();
    fprintf(output, "  (const  %i \"", id);
    switch (ivl_expr_type(param_value)) {
      case IVL_EX_STRING : bits = ivl_expr_string(param_value); break;
      case IVL_EX_NUMBER : bits = ivl_expr_bits(param_value);   break;
      default            : fprintf(output, "** ERROR: Unknown parameter type."); return -1;
    }
    for (j = width - 1; j < width; j--)
      fprintf(output, "%c", bits[j]);
    fprintf(output, "\")\n");
    indent();
    fprintf(output, "  (name   %i ", new_id());
    quoted_string(ivl_parameter_basename(param));
    fprintf(output, " %i %i)\n", width, id);
  }

  // Signals
  for (i = 0; i < ivl_scope_sigs(scope); i++) {
    ivl_signal_t sig = ivl_scope_sig(scope, i);
    unsigned pins = ivl_signal_pins(sig);
    ivl_signal_port_t type = ivl_signal_port(sig);
    const char* name = ivl_signal_basename(sig);
    unsigned id;
    if (! level && type == IVL_SIP_INPUT) {
      id = new_id();
      fprintf(output, "  (input  %i \"%s\" %i)\n", id, name, pins);
      for (j = 0; j < pins; j++)
        create_bit_select(id_of_nexus(ivl_signal_pin(sig, j), 1), pins, j, id);
    }
    else if (! level && type == IVL_SIP_INOUT) {
      printf("** ERROR: Inout ports not supported.\n");
    }
    else if (! level && type == IVL_SIP_OUTPUT) {
      id = id_of_nexus(ivl_signal_pin(sig, 0), 0);
      for (j = 1; j < pins; j++) {
        id = create_bit_concat(id, j, ivl_signal_pin(sig, j));
      }
      fprintf(output, "  (output %i \"%s\" %i %i)\n", new_id(), name, pins, id);
    }
    else {
      id = id_of_nexus(ivl_signal_pin(sig, 0), 0);
      for (j = 1; j < pins; j++) {
        id = create_bit_concat(id, j, ivl_signal_pin(sig, j));
      }
      indent();
      fprintf(output, "  (name   %i ", new_id());  //XXX Why is "_s22" getting named?
      quoted_string(name);
      fprintf(output, " %i %i)\n", pins, id);
    }
  }

  // Logic
  for (i = 0; i < ivl_scope_logs(scope); i++) {
    unsigned id;
    ivl_net_logic_t log = ivl_scope_log(scope, i);
    switch (ivl_logic_type(log)) {
      case IVL_LO_BUF:
        indent();
        fprintf(output, "  (buf    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0));
        break;

      case IVL_LO_NOT:
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0));
        break;

      case IVL_LO_AND:
        indent();
        create_multi_gate("and ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_NAND:
        id = new_id();
        indent();
        create_multi_gate("and ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;
      
      case IVL_LO_XOR:
        indent();
        create_multi_gate("xor ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_XNOR:
        id = new_id();
        indent();
        create_multi_gate("xor ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;
      
      case IVL_LO_OR:
        indent();
        create_multi_gate("or  ", id_of_nexus(ivl_logic_pin(log, 0), 1), log);
        break;
      
      case IVL_LO_NOR:
        id = new_id();
        indent();
        create_multi_gate("or  ", id, log);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id);
        break;

      default:
        printf("** ERROR: Unsupported logic type: %i.\n", ivl_logic_type(log));
        return -1;
    }
  }
  
  // LPMs
  for (i = 0; i < ivl_scope_lpms(scope); i++) {
    ivl_lpm_t lpm = ivl_scope_lpm(scope, i);
    ivl_lpm_type_t lpm_t = ivl_lpm_type(lpm);
    unsigned width   = ivl_lpm_width(lpm);
    unsigned selects;
    unsigned size;
    unsigned id, id1, id2, id3;
    switch (lpm_t) {
      case IVL_LPM_ADD:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (add    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_SUB:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (sub    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_MULT:
        id  = new_id();
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (mul    %i %i %i %i)\n", id, width, id1, id2);
        create_split_lpm_q(lpm, id);
        break;

      case IVL_LPM_CMP_EQ:
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (eq     %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id1, id2);
        break;

      case IVL_LPM_CMP_NE:
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        id  = new_id();
        indent();
        fprintf(output, "  (eq     %i %i %i %i)\n", id, width, id1, id2);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id);
        break;

      case IVL_LPM_CMP_GT:
        // XXX Check for signed.
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        indent();
        fprintf(output, "  (lt     %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id2, id1);
        break;

      case IVL_LPM_CMP_GE:
        // XXX Check for signed.
        id1 = create_concat_lpm_data(lpm);
        id2 = create_concat_lpm_datab(lpm);
        id  = new_id();
        indent();
        fprintf(output, "  (lt     %i %i %i %i)\n", id, width, id1, id2);
        indent();
        fprintf(output, "  (not    %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id);
        break;

      case IVL_LPM_FF:
        {
          ivl_nexus_t async_clr = ivl_lpm_async_clr(lpm);
          ivl_nexus_t async_set = ivl_lpm_async_set(lpm);
          ivl_nexus_t sync_clr = ivl_lpm_sync_clr(lpm);
          ivl_nexus_t sync_set = ivl_lpm_sync_set(lpm);
          ivl_nexus_t clk = ivl_lpm_clk(lpm);
          ivl_nexus_t enable = ivl_lpm_enable(lpm);
          if (async_set || sync_set) { perror("** ERROR: Does not support registers with async or sync sets.\n"); return -1; }
          id = new_id();
          id1 = create_concat_lpm_data(lpm);
          if (enable) {
            id2 = new_id();
            indent();
            fprintf(output, "  (mux    %i %i %i %i %i)\n", id2, width, id_of_nexus(enable, 0), id, id1);
            id1 = id2;
          }
          if (sync_clr) {
            id2 = new_id();
            id3 = new_id();
            indent();
            fprintf(output, "  (const  %i \"", id3);
            for (j = 0; j < width; j++)
              fprintf(output, "0");
            fprintf(output, "\")\n");
            indent();
            fprintf(output, "  (mux    %i %i %i %i %i)\n", id2, width, id_of_nexus(sync_clr, 0), id1, id3);
            id1 = id2;
          }
          // XXX Default to posedge sensitivity.
          if (async_clr) {
            indent();
            fprintf(output, "  (ffc    %i %i %i %i %i)\n", id, width, id_of_nexus(async_clr, 0), id_of_nexus(clk, 0), id1);
          }
          else {
            indent();
            fprintf(output, "  (ff     %i %i %i %i)\n", id, width, id_of_nexus(clk, 0), id1);
          }
          create_split_lpm_q(lpm, id);
        }
        break;

      case IVL_LPM_MUX:
        {
          unsigned t = 1;
          selects = ivl_lpm_selects(lpm);
          size    = ivl_lpm_size(lpm);
          for (j = 0; j < selects; j++)
            t = t * 2;
          assert(t == size); // General case.
          id = create_mux(lpm, selects, 0);
          create_split_lpm_q(lpm, id);
        }
        break;

      default:
        perror("** ERROR: Unsupported LPM type.\n");
        return -1;
    }
  }
  level = level + 1;
  return_code = ivl_scope_children(scope, build_hierarchy, 0);
  level = level - 1;
  if (! level)
    delete_nexus_table(nexus_table);
  indent();
  fprintf(output, "))\n");
  return return_code;
}
Ejemplo n.º 20
0
static void draw_binary_vec4_compare(ivl_expr_t expr)
{
      ivl_expr_t le = ivl_expr_oper1(expr);
      ivl_expr_t re = ivl_expr_oper2(expr);

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

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

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

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

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

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

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

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

      switch (ivl_expr_opcode(expr)) {
	  case 'e': /* == */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    break;
	  case 'n': /* != */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_inv 4;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 4;\n");
	    break;
	  case 'E': /* === */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 6;\n");
	    break;
	  case 'N': /* !== */
	    fprintf(vvp_out, "    %%cmp/e;\n");
	    fprintf(vvp_out, "    %%flag_inv 6;\n");
	    fprintf(vvp_out, "    %%flag_get/vec4 6;\n");
	    break;
	  default:
	    assert(0);
      }
}
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;
}
Ejemplo n.º 22
0
void show_expression(ivl_expr_t net, unsigned ind)
{
      assert(net);
      unsigned idx;
      ivl_parameter_t par = ivl_expr_parameter(net);
      const ivl_expr_type_t code = ivl_expr_type(net);
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*sized = ivl_expr_sized(net)? "sized" : "unsized";
      const char*vt = vt_type_string(net);

      switch (code) {

	  case IVL_EX_ARRAY:
	    show_array_expression(net, ind);
	    break;

	  case IVL_EX_ARRAY_PATTERN:
	    show_array_pattern_expression(net, ind);
	    break;

	  case IVL_EX_BACCESS:
	    show_branch_access_expression(net, ind);
	    break;

	  case IVL_EX_BINARY:
	    show_binary_expression(net, ind);
	    break;

	  case IVL_EX_CONCAT:
	    fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
		    ind, "", ivl_expr_repeat(net), width, sign, vt);
	    for (idx = 0 ;  idx < ivl_expr_parms(net) ;  idx += 1)
		  show_expression(ivl_expr_parm(net, idx), ind+3);

	    break;

	  case IVL_EX_ENUMTYPE:
	    show_enumtype_expression(net, ind);
	    break;

	  case IVL_EX_MEMORY:
	    show_memory_expression(net, ind);
	    break;

	  case IVL_EX_NEW:
	    show_new_expression(net, ind);
	    break;

	  case IVL_EX_NULL:
	    show_null_expression(net, ind);
	    break;

	  case IVL_EX_PROPERTY:
	    show_property_expression(net, ind);
	    break;

	  case IVL_EX_NUMBER: {
		const char*bits = ivl_expr_bits(net);

		fprintf(out, "%*s<number=%u'b", ind, "", width);
		for (idx = width ;  idx > 0 ;  idx -= 1)
		      fprintf(out, "%c", bits[idx-1]);

		fprintf(out, ", %s %s %s", sign, sized, vt);
		if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

		fprintf(out, ">\n");
		break;
	  }

	  case IVL_EX_SELECT:
	    show_select_expression(net, ind);
	    break;

	  case IVL_EX_STRING:
	    fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
		    ivl_expr_string(net), ivl_expr_width(net));
	    if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

	    fprintf(out, ", type=%s>\n", vt);
	    break;

	  case IVL_EX_SFUNC:
	    fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s file=%s:%u>\n",
		    ind, "", ivl_expr_name(net), width, sign, vt,
		    ivl_expr_file(net), ivl_expr_lineno(net));
	    { unsigned cnt = ivl_expr_parms(net);
	      unsigned jdx;
	      for (jdx = 0 ;  jdx < cnt ;  jdx += 1)
		    show_expression(ivl_expr_parm(net, jdx), ind+3);
	    }
	    break;

	  case IVL_EX_SIGNAL:
	    show_signal_expression(net, ind);
	    break;

	  case IVL_EX_TERNARY:
	    show_ternary_expression(net, ind);
	    break;

	  case IVL_EX_UNARY:
	    show_unary_expression(net, ind);
	    break;

	  case IVL_EX_UFUNC:
	    show_function_call(net, ind);
	    break;

	  case IVL_EX_REALNUM:
	      {
		    int jdx;
		    union foo {
			  double rv;
			  unsigned char bv[sizeof(double)];
		    } tmp;
		    tmp.rv = ivl_expr_dvalue(net);
		    fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
		    for (jdx = sizeof(double) ;  jdx > 0 ;  jdx -= 1)
			  fprintf(out, "%02x", tmp.bv[jdx-1]);
		    fprintf(out, ")");
		    if (par != 0)
			  fprintf(out, ", parameter=%s",
				  ivl_parameter_basename(par));

		    fprintf(out, ">\n");
	      }
	      break;

	  case IVL_EX_SHALLOWCOPY:
	    show_shallowcopy(net, ind);
	    break;

	  default:
	    fprintf(out, "%*s<expr_type=%d>\n", ind, "", code);
	    break;
      }
}
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;
}
Ejemplo n.º 24
0
static void draw_vpi_taskfunc_args(const char*call_string,
				   ivl_statement_t tnet,
				   ivl_expr_t fnet)
{
      unsigned idx;
      unsigned parm_count = tnet
	    ? ivl_stmt_parm_count(tnet)
	    : ivl_expr_parms(fnet);

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

      char buffer[4096];

      ivl_parameter_t par;

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

	    switch (ivl_expr_type(expr)) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      free(args);

      fprintf(vvp_out, ";\n");
}
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
{
      ivl_expr_t exp = ivl_stmt_cond_expr(net);
      struct vector_info cond = draw_eval_expr(exp, 0);
      unsigned count = ivl_stmt_case_count(net);

      unsigned local_base = local_count;

      unsigned idx, default_case;

      local_count += count + 1;

	/* First draw the branch table.  All the non-default cases
	   generate a branch out of here, to the code that implements
	   the case. The default will fall through all the tests. */
      default_case = count;

      for (idx = 0 ;  idx < count ;  idx += 1) {
	    ivl_expr_t cex = ivl_stmt_case_expr(net, idx);
	    struct vector_info cvec;

	    if (cex == 0) {
		  default_case = idx;
		  continue;
	    }

	      /* Is the guard expression something I can pass to a
		 %cmpi/u instruction? If so, use that instead. */

	    if ((ivl_statement_type(net) == IVL_ST_CASE)
		&& (ivl_expr_type(cex) == IVL_EX_NUMBER)
		&& (! number_is_unknown(cex))
		&& number_is_immediate(cex, 16)) {

		  unsigned long imm = get_number_immediate(cex);

		  fprintf(vvp_out, "    %%cmpi/u %u, %lu, %u;\n",
			  cond.base, imm, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 6;\n",
			  thread_count, local_base+idx);

		  continue;
	    }

	      /* Oh well, do this case the hard way. */

	    cvec = draw_eval_expr_wid(cex, cond.wid, 0);
	    assert(cvec.wid == cond.wid);

	    switch (ivl_statement_type(net)) {

		case IVL_ST_CASE:
		  fprintf(vvp_out, "    %%cmp/u %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 6;\n",
			  thread_count, local_base+idx);
		  break;

		case IVL_ST_CASEX:
		  fprintf(vvp_out, "    %%cmp/x %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 4;\n",
			  thread_count, local_base+idx);
		  break;

		case IVL_ST_CASEZ:
		  fprintf(vvp_out, "    %%cmp/z %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 4;\n",
			  thread_count, local_base+idx);
		  break;

		default:
		  assert(0);
	    }
	    
	      /* Done with the case expression */
	    clr_vector(cvec);
      }

	/* Done with the condition expression */
      clr_vector(cond);

	/* Emit code for the default case. */
      if (default_case < count) {
	    ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case);
	    show_statement(cst, sscope);
      }

	/* Jump to the out of the case. */
      fprintf(vvp_out, "    %%jmp T_%d.%d;\n", thread_count,
	      local_base+count);

      for (idx = 0 ;  idx < count ;  idx += 1) {
	    ivl_statement_t cst = ivl_stmt_case_stmt(net, idx);

	    if (idx == default_case)
		  continue;

	    fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx);
	    clear_expression_lookaside();
	    show_statement(cst, sscope);

	    fprintf(vvp_out, "    %%jmp T_%d.%d;\n", thread_count,
		    local_base+count);

      }


	/* The out of the case. */
      fprintf(vvp_out, "T_%d.%d ;\n",  thread_count, local_base+count);
      clear_expression_lookaside();

      return 0;
}
Ejemplo n.º 26
0
static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
{
      unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
      ivl_net_const_t cptr;
      ivl_net_logic_t lptr;
      ivl_signal_t sptr;
      ivl_lpm_t lpm;

      lptr = ivl_nexus_ptr_log(nptr);
      if (lptr
	  && ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT))
	  && (nptr_pin == 0))
	    do {
		  if (! can_elide_bufz(lptr, nptr))
			break;

		  return strdup(draw_net_input(ivl_logic_pin(lptr, 1)));
	    } while(0);

	/* If this is a pulldown device, then there is a single pin
	   that drives a constant value to the entire width of the
	   vector. The driver normally drives a pull0 value, so a C8<>
	   constant is appropriate, but if the drive is really strong,
	   then we can draw a C4<> constant instead. */
      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
	    if (ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) {
		  size_t result_len = ivl_logic_width(lptr) + 5;
		  char*result = malloc(result_len);
		  char*dp = result;
		  strcpy(dp, "C4<");
		  dp += strlen(dp);
		  str_repeat(dp, "0", ivl_logic_width(lptr));
		  dp += ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);
		  return result;
	    } else {
		  char val[4];
		  size_t result_len = 3*ivl_logic_width(lptr) + 5;
		  char*result = malloc(result_len);
		  char*dp = result;

		  val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
		  val[1] = val[0];
		  val[2] = '0';
		  val[3] = 0;

		  strcpy(dp, "C8<");
		  dp += strlen(dp);
		  str_repeat(dp, val, ivl_logic_width(lptr));
		  dp += 3*ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);
		  return result;
	    }
      }

      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
	    char*result;
	    char tmp[32];
	    if (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG) {
		  size_t result_len = 5 + ivl_logic_width(lptr);
		  result = malloc(result_len);
		  char*dp = result;
		  strcpy(dp, "C4<");
		  dp += strlen(dp);
		  str_repeat(dp, "1", ivl_logic_width(lptr));
		  dp += ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);

	    } else {
		  char val[4];
		  size_t result_len = 5 + 3*ivl_logic_width(lptr);
		  result = malloc(result_len);
		  char*dp = result;

		  val[0] = "01234567"[ivl_nexus_ptr_drive1(nptr)];
		  val[1] = val[0];
		  val[2] = '1';
		  val[3] = 0;

		  strcpy(dp, "C8<");
		  dp += strlen(dp);
		  str_repeat(dp, val, ivl_logic_width(lptr));
		  dp += 3*ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);

	    }

	      /* Make the constant an argument to a BUFZ, which is
		 what we use to drive the PULLed value. */
	    fprintf(vvp_out, "L_%p .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
		    lptr, result);
	    snprintf(tmp, sizeof tmp, "L_%p", lptr);
	    result = realloc(result, strlen(tmp)+1);
	    strcpy(result, tmp);
	    return result;
      }

      if (lptr && (nptr_pin == 0)) {
	    char tmp[128];
	    snprintf(tmp, sizeof tmp, "L_%p", lptr);
	    return strdup(tmp);
      }

      sptr = ivl_nexus_ptr_sig(nptr);
      if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
	    char tmp[128];
	      /* Input is a .var. This device may be a non-zero pin
	         because it may be an array of reg vectors. */
	    snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin);

	    if (ivl_signal_dimensions(sptr) > 0) {
		  fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n",
			  sptr, nptr_pin, sptr, nptr_pin);
	    }

	    return strdup(tmp);
      }

      cptr = ivl_nexus_ptr_con(nptr);
      if (cptr) {
	    char *result = 0;
	    ivl_expr_t d_rise, d_fall, d_decay;
            unsigned dly_width = 0;

	      /* Constants should have exactly 1 pin, with a literal value. */
	    assert(nptr_pin == 0);

	    switch (ivl_const_type(cptr)) {
		case IVL_VT_LOGIC:
		case IVL_VT_BOOL:
		case IVL_VT_STRING:
		  if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG)
		      && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) {

			result = draw_C4_to_string(cptr);

		  } else {
			result = draw_C8_to_string(cptr,
						   ivl_nexus_ptr_drive0(nptr),
						   ivl_nexus_ptr_drive1(nptr));
		  }
                  dly_width = ivl_const_width(cptr);
		  break;

		case IVL_VT_REAL:
		  result = draw_Cr_to_string(ivl_const_real(cptr));
                  dly_width = 0;
		  break;

		default:
		  assert(0);
		  break;
	    }

	    d_rise = ivl_const_delay(cptr, 0);
	    d_fall = ivl_const_delay(cptr, 1);
	    d_decay = ivl_const_delay(cptr, 2);

	      /* We have a delayed constant, so we need to build some code. */
	    if (d_rise != 0) {
		  char tmp[128];
		  fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
		                   "C4<0>, C4<0>, C4<0>;\n", cptr, result);
		  free(result);

		    /* Is this a fixed or variable delay? */
		  if (number_is_immediate(d_rise, 64, 0) &&
		      number_is_immediate(d_fall, 64, 0) &&
		      number_is_immediate(d_decay, 64, 0)) {

			assert(! number_is_unknown(d_rise));
			assert(! number_is_unknown(d_fall));
			assert(! number_is_unknown(d_decay));

			fprintf(vvp_out, "L_%p .delay %u "
				"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
			                 cptr, dly_width,
			                 get_number_immediate64(d_rise),
			                 get_number_immediate64(d_fall),
			                 get_number_immediate64(d_decay), cptr);

		  } else {
			ivl_signal_t sig;
			// We do not currently support calculating the decay
			// from the rise and fall variable delays.
			assert(d_decay != 0);
			assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
			assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
			assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);

			fprintf(vvp_out, "L_%p .delay %u L_%p/d",
                                cptr, dly_width, cptr);

			sig = ivl_expr_signal(d_rise);
			assert(ivl_signal_dimensions(sig) == 0);
			fprintf(vvp_out, ", v%p_0", sig);

			sig = ivl_expr_signal(d_fall);
			assert(ivl_signal_dimensions(sig) == 0);
			fprintf(vvp_out, ", v%p_0", sig);

			sig = ivl_expr_signal(d_decay);
			assert(ivl_signal_dimensions(sig) == 0);
			fprintf(vvp_out, ", v%p_0;\n", sig);
		  }

		  snprintf(tmp, sizeof tmp, "L_%p", cptr);
		  result = strdup(tmp);

	    } else {
		  char tmp[64];
		  fprintf(vvp_out, "L_%p .functor BUFT 1, %s, "
			  "C4<0>, C4<0>, C4<0>;\n", cptr, result);
		  free(result);

		  snprintf(tmp, sizeof tmp, "L_%p", cptr);
		  result = strdup(tmp);
	    }

	    return result;
      }

      lpm = ivl_nexus_ptr_lpm(nptr);
      if (lpm) switch (ivl_lpm_type(lpm)) {

	  case IVL_LPM_FF:
	  case IVL_LPM_ABS:
	  case IVL_LPM_ADD:
	  case IVL_LPM_ARRAY:
	  case IVL_LPM_CAST_INT2:
	  case IVL_LPM_CAST_INT:
	  case IVL_LPM_CAST_REAL:
	  case IVL_LPM_CONCAT:
	  case IVL_LPM_CONCATZ:
	  case IVL_LPM_CMP_EEQ:
	  case IVL_LPM_CMP_EQ:
	  case IVL_LPM_CMP_GE:
	  case IVL_LPM_CMP_GT:
	  case IVL_LPM_CMP_NE:
	  case IVL_LPM_CMP_NEE:
	  case IVL_LPM_RE_AND:
	  case IVL_LPM_RE_OR:
	  case IVL_LPM_RE_XOR:
	  case IVL_LPM_RE_NAND:
	  case IVL_LPM_RE_NOR:
	  case IVL_LPM_RE_XNOR:
	  case IVL_LPM_SFUNC:
	  case IVL_LPM_SHIFTL:
	  case IVL_LPM_SHIFTR:
	  case IVL_LPM_SIGN_EXT:
	  case IVL_LPM_SUB:
	  case IVL_LPM_MULT:
	  case IVL_LPM_MUX:
	  case IVL_LPM_POW:
	  case IVL_LPM_DIVIDE:
	  case IVL_LPM_MOD:
	  case IVL_LPM_UFUNC:
	  case IVL_LPM_PART_VP:
	  case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
	  case IVL_LPM_REPEAT:
	    if (ivl_lpm_q(lpm) == nex) {
		  char tmp[128];
		  snprintf(tmp, sizeof tmp, "L_%p", lpm);
		  return strdup(tmp);
	    }
	    break;

      }

      fprintf(stderr, "vvp.tgt error: no input to nexus.\n");
      assert(0);
      return strdup("C<z>");
}
Ejemplo n.º 27
0
void show_expression(ivl_expr_t net, unsigned ind)
{
      unsigned idx;
      const ivl_expr_type_t code = ivl_expr_type(net);
      ivl_parameter_t par = ivl_expr_parameter(net);
      unsigned width = ivl_expr_width(net);
      const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
      const char*sized = ivl_expr_sized(net)? "sized" : "unsized";
      const char*vt = vt_type_string(net);

      switch (code) {

	  case IVL_EX_ARRAY:
	    show_array_expression(net, ind);
	    break;

	  case IVL_EX_BACCESS:
	    show_branch_access_expression(net, ind);
	    break;

	  case IVL_EX_BINARY:
	    show_binary_expression(net, ind);
	    break;

	  case IVL_EX_CONCAT:
	    fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
		    ind, "", ivl_expr_repeat(net), width, sign, vt);
	    for (idx = 0 ;  idx < ivl_expr_parms(net) ;  idx += 1)
		  show_expression(ivl_expr_parm(net, idx), ind+3);

	    break;

	  case IVL_EX_MEMORY:
	    show_memory_expression(net, ind);
	    break;

	  case IVL_EX_NUMBER: {
		const char*bits = ivl_expr_bits(net);

		fprintf(out, "%*s<number=%u'b", ind, "", width);
		for (idx = width ;  idx > 0 ;  idx -= 1)
		      fprintf(out, "%c", bits[idx-1]);

		fprintf(out, ", %s %s %s", sign, sized, vt);
		if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

		fprintf(out, ">\n");
		break;
	  }

	  case IVL_EX_SELECT:
	      /* The SELECT expression can be used to express part
		 select, or if the base is null vector extension. */
	    if (ivl_expr_oper2(net)) {
		  fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
			  width, sign);
		  show_expression(ivl_expr_oper1(net), ind+3);
		  show_expression(ivl_expr_oper2(net), ind+3);
	    } else {
		  fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
			  width, sign);
		  show_expression(ivl_expr_oper1(net), ind+3);
	    }
	    break;

	  case IVL_EX_STRING:
	    fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
		    ivl_expr_string(net), ivl_expr_width(net));
	    if (par != 0)
		      fprintf(out, ", parameter=%s",
			      ivl_parameter_basename(par));

	    fprintf(out, ", type=%s>\n", vt);
	    break;

	  case IVL_EX_SFUNC:
	    fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s file=%s:%u>\n",
		    ind, "", ivl_expr_name(net), width, sign, vt,
		    ivl_expr_file(net), ivl_expr_lineno(net));
	    { unsigned cnt = ivl_expr_parms(net);
	      unsigned jdx;
	      for (jdx = 0 ;  jdx < cnt ;  jdx += 1)
		    show_expression(ivl_expr_parm(net, jdx), ind+3);
	    }
	    break;

	  case IVL_EX_SIGNAL:
	    show_signal_expression(net, ind);
	    break;

	  case IVL_EX_TERNARY:
	    show_ternary_expression(net, ind);
	    break;

	  case IVL_EX_UNARY:
	    show_unary_expression(net, ind);
	    break;

	  case IVL_EX_UFUNC:
	    show_function_call(net, ind);
	    break;

	  case IVL_EX_REALNUM:
	      {
		    int jdx;
		    union foo {
			  double rv;
			  unsigned char bv[sizeof(double)];
		    } tmp;
		    tmp.rv = ivl_expr_dvalue(net);
		    fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
		    for (jdx = sizeof(double) ;  jdx > 0 ;  jdx -= 1)
			  fprintf(out, "%02x", tmp.bv[jdx-1]);
		    fprintf(out, ")");
		    if (par != 0)
			  fprintf(out, ", parameter=%s",
				  ivl_parameter_basename(par));

		    fprintf(out, ">\n");
	      }
	      break;

	  default:
	    fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
	    break;
      }
}