Пример #1
0
static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr)
{
      ivl_net_logic_t logic;

      if (ivl_nexus_ptr_drive0(nptr) != IVL_DR_STRONG)
	    return 1;
      if (ivl_nexus_ptr_drive1(nptr) != IVL_DR_STRONG)
	    return 1;

      logic = ivl_nexus_ptr_log(nptr);
      if (logic != 0) {
	      /* These logic gates are able to generate unusual
	         strength values and so their outputs are considered
	         strength aware. */
	    if (ivl_logic_type(logic) == IVL_LO_BUFIF0)
		  return 1;
	    if (ivl_logic_type(logic) == IVL_LO_BUFIF1)
		  return 1;
	    if (ivl_logic_type(logic) == IVL_LO_PMOS)
		  return 1;
	    if (ivl_logic_type(logic) == IVL_LO_NMOS)
		  return 1;
	    if (ivl_logic_type(logic) == IVL_LO_CMOS)
		  return 1;
      }

      return 0;
}
Пример #2
0
/*
 * Pick off the cases where there is a Virtex specific implementation
 * that is better then the generic Xilinx implementation. Route the
 * remaining to the base xilinx_logic implementation.
 */
void virtex_logic(ivl_net_logic_t net)
{
	/* Nothing I can do if the user expresses a specific
	   opinion. The cellref attribute forces me to let the base
	   xilinx_logic take care of it. */
      if (ivl_logic_attr(net, "cellref")) {
	    xilinx_logic(net);
	    return;
      }

      switch (ivl_logic_type(net)) {

	  case IVL_LO_OR:
	  case IVL_LO_NOR:
	    if (ivl_logic_pins(net) <= 5) {
		  xilinx_logic(net);

	    } else {
		  virtex_or_wide(net);
	    }
	    break;

	  default:
	    xilinx_logic(net);
	    break;
      }
}
Пример #3
0
/*
 * Draw a single logic gate. Escape the name so that it is preserved
 * completely. This drawing is happening in the root scope so signal
 * references can remain hierarchical.
 */
