Esempio n. 1
0
static void find_arch(ident_t name, int kind, void *context)
{
   lib_search_params_t *params = context;

   ident_t prefix = ident_until(name, '-');

   if ((kind == T_ARCH) && (prefix == params->name)) {
      tree_t t = lib_get_check_stale(params->lib, name);
      assert(t != NULL);

      if (*(params->tree) == NULL)
         *(params->tree) = t;
      else {
         lib_mtime_t old_mtime = lib_mtime(params->lib,
                                           tree_ident(*(params->tree)));
         lib_mtime_t new_mtime = lib_mtime(params->lib, tree_ident(t));

         if (new_mtime == old_mtime) {
            // Analysed at the same time: compare line number
            // Note this assumes both architectures are from the same
            // file but this shouldn't be a problem with high-resolution
            // timestamps
            uint16_t new_line = tree_loc(t)->first_line;
            uint16_t old_line = tree_loc(*(params->tree))->first_line;

            if (new_line > old_line)
               *(params->tree) = t;
         }
         else if (new_mtime > old_mtime)
            *(params->tree) = t;
      }
   }
}
Esempio n. 2
0
static tree_t elab_port_to_signal(tree_t arch, tree_t port, tree_t actual)
{
   assert(tree_kind(port) == T_PORT_DECL);

   ident_t name = tree_ident(port);

   const int ndecls = tree_decls(arch);
   for (int i = 0; i < ndecls; i++) {
      tree_t d = tree_decl(arch, i);
      if (tree_ident(d) == name)
         return d;
   }

   type_t port_type   = tree_type(port);
   type_t actual_type = tree_type(actual);

   type_t type = (type_is_unconstrained(port_type)) ? actual_type : port_type;

   port_mode_t mode = tree_subkind(port);

   tree_t s = tree_new(T_SIGNAL_DECL);
   tree_set_ident(s, tree_ident(port));
   tree_set_type(s, type);
   tree_add_attr_int(s, fst_dir_i, mode);
   tree_set_loc(s, tree_loc(port));
   tree_set_flag(s, tree_flags(port) & TREE_F_LAST_VALUE);

   if ((mode == PORT_OUT) || (mode == PORT_INOUT) || (mode == PORT_BUFFER)) {
      if (tree_has_value(port))
         tree_add_attr_tree(s, driver_init_i, tree_value(port));
   }

   tree_add_decl(arch, s);
   return s;
}
Esempio n. 3
0
static void elab_add_context(tree_t t, const elab_ctx_t *ctx)
{
   ident_t cname = tree_ident(t);
   ident_t lname = ident_until(cname, '.');

   lib_t lib = elab_find_lib(lname, ctx);

   tree_t unit = lib_get(lib, cname);
   if (unit == NULL)
      fatal_at(tree_loc(t), "cannot find unit %s", istr(cname));
   else if (tree_kind(unit) == T_PACKAGE) {
      elab_copy_context(unit, ctx);

      ident_t name = tree_ident(unit);

      ident_t body_i = ident_prefix(name, ident_new("body"), '-');
      tree_t body = lib_get(lib, body_i);
      if (body != NULL)
         elab_copy_context(unit, ctx);
   }

   // Always use real library name rather than WORK alias
   tree_set_ident(t, tree_ident(unit));

   tree_add_context(ctx->out, t);
}
Esempio n. 4
0
static tree_t get_bool_lit(tree_t t, bool v)
{
   tree_t fdecl = tree_ref(t);
   assert(tree_kind(fdecl) == T_FUNC_DECL);

   static type_t bool_type = NULL;
   if (bool_type == NULL) {
      lib_t std = lib_find("std", true, true);
      assert(std != NULL);

      tree_t standard = lib_get(std, ident_new("STD.STANDARD"));
      assert(standard != NULL);

      const int ndecls = tree_decls(standard);
      for (int i = 0; (i < ndecls) && (bool_type == NULL); i++) {
         tree_t d = tree_decl(standard, i);
         if (tree_ident(d) == std_bool_i)
            bool_type = tree_type(d);
      }
      assert(bool_type != NULL);
   }

   tree_t lit = type_enum_literal(bool_type, v ? 1 : 0);

   tree_t b = tree_new(T_REF);
   tree_set_loc(b, tree_loc(t));
   tree_set_ref(b, lit);
   tree_set_type(b, bool_type);
   tree_set_ident(b, tree_ident(lit));

   return b;
}
Esempio n. 5
0
tree_t get_real_lit(tree_t t, double r)
{
   tree_t f = tree_new(T_LITERAL);
   tree_set_loc(f, tree_loc(t));
   tree_set_subkind(f, L_REAL);
   tree_set_dval(f, r);
   tree_set_type(f, tree_type(t));

   return f;
}
Esempio n. 6
0
tree_t get_int_lit(tree_t t, int64_t i)
{
   tree_t f = tree_new(T_LITERAL);
   tree_set_subkind(f, L_INT);
   tree_set_ival(f, i);
   tree_set_loc(f, tree_loc(t));
   tree_set_type(f, tree_type(t));

   return f;
}
Esempio n. 7
0
tree_t get_bool_lit(tree_t t, bool v)
{
   type_t bool_type = tree_type(t);
   tree_t lit = type_enum_literal(bool_type, v ? 1 : 0);

   tree_t b = tree_new(T_REF);
   tree_set_loc(b, tree_loc(t));
   tree_set_ref(b, lit);
   tree_set_type(b, bool_type);
   tree_set_ident(b, tree_ident(lit));

   return b;
}
Esempio n. 8
0
File: fst.c Progetto: SnookEE/nvc
static void fst_process_hier(tree_t h)
{
   const tree_kind_t scope_kind = tree_subkind(h);

   enum fstScopeType st;
   switch (scope_kind) {
   case T_ARCH: st = FST_ST_VHDL_ARCHITECTURE; break;
   case T_BLOCK: st = FST_ST_VHDL_BLOCK; break;
   case T_FOR_GENERATE: st = FST_ST_VHDL_FOR_GENERATE; break;
   case T_PACKAGE: st = FST_ST_VHDL_PACKAGE; break;
   default:
      st = FST_ST_VHDL_ARCHITECTURE;
      warn_at(tree_loc(h), "no FST scope type for %s",
              tree_kind_str(scope_kind));
      break;
   }

   const loc_t *loc = tree_loc(h);
   fstWriterSetSourceStem(fst_ctx, loc->file, loc->first_line, 1);

   fstWriterSetScope(fst_ctx, st, istr(tree_ident(h)),
                     tree_has_ident2(h) ? istr(tree_ident2(h)) : "");
}
Esempio n. 9
0
tree_t add_param(tree_t call, tree_t value, param_kind_t kind, tree_t name)
{
   tree_t p = tree_new(T_PARAM);
   tree_set_loc(p, tree_loc(value));
   tree_set_subkind(p, kind);
   tree_set_value(p, value);

   if (kind == P_NAMED) {
      assert(name != NULL);
      tree_set_name(p, name);
   }

   tree_add_param(call, p);
   return p;
}
Esempio n. 10
0
static tree_t rewrite_refs(tree_t t, void *context)
{
   rewrite_params_t *params = context;

   if (tree_kind(t) != T_REF)
      return t;

   tree_t decl = tree_ref(t);

   for (int i = 0; i < params->count; i++) {
      if (decl != params->formals[i])
         continue;

      // Do not rewrite references if they appear as formal names
      if (tree_attr_int(t, formal_i, 0))
         continue;

      // Skip assignments to OPEN ports
      if (params->actuals[i] == NULL)
         continue;

      switch (tree_kind(params->actuals[i])) {
      case T_SIGNAL_DECL:
      case T_ENUM_LIT:
         tree_set_ref(t, params->actuals[i]);
         tree_set_type(t, tree_type(params->actuals[i]));
         return t;
      case T_LITERAL:
      case T_AGGREGATE:
      case T_REF:
      case T_ARRAY_SLICE:
      case T_ARRAY_REF:
      case T_FCALL:
      case T_CONCAT:
         return params->actuals[i];
      case T_TYPE_CONV:
         // XXX: this only works in trivial cases
         return tree_value(tree_param(params->actuals[i], 0));
      default:
         fatal_at(tree_loc(params->actuals[i]), "cannot handle tree kind %s "
                  "in rewrite_refs",
                  tree_kind_str(tree_kind(params->actuals[i])));
      }
   }

   return t;
}
Esempio n. 11
0
static ident_t elab_formal_name(tree_t t)
{
   tree_kind_t kind;
   while ((kind = tree_kind(t)) != T_REF) {
      switch (kind) {
      case T_ARRAY_REF:
      case T_ARRAY_SLICE:
         t = tree_value(t);
         break;

      default:
         fatal_at(tree_loc(t), "sorry, this kind of formal is not supported %s",
                  tree_kind_str(kind));
      }
   }

   return tree_ident(t);
}
Esempio n. 12
0
File: cover.c Progetto: a4a881d4/nvc
static void cover_report_stmts_fn(tree_t t, void *context)
{
   const int32_t *counts = context;

   const int tag = tree_attr_int(t, stmt_tag_i, -1);
   if (tag == -1)
      return;

   const loc_t *loc = tree_loc(t);
   cover_file_t *file = cover_file(loc);
   if (file == NULL)
      return;

   assert(loc->first_line < file->n_lines);

   cover_line_t *l = &(file->lines[loc->first_line - 1]);
   l->hits = MAX(counts[tag], l->hits);
}
Esempio n. 13
0
int64_t assume_int(tree_t t)
{
   switch (tree_kind(t)) {
   case T_LITERAL:
      assert(tree_subkind(t) == L_INT);
      return tree_ival(t);

   case T_REF:
      {
         tree_t ref = tree_ref(t);
         assert(tree_kind(ref) == T_ENUM_LIT);
         return tree_pos(ref);
      }

   default:
      fatal_at(tree_loc(t), "expression cannot be folded to "
               "an integer constant");
   }
}
Esempio n. 14
0
File: group.c Progetto: nickg/nvc
static void group_target(tree_t t, group_nets_ctx_t *ctx)
{
   switch (tree_kind(t)) {
   case T_REF:
      group_ref(t, ctx, 0, -1);
      break;

   case T_ARRAY_REF:
   case T_ARRAY_SLICE:
   case T_RECORD_REF:
      {
         type_t type = tree_type(t);
         if (!type_known_width(type))
            ungroup_name(t, ctx);
         else if (!group_name(t, ctx, 0, type_width(type)))
            ungroup_name(t, ctx);
      }
      break;

   case T_LITERAL:
   case T_OPEN:
      // Constant folding can cause this to appear
      break;

   case T_AGGREGATE:
      {
         const int nassocs = tree_assocs(t);
         for (int i = 0; i < nassocs; i++)
            group_target(tree_value(tree_assoc(t, i)), ctx);
      }
      break;

   default:
      fmt_loc(stdout, tree_loc(t));
      fatal_trace("Cannot handle tree kind %s in group_target",
                  tree_kind_str(tree_kind(t)));
   }
}
Esempio n. 15
0
File: fst.c Progetto: 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);
}
Esempio n. 16
0
File: group.c Progetto: 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)));
   }
}
Esempio n. 17
0
static tree_t elab_signal_port(tree_t arch, tree_t formal, tree_t param,
                               map_list_t **maps)
{
   assert(tree_kind(param) == T_PARAM);

   tree_t actual = tree_value(param);

   // NULL name means associate the whole port
   tree_t name = NULL;
   if (tree_subkind(param) == P_NAMED) {
      tree_t n = tree_name(param);
      if (tree_kind(n) != T_REF)
         name = n;
   }

   const bool partial_map = name != NULL;

   switch (tree_kind(actual)) {
   case T_REF:
   case T_ARRAY_REF:
   case T_ARRAY_SLICE:
   case T_RECORD_REF:
      {
         // Replace the formal port with a signal and connect its nets to
         // those of the actual

         tree_t ref = actual;
         tree_kind_t ref_kind;
         while ((ref_kind = tree_kind(ref)) != T_REF) {
            if ((ref_kind == T_AGGREGATE) || (ref_kind == T_LITERAL))
               return actual;
            else
               ref = tree_value(ref);
         }

         tree_t decl = tree_ref(ref);
         tree_kind_t decl_kind = tree_kind(decl);
         if (decl_kind == T_SIGNAL_DECL) {
            tree_t s = elab_port_to_signal(arch, formal, actual);

            if (partial_map)
               tree_add_attr_int(s, partial_map_i, 1);

            map_list_t *m = xmalloc(sizeof(map_list_t));
            m->next   = *maps;
            m->formal = formal;
            m->actual = actual;
            m->signal = s;
            m->name   = name;

            *maps = m;

            return s;
         }
         else if (decl_kind == T_PORT_DECL)
            return NULL;    // Port was OPEN at a higher level
         else
            return actual;
      }

   case T_LITERAL:
   case T_AGGREGATE:
      {
         type_t formal_type = tree_type(formal);
         if (!type_is_unconstrained(formal_type))
            tree_set_type(actual, formal_type);
         return actual;
      }

   case T_OPEN:
      return NULL;

   case T_TYPE_CONV:
      // Only allow simple array type conversions for now
      {
         type_t to_type   = tree_type(actual);
         type_t from_type = tree_type(tree_value(tree_param(actual, 0)));

         if (type_is_array(to_type) && type_is_array(from_type))
            return actual;
         else
            fatal_at(tree_loc(actual), "sorry, this form of type conversion "
                     "is not supported as an actual");
      }

   default:
      fatal_at(tree_loc(actual), "tree %s not supported as actual",
               tree_kind_str(tree_kind(actual)));
   }
}
Esempio n. 18
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__);
   }
}
Esempio n. 19
0
File: lxt.c Progetto: 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;
}
Esempio n. 20
0
tree_t call_builtin(const char *builtin, type_t type, ...)
{
   struct decl_cache {
      struct decl_cache *next;
      ident_t bname;
      tree_t  decl;
   };

   char *name = xasprintf("NVC.BUILTIN.%s", builtin);
   for (char *p = name; *p != '\0'; p++)
      *p = toupper((int)*p);

   static struct decl_cache *cache = NULL;

   ident_t bname = ident_new(builtin);
   ident_t name_i = ident_new(name);
   free(name);

   struct decl_cache *it;
   tree_t decl = NULL;
   for (it = cache; it != NULL; it = it->next) {
      if (it->bname == bname) {
         decl = it->decl;
         break;
      }
   }

   if (decl == NULL) {
      decl = tree_new(T_FUNC_DECL);
      tree_set_ident(decl, name_i);
      tree_add_attr_str(decl, builtin_i, ident_new(builtin));
   }

   struct decl_cache *c = xmalloc(sizeof(struct decl_cache));
   c->next  = cache;
   c->bname = bname;
   c->decl  = decl;

   cache = c;

   tree_t call = tree_new(T_FCALL);
   tree_set_ident(call, name_i);
   tree_set_ref(call, decl);
   if (type != NULL)
      tree_set_type(call, type);

   va_list ap;
   va_start(ap, type);
   tree_t arg;
   while ((arg = va_arg(ap, tree_t))) {
      tree_t p = tree_new(T_PARAM);
      tree_set_value(p, arg);
      tree_set_loc(p, tree_loc(arg));
      tree_set_subkind(p, P_POS);

      tree_add_param(call, p);
   }
   va_end(ap);

   return call;
}
Esempio n. 21
0
File: vcd.c Progetto: 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);
}
Esempio n. 22
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);
   }
}