Example #1
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 #2
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 #3
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 #4
0
File: group.c Project: nickg/nvc
static bool group_name(tree_t target, group_nets_ctx_t *ctx, int start, int n)
{
   switch (tree_kind(target)) {
   case T_REF:
      group_ref(target, ctx, start, n);
      return true;

   case T_ARRAY_REF:
      {
         tree_t value = tree_value(target);

         type_t type = tree_type(value);
         if (type_is_unconstrained(type))
            return false;

         int offset = 0;
         const int nparams = tree_params(target);
         for (int i = 0; i < nparams; i++) {
            tree_t index = tree_value(tree_param(target, i));
            const int stride = type_width(type_elem(type));

            if (tree_kind(index) != T_LITERAL) {
               if (i > 0)
                  return false;

               const int twidth = type_width(type);
               for (int j = 0; j < twidth; j += stride)
                  group_name(value, ctx, start + j, n);
               return true;
            }
            else {
               if (i > 0) {
                  range_t type_r = range_of(type, i);
                  int64_t low, high;
                  range_bounds(type_r, &low, &high);
                  offset *= high - low + 1;
               }

               offset += stride * rebase_index(type, i, assume_int(index));
            }
         }

         return group_name(value, ctx, start + offset, n);
      }

   case T_ARRAY_SLICE:
      {
         tree_t value = tree_value(target);
         type_t type  = tree_type(value);

         if (type_is_unconstrained(type))
            return false;    // Only in procedure

         range_t slice = tree_range(target, 0 );

         if (tree_kind(slice.left) != T_LITERAL
             || tree_kind(slice.right) != T_LITERAL)
            return false;

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

         const int64_t low0 = rebase_index(type, 0, assume_int(slice.left));
         const int stride   = type_width(type_elem(type));

         return group_name(value, ctx, start + low0 * stride, n);
      }

   case T_RECORD_REF:
      {
         tree_t value = tree_value(target);
         type_t rec = tree_type(value);
         const int offset = record_field_to_net(rec, tree_ident(target));

         return group_name(value, ctx, start + offset, n);
      }

   case T_AGGREGATE:
   case T_LITERAL:
      // This can appear due to assignments to open ports with a
      // default value
      return true;

   default:
      fatal_at(tree_loc(target), "tree kind %s not yet supported for offset "
               "calculation", tree_kind_str(tree_kind(target)));
   }
}
Example #5
0
File: shell.c Project: a4a881d4/nvc
static int shell_cmd_show(ClientData cd, Tcl_Interp *interp,
                          int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "show - Display simulation objects\n"
      "\n"
      "Usage: show LIST...\n"
      "\n"
      "Prints a representation of each simulation object in LIST. Typically\n"
      "this will be a list of signal names and the output will show their\n"
      "current value.\n"
      "\n"
      "Examples:\n"
      "  show {:top:foo}      Print value of signal :top_foo\n"
      "  show [signals]       Print value of all signals\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   if (objc == 1) {
      warnf("nothing to show (try -help for usage)");
      return TCL_OK;
   }

   hash_t *decl_hash = (hash_t *)cd;

   for (int i = 1; i < objc; i++) {
      int length;
      if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK)
         return TCL_ERROR;

      for (int j = 0; j < length; j++) {
         Tcl_Obj *obj;
         if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK)
            return TCL_ERROR;

         const char *str = Tcl_GetString(obj);

         tree_t t = hash_get(decl_hash, ident_new(str));
         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);

         tree_kind_t kind = tree_kind(t);
         switch (kind) {
         case T_SIGNAL_DECL:
            {
               size_t len = 1;
               type_t type = tree_type(t);
               while (type_is_array(type)) {
                  int64_t low = 0, high = 0;
                  range_bounds(type_dim(type, 0), &low, &high);
                  len *= (high - low + 1);

                  type = type_elem(type);
               }

               slave_read_signal_msg_t msg = {
                  .index = tree_index(t),
                  .len   = len
               };
               slave_post_msg(SLAVE_READ_SIGNAL, &msg, sizeof(msg));

               const size_t rsz =
                  sizeof(reply_read_signal_msg_t)
                  + (msg.len * sizeof(uint64_t));
               reply_read_signal_msg_t *reply = xmalloc(rsz);
               slave_get_reply(REPLY_READ_SIGNAL, reply, rsz);

               const char *type_str = type_pp(type);
               const char *short_name = strrchr(type_str, '.');

               printf("%-30s%-20s%s\n",
                      str,
                      (short_name != NULL ? short_name + 1 : type_str),
                      pprint(t, reply->values, msg.len));

               free(reply);
            }
            break;

         default:
            return tcl_error(interp, "cannot show tree kind %s",
                             tree_kind_str(kind));
         }
      }
   }

   return TCL_OK;
}