Example #1
0
type_t array_aggregate_type(type_t array, int from_dim)
{
   if (type_is_unconstrained(array)) {
      const int nindex = type_index_constrs(array);
      assert(from_dim < nindex);

      type_t type = type_new(T_UARRAY);
      type_set_ident(type, type_ident(array));
      type_set_elem(type, type_elem(array));

      for (int i = from_dim; i < nindex; i++)
         type_add_index_constr(type, type_index_constr(array, i));

      return type;
   }
   else {
      const int ndims = type_dims(array);
      assert(from_dim < ndims);

      type_t type = type_new(T_CARRAY);
      type_set_ident(type, type_ident(array));
      type_set_elem(type, type_elem(array));

      for (int i = from_dim; i < ndims; i++)
         type_add_dim(type, type_dim(array, i));

      return type;
   }
}
Example #2
0
bool type_is_unconstrained(type_t t)
{
   assert(t != NULL);
   if (t->kind == T_SUBTYPE) {
      if (type_dims(t) == 0)
         return type_is_unconstrained(type_base(t));
      else
         return false;
   }
   else
      return (t->kind == T_UARRAY);
}
Example #3
0
void type_replace(type_t t, type_t a)
{
   assert(t != NULL);
   assert(IS(t, T_INCOMPLETE));

   t->kind  = a->kind;
   t->ident = a->ident;

   const imask_t has = has_map[t->kind];

   if (has & I_DIMS) {
      const int ndims = type_dims(a);
      for (int i = 0; i < ndims; i++)
         type_add_dim(t, type_dim(a, i));
   }

   switch (a->kind) {
   case T_UARRAY:
      for (unsigned i = 0; i < type_index_constrs(a); i++)
         type_add_index_constr(t, type_index_constr(a, i));

      // Fall-through
   case T_CARRAY:
      type_set_elem(t, type_elem(a));
      break;

   case T_SUBTYPE:
      type_set_base(t, type_base(a));
      break;

   case T_FUNC:
      type_set_result(t, type_result(a));
      break;

   case T_INTEGER:
   case T_REAL:
      break;

   case T_ENUM:
      for (unsigned i = 0; i < type_enum_literals(a); i++)
         type_enum_add_literal(t, type_enum_literal(a, i));
      break;

   case T_RECORD:
      for (unsigned i = 0; i < type_fields(a); i++)
         type_add_field(t, type_field(a, i));
      break;

   default:
      assert(false);
   }
}
Example #4
0
unsigned type_width(type_t type)
{
   if (type_is_array(type)) {
      const unsigned elem_w = type_width(type_elem(type));
      unsigned w = 1;
      const int ndims = type_dims(type);
      for (int i = 0; i < ndims; i++) {
         int64_t low, high;
         range_bounds(type_dim(type, i), &low, &high);
         w *= MAX(high - low + 1, 0) * elem_w;
      }
      return w;
   }
   else if (type_is_record(type)) {
      type_t base = type_base_recur(type);
      unsigned w = 0;
      const int nfields = type_fields(base);
      for (int i = 0; i < nfields; i++)
         w += type_width(tree_type(type_field(base, i)));
      return w;
   }
   else
      return 1;
}
Example #5
0
File: vcd.c Project: SnookEE/nvc
static void vcd_process_signal(tree_t d, int *next_key)
{
   type_t type = tree_type(d);
   type_t base = type_base_recur(type);

   vcd_data_t *data = xmalloc(sizeof(vcd_data_t));
   memset(data, '\0', sizeof(vcd_data_t));

   int msb = 0, lsb = 0;

   if (type_is_array(type)) {
      if (type_dims(type) > 1) {
         warn_at(tree_loc(d), "cannot represent multidimensional arrays "
                 "in VCD format");
         free(data);
         return;
      }

      range_t r = type_dim(type, 0);

      int64_t low, high;
      range_bounds(r, &low, &high);

      data->dir  = r.kind;
      data->size = high - low + 1;

      msb = assume_int(r.left);
      lsb = assume_int(r.right);

      type_t elem = type_elem(type);
      if (!vcd_can_fmt_chars(elem, data)) {
         warn_at(tree_loc(d), "cannot represent arrays of type %s "
                 "in VCD format", type_pp(elem));
         free(data);
         return;
      }
   }
   else {
      switch (type_kind(base)) {
      case T_INTEGER:
         {
            int64_t low, high;
            range_bounds(type_dim(type, 0), &low, &high);

            data->size = ilog2(high - low + 1);
            data->fmt  = vcd_fmt_int;
         }
         break;

      case T_ENUM:
         if (vcd_can_fmt_chars(type, data)) {
            data->size = 1;
            break;
         }
         // Fall-through

      default:
         warn_at(tree_loc(d), "cannot represent type %s in VCD format",
                 type_pp(type));
         free(data);
         return;
      }
   }

   const char *name_base = strrchr(istr(tree_ident(d)), ':') + 1;
   const size_t base_len = strlen(name_base);
   char name[base_len + 64];
   strncpy(name, name_base, base_len + 64);
   if (type_is_array(type))
      snprintf(name + base_len, 64, "[%d:%d]\n", msb, lsb);

   tree_add_attr_ptr(d, vcd_data_i, data);

   data->watch = rt_set_event_cb(d, vcd_event_cb, data, true);

   vcd_key_fmt(*next_key, data->key);

   fprintf(vcd_file, "$var reg %d %s %s $end\n",
           (int)data->size, data->key, name);

   ++(*next_key);
}
Example #6
0
File: lxt.c Project: SnookEE/nvc
void lxt_restart(void)
{
   if (trace == NULL)
      return;

   lt_set_timescale(trace, -15);
   lt_symbol_bracket_stripping(trace, 0);
   lt_set_clock_compress(trace);

   const int ndecls = tree_decls(lxt_top);
   for (int i = 0; i < ndecls; i++) {
      tree_t d = tree_decl(lxt_top, i);
      if (tree_kind(d) != T_SIGNAL_DECL)
         continue;
      else if (!wave_should_dump(d))
         continue;

      type_t type = tree_type(d);

      int rows, msb, lsb;
      if (type_is_array(type)) {
         rows = type_dims(type) - 1;
         if ((rows > 0) || type_is_array(type_elem(type))) {
            warn_at(tree_loc(d), "cannot emit arrays of greater than one "
                    "dimension or arrays of arrays in LXT yet");
            continue;
         }

         range_t r = type_dim(type, 0);
         msb = assume_int(r.left);
         lsb = assume_int(r.right);
      }
      else {
         rows = 0;
         msb = lsb = -1;
      }

      lxt_data_t *data = xmalloc(sizeof(lxt_data_t));
      memset(data, '\0', sizeof(lxt_data_t));

      int flags = 0;

      if (type_is_array(type)) {
         // Only arrays of CHARACTER, BIT, STD_ULOGIC are supported
         type_t elem = type_base_recur(type_elem(type));
         if ((type_kind(elem) != T_ENUM)
             || !lxt_can_fmt_enum_chars(elem, data, &flags)) {
            warn_at(tree_loc(d), "cannot represent arrays of type %s "
                    "in LXT format", type_pp(elem));
            free(data);
            continue;
         }

         data->dir = type_dim(type, 0).kind;
      }
      else {
         type_t base = type_base_recur(type);
         switch (type_kind(base)) {
         case T_INTEGER:
            data->fmt = lxt_fmt_int;
            flags = LT_SYM_F_INTEGER;
            break;

         case T_ENUM:
            if (!lxt_can_fmt_enum_chars(base, data, &flags)) {
               data->fmt = lxt_fmt_enum;
               flags = LT_SYM_F_STRING;
            }
            break;

         default:
            warn_at(tree_loc(d), "cannot represent type %s in LXT format",
                    type_pp(type));
            free(data);
            continue;
         }
      }

      char *name = lxt_fmt_name(d);
      data->sym = lt_symbol_add(trace, name, rows, msb, lsb, flags);
      free(name);

      tree_add_attr_ptr(d, lxt_data_i, data);

      watch_t *w = rt_set_event_cb(d, lxt_event_cb, data, true);

      (*data->fmt)(d, w, data);
   }

   last_time = (lxttime_t)-1;
}
Example #7
0
File: fst.c Project: SnookEE/nvc
static void fst_process_signal(tree_t d)
{
   type_t type = tree_type(d);
   type_t base = type_base_recur(type);

   fst_data_t *data = xmalloc(sizeof(fst_data_t));
   memset(data, '\0', sizeof(fst_data_t));

   int msb = 0, lsb = 0;

   enum fstVarType vt;
   enum fstSupplementalDataType sdt;
   if (type_is_array(type)) {
      if (type_dims(type) > 1) {
         warn_at(tree_loc(d), "cannot represent multidimensional arrays "
                 "in FST format");
         free(data);
         return;
      }

      range_t r = type_dim(type, 0);

      int64_t low, high;
      range_bounds(r, &low, &high);

      data->dir  = r.kind;
      data->size = high - low + 1;

      msb = assume_int(r.left);
      lsb = assume_int(r.right);

      type_t elem = type_elem(type);
      if (!fst_can_fmt_chars(elem, data, &vt, &sdt)) {
         warn_at(tree_loc(d), "cannot represent arrays of type %s "
                 "in FST format", type_pp(elem));
         free(data);
         return;
      }
      else {
         ident_t ident = type_ident(base);
         if (ident == unsigned_i)
            sdt = FST_SDT_VHDL_UNSIGNED;
         else if (ident == signed_i)
            sdt = FST_SDT_VHDL_SIGNED;
      }
   }
   else {
      switch (type_kind(base)) {
      case T_INTEGER:
         {
            ident_t ident = type_ident(type);
            if (ident == natural_i)
               sdt = FST_SDT_VHDL_NATURAL;
            else if (ident == positive_i)
               sdt = FST_SDT_VHDL_POSITIVE;
            else
               sdt = FST_SDT_VHDL_INTEGER;

            int64_t low, high;
            range_bounds(type_dim(type, 0), &low, &high);

            vt = FST_VT_VCD_INTEGER;
            data->size = ilog2(high - low + 1);
            data->fmt  = fst_fmt_int;
         }
         break;

      case T_ENUM:
         if (!fst_can_fmt_chars(type, data, &vt, &sdt)) {
            ident_t ident = type_ident(base);
            if (ident == std_bool_i)
               sdt = FST_SDT_VHDL_BOOLEAN;
            else if (ident == std_char_i)
               sdt = FST_SDT_VHDL_CHARACTER;
            else
               sdt = FST_SDT_NONE;

            vt = FST_VT_GEN_STRING;
            data->size = 0;
            data->fmt  = fst_fmt_enum;
         }
         else
            data->size = 1;
         break;

      case T_PHYSICAL:
         {
            sdt = FST_SDT_NONE;
            vt  = FST_VT_GEN_STRING;
            data->size = 0;
            data->type.units = fst_make_unit_map(type);
            data->fmt = fst_fmt_physical;
         }
         break;

      default:
         warn_at(tree_loc(d), "cannot represent type %s in FST format",
                 type_pp(type));
         free(data);
         return;
      }
   }

   enum fstVarDir dir = FST_VD_IMPLICIT;

   switch (tree_attr_int(d, fst_dir_i, -1)) {
   case PORT_IN: dir = FST_VD_INPUT; break;
   case PORT_OUT: dir = FST_VD_OUTPUT; break;
   case PORT_INOUT: dir = FST_VD_INOUT; break;
   case PORT_BUFFER: dir = FST_VD_BUFFER; break;
   }

   const char *name_base = strrchr(istr(tree_ident(d)), ':') + 1;
   const size_t base_len = strlen(name_base);
   char name[base_len + 64];
   strncpy(name, name_base, base_len + 64);
   if (type_is_array(type))
      snprintf(name + base_len, 64, "[%d:%d]\n", msb, lsb);

   data->handle = fstWriterCreateVar2(
      fst_ctx,
      vt,
      dir,
      data->size,
      name,
      0,
      type_pp(type),
      FST_SVT_VHDL_SIGNAL,
      sdt);

   tree_add_attr_ptr(d, fst_data_i, data);

   data->watch = rt_set_event_cb(d, fst_event_cb, data, true);
}
Example #8
0
unsigned array_dimension(type_t a)
{
   return (type_is_unconstrained(a)
           ? type_index_constrs(type_base_recur(a))
           : type_dims(a));
}
Example #9
0
tree_t make_default_value(type_t type, const loc_t *loc)
{
   type_t base = type_base_recur(type);

   switch (type_kind(base)) {
   case T_UARRAY:
      assert(type_kind(type) == T_SUBTYPE);
      // Fall-through

   case T_CARRAY:
      {
         tree_t def = NULL;
         const int ndims = type_dims(type);
         for (int i = ndims - 1; i >= 0; i--) {
            tree_t val = (def ? def : make_default_value(type_elem(base), loc));
            def = tree_new(T_AGGREGATE);
            tree_set_type(def, array_aggregate_type(type, i));

            tree_t a = tree_new(T_ASSOC);
            tree_set_subkind(a, A_OTHERS);
            tree_set_value(a, val);

            tree_add_assoc(def, a);
         }
         tree_set_type(def, type);
         tree_set_loc(def, loc);
         return def;
      }

   case T_INTEGER:
   case T_PHYSICAL:
   case T_REAL:
      return type_dim(type, 0).left;

   case T_ENUM:
      {
         int64_t val = 0;
         const bool folded = folded_int(type_dim(type, 0).left, &val);
         if (folded)
            return make_ref(type_enum_literal(base, (unsigned) val));
         else
            return type_dim(type, 0).left;
      }

   case T_RECORD:
      {
         tree_t def = tree_new(T_AGGREGATE);
         tree_set_loc(def, loc);
         const int nfields = type_fields(base);
         for (int i = 0; i < nfields; i++) {
            tree_t field = type_field(base, i);

            tree_t a = tree_new(T_ASSOC);
            tree_set_subkind(a, A_POS);
            tree_set_value(a, make_default_value(tree_type(field),
                                                 tree_loc(field)));

            tree_add_assoc(def, a);
         }
         tree_set_type(def, type);
         return def;
      }

   case T_ACCESS:
      {
         tree_t null = tree_new(T_LITERAL);
         tree_set_loc(null, loc);
         tree_set_subkind(null, L_NULL);
         tree_set_type(null, type);
         return null;
      }

   case T_UNRESOLVED:
      return NULL;

   default:
      fatal_trace("cannot handle type %s in %s",
                  type_kind_str(type_kind(base)), __func__);
   }
}
Example #10
0
bool type_eq(type_t a, type_t b)
{
   assert(a != NULL);
   assert(b != NULL);

   type_kind_t kind_a = type_kind(a);
   type_kind_t kind_b = type_kind(b);

   if ((kind_a == T_UNRESOLVED) || (kind_b == T_UNRESOLVED))
      return false;

   if (a == b)
      return true;

   // Subtypes are convertible to the base type
   while ((kind_a = type_kind(a)) == T_SUBTYPE)
      a = type_base(a);
   while ((kind_b = type_kind(b)) == T_SUBTYPE)
      b = type_base(b);

   const bool compare_c_u_arrays =
      (kind_a == T_CARRAY && kind_b == T_UARRAY)
      || (kind_a == T_UARRAY && kind_b == T_CARRAY);

   if ((kind_a != kind_b) && !compare_c_u_arrays)
      return false;

   // Universal integer type is equal to any other integer type
   type_t universal_int = type_universal_int();
   ident_t uint_i = type_ident(universal_int);
   if (kind_a == T_INTEGER
       && (type_ident(a) == uint_i || type_ident(b) == uint_i))
      return true;

   // Universal real type is equal to any other real type
   type_t universal_real = type_universal_real();
   ident_t ureal_i = type_ident(universal_real);
   if (kind_a == T_REAL
       && (type_ident(a) == ureal_i || type_ident(b) == ureal_i))
      return true;

   // XXX: this is not quite right as structurally equivalent types
   // may be declared in different scopes with the same name but
   // shouldn't compare equal

   if (type_ident(a) != type_ident(b))
      return false;

   // Access types are equal if the pointed to type is the same
   if (kind_a == T_ACCESS)
      return type_eq(type_access(a), type_access(b));

   if (compare_c_u_arrays)
      return type_eq(type_elem(a), type_elem(b));

   const imask_t has = has_map[a->kind];

   if ((has & I_DIMS) && (type_dims(a) != type_dims(b)))
      return false;

   if (type_kind(a) == T_FUNC) {
      if (!type_eq(type_result(a), type_result(b)))
         return false;
   }

   if (has & I_PARAMS) {
      if (type_params(a) != type_params(b))
         return false;

      const int nparams = type_params(a);
      for (int i = 0; i < nparams; i++) {
         if (!type_eq(type_param(a, i), type_param(b, i)))
             return false;
      }
   }

   return true;
}
Example #11
0
tree_t make_default_value(type_t type, const loc_t *loc)
{
   type_t base = type_base_recur(type);

   switch (type_kind(base)) {
   case T_UARRAY:
      assert(type_kind(type) == T_SUBTYPE);
      // Fall-through

   case T_CARRAY:
      {
         tree_t def = NULL;
         const int ndims = type_dims(type);
         for (int i = ndims - 1; i >= 0; i--) {
            tree_t val = (def ? def : make_default_value(type_elem(base), loc));
            def = tree_new(T_AGGREGATE);
            tree_set_type(def, array_aggregate_type(type, i));

            tree_t a = tree_new(T_ASSOC);
            tree_set_subkind(a, A_OTHERS);
            tree_set_value(a, val);

            tree_add_assoc(def, a);
         }
         tree_set_type(def, type);
         tree_set_loc(def, loc);
         return def;
      }

   case T_INTEGER:
   case T_PHYSICAL:
   case T_REAL:
      return type_dim(type, 0).left;

   case T_ENUM:
      return make_ref(type_enum_literal(base, 0));

   case T_RECORD:
      {
         tree_t def = tree_new(T_AGGREGATE);
         tree_set_loc(def, loc);
         const int nfields = type_fields(base);
         for (int i = 0; i < nfields; i++) {
            tree_t field = type_field(base, i);

            tree_t a = tree_new(T_ASSOC);
            tree_set_subkind(a, A_POS);
            tree_set_value(a, make_default_value(tree_type(field),
                                                 tree_loc(field)));

            tree_add_assoc(def, a);
         }
         tree_set_type(def, type);
         return def;
      }

   case T_ACCESS:
      {
         tree_t null = tree_new(T_LITERAL);
         tree_set_loc(null, loc);
         tree_set_subkind(null, L_NULL);
         tree_set_type(null, type);
         return null;
      }

   default:
      assert(false);
   }
}