Example #1
0
void show_constant(ivl_net_const_t net)
{
      assert(net);

      fprintf(out, "constant ");
      switch (ivl_const_type(net)) {
	  case IVL_VT_BOOL:
	  case IVL_VT_LOGIC:
	    {
	    const char*bits = ivl_const_bits(net);
	    unsigned idx;
	    assert(bits);
	    for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1)
		  fprintf(out, "%c", bits[idx]);
	    }
	    break;
	  case IVL_VT_REAL:
	    fprintf(out, "%f", ivl_const_real(net));
	    break;
	  default:
	    fprintf(out, "<unsupported type>");
	    break;
      }
      fprintf(out, " at %s:%u\n", ivl_const_file(net), ivl_const_lineno(net));
}
Example #2
0
void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t net_const)
{
      ivl_scope_t const_scope = ivl_const_scope(net_const);
      unsigned idx, count, lineno;
      const char *file;
      count = ivl_scope_params(const_scope);
      file = ivl_const_file(net_const);
      lineno = ivl_const_lineno(net_const);
	/* Look to see if the constant matches a parameter in its scope. */
      for (idx = 0; idx < count; idx += 1) {
	    ivl_parameter_t par = ivl_scope_param(const_scope, idx);
	    if (lineno != ivl_parameter_lineno(par)) continue;
	    if (strcmp(file, ivl_parameter_file(par)) == 0) {
		    /* Check that the appropriate expression bits match the
		     * original parameter bits. */
// HERE: Verify that the values match and then print the name.
//       Does this work with out of scope references? Check real parameters.
		  emit_id(ivl_parameter_basename(par));
		  return;
	    }
      }

	/* If the scopes don't match then we assume this is an empty port. */
      if (const_scope != scope)  {
	      /* This constant could really be from an input port. */
	    if (emit_as_input(scope, net_const)) return;
	    fprintf(vlog_out, "/* Empty */");
	    return;
      }

      switch (ivl_const_type(net_const)) {
	case IVL_VT_LOGIC:
	case IVL_VT_BOOL:
	    emit_number(ivl_const_bits(net_const),
	                ivl_const_width(net_const),
	                ivl_const_signed(net_const),
	                ivl_const_file(net_const),
	                ivl_const_lineno(net_const));
	    break;
	case IVL_VT_STRING:
	    emit_number_as_string(net_const);
	    break;
	case IVL_VT_REAL:
	    emit_real_number(ivl_const_real(net_const));
	    break;
	default:
	    fprintf(vlog_out, "<invalid>");
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown constant type "
	                    "(%d).\n",
	                    ivl_const_file(net_const),
	                    ivl_const_lineno(net_const),
	                    (int)ivl_const_type(net_const));
	    vlog_errors += 1;
	    break;
      }
}
Example #3
0
/*
 * This function is used by the show_signal to dump a constant value
 * that is connected to the signal. While we are here, check that the
 * value is consistent with the signal itself.
 */
static void signal_nexus_const(ivl_signal_t sig,
			       ivl_nexus_ptr_t ptr,
			       ivl_net_const_t con)
{
      const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
      const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];

      const char*bits;
      unsigned idx, width = ivl_const_width(con);

      fprintf(out, "      const-");

      switch (ivl_const_type(con)) {
	  case IVL_VT_BOOL:
	  case IVL_VT_LOGIC:
	    bits = ivl_const_bits(con);
	    assert(bits);
	    for (idx = 0 ;  idx < width ;  idx += 1) {
		  fprintf(out, "%c", bits[width-idx-1]);
	    }
	    break;

	  case IVL_VT_REAL:
	    fprintf(out, "%f", ivl_const_real(con));
	    break;

	  default:
	    fprintf(out, "????");
	    break;
      }

      fprintf(out, " (%s0, %s1, width=%u)\n", dr0, dr1, width);

      if (ivl_signal_width(sig) != width) {
	    fprintf(out, "ERROR: Width of signal does not match "
		    "width of connected constant vector.\n");
	    stub_errors += 1;
      }

      int drive_type_ok = check_signal_drive_type(ivl_signal_data_type(sig),
						  ivl_const_type(con));

      if (! drive_type_ok) {
	    fprintf(out, "ERROR: Signal data type does not match"
		    " literal type.\n");
	    stub_errors += 1;
      }
}
Example #4
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>");
}
Example #5
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 (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
	    return draw_net_pull(lptr, ivl_nexus_ptr_drive0(nptr), "0");
      }

      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
	    return draw_net_pull(lptr, ivl_nexus_ptr_drive1(nptr), "1");
      }

      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 tmp[64];
	    char *result = 0;
	    ivl_expr_t d_rise, d_fall, d_decay;
            unsigned dly_width = 0;
	    char *dly;

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

	    dly = "";
	    if (d_rise != 0) {
		  draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay);
		  dly = "/d";
	    }
	    fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
		    cptr, dly, result);
	    free(result);

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

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

	  case IVL_LPM_FF:
	  case IVL_LPM_LATCH:
	  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_WEQ:
	  case IVL_LPM_CMP_WNE:
	  case IVL_LPM_CMP_EQX:
	  case IVL_LPM_CMP_EQZ:
	  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:
	  case IVL_LPM_SUBSTITUTE:
	    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>");
}