static int draw_logic(ivl_net_logic_t net)
{
      unsigned npins, idx;
      const char*name = ivl_logic_name(net);

      switch (ivl_logic_type(net)) {
	  case IVL_LO_AND:
	    fprintf(out, "    and \\%s (", name);
	    break;
	  case IVL_LO_BUF:
	    fprintf(out, "    buf \\%s (", name);
	    break;
	  case IVL_LO_OR:
	    fprintf(out, "    or \\%s (", name);
	    break;
	  case IVL_LO_XOR:
	    fprintf(out, "    xor \\%s (", name);
	    break;
	  default:
	    fprintf(out, "STUB: %s: unsupported gate\n", name);
	    return -1;
      }

      draw_nexus(ivl_logic_pin(net, 0));

      npins = ivl_logic_pins(net);
      for (idx = 1 ;  idx < npins ;  idx += 1) {
	    fprintf(out, ", ");
	    draw_nexus(ivl_logic_pin(net,idx));
      }

      fprintf(out, ");\n");
      return 0;
}
Пример #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>");
}
Пример #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>");
}
Пример #6
0
static void lpm_logic(ivl_net_logic_t net)
{
      edif_cell_t cell;
      edif_cellref_t ref;
      edif_joint_t jnt;

      switch (ivl_logic_type(net)) {

	  case IVL_LO_BUFZ:
	  case IVL_LO_BUF:
	    assert(ivl_logic_pins(net) == 2);
	    cell = lpm_cell_buf();
	    ref = edif_cellref_create(edf, cell);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
	    edif_add_to_joint(jnt, ref, 0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
	    edif_add_to_joint(jnt, ref, 1);
	    break;

	  case IVL_LO_BUFIF0:
	    assert(ivl_logic_pins(net) == 3);
	    cell = lpm_cell_bufif0();
	    ref = edif_cellref_create(edf, cell);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
	    edif_add_to_joint(jnt, ref, 0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
	    edif_add_to_joint(jnt, ref, 1);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
	    edif_add_to_joint(jnt, ref, 2);
	    break;

	  case IVL_LO_BUFIF1:
	    assert(ivl_logic_pins(net) == 3);
	    cell = lpm_cell_bufif1();
	    ref = edif_cellref_create(edf, cell);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
	    edif_add_to_joint(jnt, ref, 0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
	    edif_add_to_joint(jnt, ref, 1);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
	    edif_add_to_joint(jnt, ref, 2);
	    break;

	  case IVL_LO_NOT:
	    assert(ivl_logic_pins(net) == 2);
	    cell = lpm_cell_inv();
	    ref = edif_cellref_create(edf, cell);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
	    edif_add_to_joint(jnt, ref, 0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
	    edif_add_to_joint(jnt, ref, 1);
	    break;

	  case IVL_LO_OR:
	    cell = lpm_cell_or(ivl_logic_pins(net)-1);
	    hookup_logic_gate(net, cell);
	    break;

	  case IVL_LO_NOR:
	    cell = lpm_cell_nor(ivl_logic_pins(net)-1);
	    hookup_logic_gate(net, cell);
	    break;

	  case IVL_LO_AND:
	    cell = lpm_cell_and(ivl_logic_pins(net)-1);
	    hookup_logic_gate( net, cell);
	    break;

	  case IVL_LO_XOR:
	    cell = lpm_cell_xor(ivl_logic_pins(net)-1);
	    hookup_logic_gate( net, cell);
	    break;

	  default:
	    fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
		    ivl_logic_type(net));
	    break;
      }
}
Пример #7
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;
}
Пример #8
0
static void virtex_or_wide(ivl_net_logic_t net)
{
      edif_cell_t cell_muxcy_l = xilinx_cell_muxcy_l(xlib);
      edif_cell_t cell_muxcy = xilinx_cell_muxcy(xlib);
      edif_cell_t cell_lut4 = xilinx_cell_lut4(xlib);

      edif_cellref_t true_out, false_out;
      edif_cellref_t lut, muxcy, muxcy_down=NULL;
      edif_joint_t jnt;

      unsigned idx, inputs, lut4_cnt;

      if (ivl_logic_type(net) == IVL_LO_OR) {
	    true_out  = edif_cellref_create(edf, cell_1);
	    false_out = edif_cellref_create(edf, cell_0);
      } else {
	    true_out  = edif_cellref_create(edf, cell_0);
	    false_out = edif_cellref_create(edf, cell_1);
      }

      inputs = ivl_logic_pins(net) - 1;
      lut4_cnt = (inputs-1)/4;

      for (idx = 0 ;  idx < lut4_cnt ;  idx += 1) {
	    muxcy = edif_cellref_create(edf, cell_muxcy_l);
	    lut = edif_cellref_create(edf, cell_lut4);

	    edif_cellref_pstring(lut, "INIT", "0001");

	    jnt = edif_joint_create(edf);
	    edif_add_to_joint(jnt, lut, LUT_O);
	    edif_add_to_joint(jnt, muxcy, MUXCY_S);

	    jnt = edif_joint_create(edf);
	    edif_add_to_joint(jnt, true_out, 0);
	    edif_add_to_joint(jnt, muxcy, MUXCY_DI);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+0));
	    edif_add_to_joint(jnt, lut, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+1));
	    edif_add_to_joint(jnt, lut, LUT_I1);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+2));
	    edif_add_to_joint(jnt, lut, LUT_I2);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+3));
	    edif_add_to_joint(jnt, lut, LUT_I3);

	    if (idx > 0) {
		  jnt = edif_joint_create(edf);
		  edif_add_to_joint(jnt, muxcy, MUXCY_CI);
		  edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
	    } else {
		  jnt = edif_joint_create(edf);
		  edif_add_to_joint(jnt, muxcy, MUXCY_CI);
		  edif_add_to_joint(jnt, false_out, 0);
	    }

	    muxcy_down = muxcy;
      }

      muxcy = edif_cellref_create(edf, cell_muxcy);
      jnt = edif_joint_create(edf);
      edif_add_to_joint(jnt, true_out, 0);
      edif_add_to_joint(jnt, muxcy, MUXCY_DI);

      jnt = edif_joint_create(edf);
      edif_add_to_joint(jnt, muxcy, MUXCY_CI);
      edif_add_to_joint(jnt, muxcy_down, MUXCY_O);

      switch (ivl_logic_pins(net) - 1 - lut4_cnt*4) {

	  case 1:
	    lut = edif_cellref_create(edf, xilinx_cell_inv(xlib));

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
	    edif_add_to_joint(jnt, lut, BUF_I);
	    break;

	  case 2:
	    lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));

	    edif_cellref_pstring(lut, "INIT", "1");

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
	    edif_add_to_joint(jnt, lut, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
	    edif_add_to_joint(jnt, lut, LUT_I1);
	    break;

	  case 3:
	    lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));

	    edif_cellref_pstring(lut, "INIT", "01");

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
	    edif_add_to_joint(jnt, lut, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
	    edif_add_to_joint(jnt, lut, LUT_I1);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
	    edif_add_to_joint(jnt, lut, LUT_I2);
	    break;

	  case 4:
	    lut = edif_cellref_create(edf, cell_lut4);

	    edif_cellref_pstring(lut, "INIT", "0001");

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
	    edif_add_to_joint(jnt, lut, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
	    edif_add_to_joint(jnt, lut, LUT_I1);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
	    edif_add_to_joint(jnt, lut, LUT_I2);

	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+3));
	    edif_add_to_joint(jnt, lut, LUT_I3);
	    break;

	  default:
	    assert(0);
      }

      jnt = edif_joint_create(edf);
      edif_add_to_joint(jnt, lut, LUT_O);
      edif_add_to_joint(jnt, muxcy, MUXCY_S);

      jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
      edif_add_to_joint(jnt, muxcy, MUXCY_O);
}
Пример #9
0
static void edif_show_logic(ivl_net_logic_t net)
{
      char jbuf[1024];
      unsigned idx;

      edif_uref += 1;

      switch (ivl_logic_type(net)) {

	  case IVL_LO_AND:
	    assert(ivl_logic_pins(net) <= 10);
	    assert(ivl_logic_pins(net) >= 3);

	    fprintf(xnf, "(instance (rename U%u \"%s\")",
		    edif_uref, ivl_logic_name(net));
	    fprintf(xnf, " (viewRef net"
		    " (cellRef AND%u (libraryRef VIRTEX))))\n",
		    ivl_logic_pins(net) - 1);

	    sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
	    edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);

	    for (idx = 1 ;  idx < ivl_logic_pins(net)  ;  idx += 1) {
		  sprintf(jbuf, "(portRef I%u (instanceRef U%u))",
			  idx-1, edif_uref);
		  edif_set_nexus_joint(ivl_logic_pin(net, idx), jbuf);
	    }
	    break;

	  case IVL_LO_BUF:
	    assert(ivl_logic_pins(net) == 2);
	    fprintf(xnf, "(instance (rename U%u \"%s\")",
		    edif_uref, ivl_logic_name(net));
	    fprintf(xnf, " (viewRef net"
		    " (cellRef BUF (libraryRef VIRTEX))))\n");

	    sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
	    edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);

	    sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
	    edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
	    break;

        case IVL_LO_BUFZ:
          {
            static int bufz_warned_once=0;
            if (!bufz_warned_once) {
              fprintf (stderr,
                       "0:0: internal warning: BUFZ objects found "
                       "in EDIF netlist.\n");
              fprintf (stderr,
                       "0:0:                 : I'll make BUFs for them.\n");
              bufz_warned_once=1;
            }
            assert(ivl_logic_pins(net) == 2);
            fprintf(xnf, "(instance (rename U%u \"%s\")",
                    edif_uref, ivl_logic_name(net));
            fprintf(xnf, " (viewRef net"
                    " (cellRef BUF (libraryRef VIRTEX))))\n");

            sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
            edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);

            sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
            edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
          }
          break;

	  case IVL_LO_NOR:
	    assert(ivl_logic_pins(net) <= 10);
	    assert(ivl_logic_pins(net) >= 3);

	    fprintf(xnf, "(instance (rename U%u \"%s\")",
		    edif_uref, ivl_logic_name(net));
	    fprintf(xnf, " (viewRef net"
		    " (cellRef NOR%u (libraryRef VIRTEX))))\n",
		    ivl_logic_pins(net) - 1);

	    sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
	    edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);

	    for (idx = 1 ;  idx < ivl_logic_pins(net)  ;  idx += 1) {
		  sprintf(jbuf, "(portRef I%u (instanceRef U%u))",
			  idx-1, edif_uref);
		  edif_set_nexus_joint(ivl_logic_pin(net, idx), jbuf);
	    }
	    break;

	  default:
	    fprintf(stderr, "UNSUPPORT LOGIC TYPE: %u\n", ivl_logic_type(net));
      }
}
Пример #10
0
static void generic_show_logic(ivl_net_logic_t net)
{
    char name[1024];
    ivl_nexus_t nex;
    unsigned idx;

    xnf_mangle_logic_name(net, name, sizeof name);

    switch (ivl_logic_type(net)) {

    case IVL_LO_AND:
        fprintf(xnf, "SYM, %s, AND, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_BUF:
        assert(ivl_logic_pins(net) == 2);
        fprintf(xnf, "SYM, %s, BUF, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        nex = ivl_logic_pin(net, 1);
        xnf_draw_pin(nex, "I", 'I');
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_NAND:
        fprintf(xnf, "SYM, %s, NAND, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_NOR:
        fprintf(xnf, "SYM, %s, NOR, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_NOT:
        assert(ivl_logic_pins(net) == 2);
        fprintf(xnf, "SYM, %s, INV, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        nex = ivl_logic_pin(net, 1);
        xnf_draw_pin(nex, "I", 'I');
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_OR:
        fprintf(xnf, "SYM, %s, OR, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_XOR:
        fprintf(xnf, "SYM, %s, XOR, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_XNOR:
        fprintf(xnf, "SYM, %s, XNOR, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
            char ipin[32];
            nex = ivl_logic_pin(net, idx);
            sprintf(ipin, "I%u", idx-1);
            xnf_draw_pin(nex, ipin, 'I');
        }
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_BUFIF0:
        fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        nex = ivl_logic_pin(net, 1);
        xnf_draw_pin(nex, "I", 'I');
        nex = ivl_logic_pin(net, 2);
        xnf_draw_pin(nex, "~T", 'I');
        fprintf(xnf, "END\n");
        break;

    case IVL_LO_BUFIF1:
        fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name);
        nex = ivl_logic_pin(net, 0);
        xnf_draw_pin(nex, "O", 'O');
        nex = ivl_logic_pin(net, 1);
        xnf_draw_pin(nex, "I", 'I');
        nex = ivl_logic_pin(net, 2);
        xnf_draw_pin(nex, "T", 'I');
        fprintf(xnf, "END\n");
        break;

    default:
        fprintf(stderr, "fpga.tgt: unknown logic type %u\n",
                ivl_logic_type(net));
        break;
    }

}
Пример #11
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);
	    }
      }
}
Пример #12
0
/*
 * All logic gates have inputs and outputs that match exactly in
 * width. For example, and AND gate with 4 bit inputs generates a 4
 * bit output, and all the inputs are 4 bits.
 */
static void show_logic(ivl_net_logic_t net)
{
      unsigned npins, idx;
      const char*name = ivl_logic_basename(net);
      ivl_drive_t drive0 = ivl_logic_drive0(net);
      ivl_drive_t drive1 = ivl_logic_drive1(net);

      switch (ivl_logic_type(net)) {
	  case IVL_LO_AND:
	    fprintf(out, "  and %s", name);
	    break;
	  case IVL_LO_BUF:
	    fprintf(out, "  buf %s", name);
	    break;
	  case IVL_LO_BUFIF0:
	    fprintf(out, "  bufif0 %s", name);
	    break;
	  case IVL_LO_BUFIF1:
	    fprintf(out, "  bufif1 %s", name);
	    break;
	  case IVL_LO_BUFT:
	    fprintf(out, "  buft %s", name);
	    break;
	  case IVL_LO_BUFZ:
	    fprintf(out, "  bufz %s", name);
	    break;
	  case IVL_LO_CMOS:
	    fprintf(out, "  cmos %s", name);
	    break;
	  case IVL_LO_NAND:
	    fprintf(out, "  nand %s", name);
	    break;
	  case IVL_LO_NMOS:
	    fprintf(out, "  nmos %s", name);
	    break;
	  case IVL_LO_NOR:
	    fprintf(out, "  nor %s", name);
	    break;
	  case IVL_LO_NOT:
	    fprintf(out, "  not %s", name);
	    break;
	  case IVL_LO_NOTIF0:
	    fprintf(out, "  notif0 %s", name);
	    break;
	  case IVL_LO_NOTIF1:
	    fprintf(out, "  notif1 %s", name);
	    break;
	  case IVL_LO_OR:
	    fprintf(out, "  or %s", name);
	    break;
	  case IVL_LO_PMOS:
	    fprintf(out, "  pmos %s", name);
	    break;
	  case IVL_LO_PULLDOWN:
	    fprintf(out, "  pulldown %s", name);
	    break;
	  case IVL_LO_PULLUP:
	    fprintf(out, "  pullup %s", name);
	    break;
	  case IVL_LO_RCMOS:
	    fprintf(out, "  rcmos %s", name);
	    break;
	  case IVL_LO_RNMOS:
	    fprintf(out, "  rnmos %s", name);
	    break;
	  case IVL_LO_RPMOS:
	    fprintf(out, "  rpmos %s", name);
	    break;
	  case IVL_LO_XNOR:
	    fprintf(out, "  xnor %s", name);
	    break;
	  case IVL_LO_XOR:
	    fprintf(out, "  xor %s", name);
	    break;

	  case IVL_LO_UDP:
	    fprintf(out, "  primitive<%s> %s",
		    ivl_udp_name(ivl_logic_udp(net)), name);
	    break;

	  default:
	    fprintf(out, "  unsupported gate<type=%d> %s", ivl_logic_type(net), name);
	    break;
      }

      fprintf(out, " <width=%u>\n", ivl_logic_width(net));

      fprintf(out, "    <Delays...>\n");
      if (ivl_logic_delay(net,0)) {
	    test_expr_is_delay(ivl_logic_delay(net,0));
	    show_expression(ivl_logic_delay(net,0), 6);
      }
      if (ivl_logic_delay(net,1)) {
	    test_expr_is_delay(ivl_logic_delay(net,1));
	    show_expression(ivl_logic_delay(net,1), 6);
      }
      if (ivl_logic_delay(net,2)) {
	    test_expr_is_delay(ivl_logic_delay(net,2));
	    show_expression(ivl_logic_delay(net,2), 6);
      }

      npins = ivl_logic_pins(net);

	/* Show the pins of the gate. Pin-0 is always the output, and
	   the remaining pins are the inputs. Inputs may be
	   unconnected, but if connected the nexus width must exactly
	   match the gate width. */
      for (idx = 0 ;  idx < npins ;  idx += 1) {
	    ivl_nexus_t nex = ivl_logic_pin(net, idx);

	    fprintf(out, "    %d: %p", idx, nex);
	    if (idx == 0)
		  fprintf(out, " <drive0/1 = %u/%u>", drive0, drive1);
	    fprintf(out, "\n");

	    if (nex == 0) {
		  if (idx == 0) {
			fprintf(out, "    0: ERROR: Pin 0 must not "
				"be unconnected\n");
			stub_errors += 1;
		  }
		  continue;
	    }

	    if (ivl_logic_width(net) != width_of_nexus(nex)) {
		  fprintf(out, "    %d: ERROR: Nexus width is %u\n",
			  idx, width_of_nexus(nex));
		  stub_errors += 1;
	    }
      }

	/* If this is an instance of a UDP, then check that the
	   instantiation is consistent with the definition. */
      if (ivl_logic_type(net) == IVL_LO_UDP) {
	    ivl_udp_t udp = ivl_logic_udp(net);
	    if (npins != 1+ivl_udp_nin(udp)) {
		  fprintf(out, "    ERROR: UDP %s expects %u inputs\n",
			  ivl_udp_name(udp), ivl_udp_nin(udp));
		  stub_errors += 1;
	    }

	      /* Add a reference to this udp definition. */
	    reference_udp_definition(udp);
      }

      npins = ivl_logic_attr_cnt(net);
      for (idx = 0 ;  idx < npins ;  idx += 1) {
	    ivl_attribute_t cur = ivl_logic_attr_val(net,idx);
	    switch (cur->type) {
		case IVL_ATT_VOID:
		  fprintf(out, "    %s\n", cur->key);
		  break;
		case IVL_ATT_NUM:
		  fprintf(out, "    %s = %ld\n", cur->key, cur->val.num);
		  break;
		case IVL_ATT_STR:
		  fprintf(out, "    %s = %s\n", cur->key, cur->val.str);
		  break;
	    }
      }
}