Exemple #1
0
Fichier : opt.c Projet : chiggs/nvc
static void opt_elide_array_ref_bounds(tree_t t)
{
   tree_t value = tree_value(t);
   if (tree_kind(value) != T_REF)
      return;

   tree_t decl = tree_ref(value);

   const int nparams = tree_params(t);
   for (int i = 0; i < nparams; i++) {
      tree_t index = tree_value(tree_param(t, i));
      if (tree_kind(index) != T_REF)
         return;

      tree_t index_decl = tree_ref(index);

      tree_t range_var = tree_attr_tree(index_decl, range_var_i);
      if (range_var == NULL)
         return;

      if (range_var != decl)
         return;
   }

   tree_add_attr_int(t, elide_bounds_i, 1);
}
Exemple #2
0
Fichier : opt.c Projet : chiggs/nvc
static void opt_tag_last_value_fcall(tree_t t)
{
   tree_t decl = tree_ref(t);

   if (tree_attr_str(decl, builtin_i) != NULL)
      return;

   // A regular subprogram call may pass parameters as class signal which
   // could access 'LAST_VALUE in the body

   const int nports = tree_ports(decl);
   for (int i = 0; i < nports; i++) {
      tree_t port = tree_port(decl, i);
      if (tree_class(port) != C_SIGNAL)
         continue;

      tree_t value = tree_value(tree_param(t, i));
      tree_kind_t kind;
      while ((kind = tree_kind(value)) != T_REF) {
         assert((kind == T_ARRAY_REF) || (kind == T_ARRAY_SLICE));
         value = tree_value(value);
      }

      tree_add_attr_int(tree_ref(value), last_value_i, 1);
   }
}
Exemple #3
0
static tree_t fixup_entity_refs(tree_t t, void *context)
{
   // Rewrite references to an entity to point at the selected architecture
   // so attributes like 'PATH_NAME are correct

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

   tree_t arch = context;

   if (tree_ref(t) == tree_ref(arch))
      tree_set_ref(t, arch);

   return t;
}
Exemple #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;
}
Exemple #5
0
static void ungroup_proc_params(tree_t t, group_nets_ctx_t *ctx)
{
   // Ungroup any signal that is passed to a procedure as in general we
   // cannot guarantee anything about the procedure's behaviour

   const int nparams = tree_params(t);
   for (int i = 0; i < nparams; i++) {
      tree_t value = tree_value(tree_param(t, i));

      tree_kind_t kind = tree_kind(value);
      while (kind == T_ARRAY_REF || kind == T_ARRAY_SLICE) {
         value = tree_value(value);
         kind = tree_kind(value);
      }

      if (kind != T_REF)
         continue;

      tree_t decl = tree_ref(value);

      if (tree_kind(decl) != T_SIGNAL_DECL)
         continue;

      const int nnets = tree_nets(decl);
      for (int i = 0; i < nnets; i++)
         group_add(ctx, tree_net(decl, i), 1);
   }
}
Exemple #6
0
static void ungroup_ref(tree_t target, group_nets_ctx_t *ctx)
{
   tree_t decl = tree_ref(target);
   if (tree_kind(decl) == T_SIGNAL_DECL) {
      const int nnets = tree_nets(decl);
      for (int i = 0; i < nnets; i++)
         group_add(ctx, tree_net(decl, i), 1);
   }
}
Exemple #7
0
class_t class_of(tree_t t)
{
   switch (tree_kind(t)) {
   case T_VAR_DECL:
      return C_VARIABLE;
   case T_SIGNAL_DECL:
      return C_SIGNAL;
   case T_CONST_DECL:
      return C_CONSTANT;
   case T_PORT_DECL:
      return tree_class(t);
   case T_ENUM_LIT:
   case T_GENVAR:
   case T_ALIAS:
   case T_FIELD_DECL:
      return C_DEFAULT;
   case T_UNIT_DECL:
      return C_UNITS;
   case T_ARCH:
      return C_ARCHITECTURE;
   case T_FUNC_DECL:
   case T_FUNC_BODY:
      return C_FUNCTION;
   case T_PROC_DECL:
   case T_PROC_BODY:
      return C_PROCEDURE;
   case T_ENTITY:
      return C_ENTITY;
   case T_TYPE_DECL:
      return C_TYPE;
   case T_FILE_DECL:
      return C_FILE;
   case T_PROCESS:
   case T_BLOCK:
   case T_FOR:
      return C_LABEL;
   case T_COMPONENT:
      return C_COMPONENT;
   case T_REF:
      return class_of(tree_ref(t));
   case T_ARRAY_REF:
   case T_ARRAY_SLICE:
   case T_RECORD_REF:
      return class_of(tree_value(t));
   case T_PACKAGE:
      return C_PACKAGE;
   case T_LIBRARY:
      return C_LIBRARY;
   case T_ELAB:
      return C_ELAB;
   default:
      fatal("missing class_of for %s", tree_kind_str(tree_kind(t)));
   }
}
Exemple #8
0
bool folded_enum(tree_t t, unsigned *pos)
{
   if (tree_kind(t) == T_REF) {
      tree_t decl = tree_ref(t);
      if (tree_kind(decl) == T_ENUM_LIT) {
         *pos = tree_pos(decl);
         return true;
      }
   }

   return false;
}
Exemple #9
0
bool folded_bool(tree_t t, bool *b)
{
   if (tree_kind(t) == T_REF) {
      tree_t decl = tree_ref(t);
      if (tree_kind(decl) == T_ENUM_LIT
          && type_ident(tree_type(decl)) == std_bool_i) {
         *b = (tree_pos(decl) == 1);
         return true;
      }
   }

   return false;
}
Exemple #10
0
bool folded_bool(tree_t t, bool *b)
{
   ident_t std_bool_i = ident_new("STD.STANDARD.BOOLEAN");
   if (tree_kind(t) == T_REF) {
      tree_t decl = tree_ref(t);
      if (tree_kind(decl) == T_ENUM_LIT
          && type_ident(tree_type(decl)) == std_bool_i) {
         *b = (tree_pos(decl) == 1);
         return true;
      }
   }

   return false;
}
Exemple #11
0
static void group_ref(tree_t target, group_nets_ctx_t *ctx, int start, int n)
{
   assert(tree_kind(target) == T_REF);

   tree_t decl = tree_ref(target);
   switch (tree_kind(decl)) {
   case T_SIGNAL_DECL:
      group_decl(decl, ctx, start, n);
      break;
   case T_ALIAS:
      group_target(tree_value(decl), ctx);
      break;
   default:
      break;
   }
}
Exemple #12
0
int tree_route_get(const str *user)
{
	struct tree *tree;
	int route;

	/* Find match in tree */
	tree = tree_ref();
	if (NULL == tree) {
		return -1;
	}

	route = tree_item_get(tree->root, user);
	tree_deref(tree);

	return route;
}
Exemple #13
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;
}
Exemple #14
0
Fichier : opt.c Projet : chiggs/nvc
static void opt_tag_last_value_attr_ref(tree_t t)
{
   static ident_t last_value_attr_i = NULL;

   if (last_value_attr_i == NULL)
      last_value_attr_i = ident_new("LAST_VALUE");

   if (tree_ident(t) == last_value_attr_i) {
      tree_t signal = tree_ref(tree_name(t));
      if (tree_kind(signal) != T_SIGNAL_DECL)
         return;

      // A signal in a package will not have nets assigned yet so we cannot
      // optimise out 'LAST_VALUE
      if (tree_nets(signal) > 0)
         tree_add_attr_int(signal, last_value_i, 1);
   }
}
Exemple #15
0
void tree_print(FILE *f)
{
	struct tree *tree;

	tree = tree_ref();

	fprintf(f, "Prefix route tree:\n");

	if (tree) {
		fprintf(f, " reference count: %d\n",
			atomic_get(&tree->refcnt));
		tree_item_print(tree->root, f, 0);
	}
	else {
		fprintf(f, " (no tree)\n");
	}

	tree_deref(tree);
}
Exemple #16
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");
   }
}
Exemple #17
0
END_TEST

START_TEST(test_lib_save)
{
   {
      tree_t ent = tree_new(T_ENTITY);
      tree_set_ident(ent, ident_new("name"));

      tree_add_attr_str(ent, ident_new("attr"), ident_new("test string"));

      type_t e = type_new(T_ENUM);
      type_set_ident(e, ident_new("myenum"));
      tree_t a = tree_new(T_ENUM_LIT);
      tree_set_ident(a, ident_new("a"));
      tree_set_type(a, e);
      tree_set_pos(a, 55);
      type_enum_add_literal(e, a);
      tree_t b = tree_new(T_ENUM_LIT);
      tree_set_ident(b, ident_new("b"));
      tree_set_type(b, e);
      type_enum_add_literal(e, b);

      tree_t p1 = tree_new(T_PORT_DECL);
      tree_set_ident(p1, ident_new("foo"));
      tree_set_subkind(p1, PORT_OUT);
      tree_set_type(p1, type_universal_int());
      tree_add_port(ent, p1);

      tree_t p2 = tree_new(T_PORT_DECL);
      tree_set_ident(p2, ident_new("bar"));
      tree_set_subkind(p2, PORT_IN);
      tree_set_type(p2, e);
      tree_add_port(ent, p2);

      tree_t ar = tree_new(T_ARCH);
      tree_set_ident(ar, ident_new("arch"));
      tree_set_ident2(ar, ident_new("foo"));

      tree_t pr = tree_new(T_PROCESS);
      tree_set_ident(pr, ident_new("proc"));
      tree_add_stmt(ar, pr);

      tree_t v1 = tree_new(T_VAR_DECL);
      tree_set_ident(v1, ident_new("v1"));
      tree_set_type(v1, e);

      tree_t r = tree_new(T_REF);
      tree_set_ident(r, ident_new("v1"));
      tree_set_ref(r, v1);

      tree_t s = tree_new(T_VAR_ASSIGN);
      tree_set_ident(s, ident_new("var_assign"));
      tree_set_target(s, r);
      tree_set_value(s, r);
      tree_add_stmt(pr, s);

      tree_t c = tree_new(T_LITERAL);
      tree_set_subkind(c, L_INT);
      tree_set_ival(c, 53);

      tree_t s2 = tree_new(T_VAR_ASSIGN);
      tree_set_ident(s2, ident_new("var_assign"));
      tree_set_target(s2, r);
      tree_set_value(s2, c);
      tree_add_stmt(pr, s2);

      tree_t s3 = tree_new(T_VAR_ASSIGN);
      tree_set_ident(s3, ident_new("var_assign"));
      tree_set_target(s3, r);
      tree_set_value(s3, str_to_agg("foobar", NULL));
      tree_add_stmt(pr, s3);

      tree_t s4 = tree_new(T_ASSERT);
      tree_set_ident(s4, ident_new("assert"));
      tree_set_value(s4, c);
      tree_set_severity(s4, c);
      tree_set_message(s4, str_to_agg("message", NULL));
      tree_add_stmt(pr, s4);

      lib_put(work, ar);
      lib_put(work, ent);
   }

   tree_gc();

   lib_save(work);
   lib_free(work);

   lib_add_search_path("/tmp");
   work = lib_find(ident_new("test_lib"), false);
   fail_if(work == NULL);

   {
      tree_t ent = lib_get(work, ident_new("name"));
      fail_if(ent == NULL);
      fail_unless(tree_kind(ent) == T_ENTITY);
      fail_unless(tree_ident(ent) == ident_new("name"));
      fail_unless(tree_ports(ent) == 2);

      ident_t attr = tree_attr_str(ent, ident_new("attr"));
      fail_if(attr == NULL);
      fail_unless(icmp(attr, "test string"));

      tree_t p1 = tree_port(ent, 0);
      fail_unless(tree_kind(p1) == T_PORT_DECL);
      fail_unless(tree_subkind(p1) == PORT_OUT);
      fail_unless(type_kind(tree_type(p1)) == T_INTEGER);

      tree_t p2 = tree_port(ent, 1);
      fail_unless(tree_kind(p2) == T_PORT_DECL);
      fail_unless(tree_subkind(p2) == PORT_IN);

      type_t e = tree_type(p2);
      fail_unless(type_kind(e) == T_ENUM);
      fail_unless(type_enum_literals(e) == 2);
      tree_t a = type_enum_literal(e, 0);
      fail_unless(tree_kind(a) == T_ENUM_LIT);
      fail_unless(tree_ident(a) == ident_new("a"));
      fail_unless(tree_type(a) == e);
      fail_unless(tree_pos(a) == 55);
      tree_t b = type_enum_literal(e, 1);
      fail_unless(tree_kind(b) == T_ENUM_LIT);
      fail_unless(tree_ident(b) == ident_new("b"));
      fail_unless(tree_type(b) == e);

      tree_t ar = lib_get(work, ident_new("arch"));
      fail_if(ar == NULL);
      fail_unless(tree_ident(ar) == ident_new("arch"));
      fail_unless(tree_ident2(ar) == ident_new("foo"));

      tree_t pr = tree_stmt(ar, 0);
      fail_unless(tree_kind(pr) == T_PROCESS);
      fail_unless(tree_ident(pr) == ident_new("proc"));

      tree_t s = tree_stmt(pr, 0);
      fail_unless(tree_kind(s) == T_VAR_ASSIGN);

      tree_t r = tree_target(s);
      fail_unless(tree_kind(r) == T_REF);
      fail_unless(tree_value(s) == r);

      tree_t s2 = tree_stmt(pr, 1);
      fail_unless(tree_kind(s2) == T_VAR_ASSIGN);
      fail_unless(tree_target(s2) == r);

      tree_t s3 = tree_stmt(pr, 2);
      fail_unless(tree_kind(s3) == T_VAR_ASSIGN);
      fail_unless(tree_target(s3) == r);
      fail_unless(tree_kind(tree_value(s3)) == T_AGGREGATE);

      tree_t s4 = tree_stmt(pr, 3);
      fail_unless(tree_kind(s4) == T_ASSERT);
      fail_unless(tree_ident(s4) == ident_new("assert"));

      tree_t c = tree_value(s2);
      fail_unless(tree_kind(c) == T_LITERAL);
      fail_unless(tree_subkind(c) == L_INT);
      fail_unless(tree_ival(c) == 53);

      // Type declaration and reference written to different units
      // so two copies of the type declaration will be read back
      // hence can't check for pointer equality here
      fail_unless(type_eq(tree_type(tree_ref(r)), e));
   }
}
Exemple #18
0
static map_list_t *elab_map(tree_t t, tree_t arch,
                            tree_formals_t tree_Fs, tree_formal_t tree_F,
                            tree_actuals_t tree_As, tree_actual_t tree_A)
{
   tree_t unit = tree_ref(arch);
   assert(tree_kind(unit) == T_ENTITY);

   const int nformals = tree_Fs(unit);
   const int nactuals = (tree_As != NULL) ? tree_As(t) : 0;

   bool *have_formals = xmalloc(sizeof(bool) * nformals);

   for (int i = 0; i < nformals; i++)
      have_formals[i] = false;

   const int maxr = nformals + nactuals;

   tree_t *rformals = xmalloc(sizeof(tree_t) * maxr);
   tree_t *ractuals = xmalloc(sizeof(tree_t) * maxr);
   int count = 0;

   map_list_t *maps = NULL;

   for (int i = 0; i < nactuals; i++) {
      tree_t p = tree_A(t, i);
      tree_t formal = NULL;

      switch (tree_subkind(p)) {
      case P_POS:
         {
            const int pos = tree_pos(p);
            formal = tree_F(unit, pos);
            have_formals[pos] = true;
         }
         break;
      case P_NAMED:
         {
            ident_t name = elab_formal_name(tree_name(p));
            for (int j = 0; j < nformals; j++) {
               tree_t port = tree_F(unit, j);
               if (tree_ident(port) == name) {
                  formal = port;
                  have_formals[j] = true;
                  break;
               }
            }
         }
         break;
      default:
         assert(false);
      }
      assert(formal != NULL);

      switch (tree_class(formal)) {
      case C_SIGNAL:
         ractuals[count] = elab_signal_port(arch, formal, p, &maps);
         break;

      case C_CONSTANT:
         ractuals[count] = tree_value(p);
         break;

      default:
         assert(false);
      }

      rformals[count] = formal;
      count++;
   }

   // Assign default values
   for (unsigned i = 0; i < nformals; i++) {
      if (!have_formals[i]) {
         tree_t f = tree_F(unit, i);
         if (tree_has_value(f)) {
            rformals[count] = f;
            ractuals[count] = tree_value(f);
            count++;
         }
      }
   }

   assert(count <= maxr);

   if (count > 0) {
      rewrite_params_t params = {
         .formals = rformals,
         .actuals = ractuals,
         .count   = count
      };
      tree_rewrite(arch, rewrite_refs, &params);

      tree_t ent = tree_ref(arch);
      if (tree_stmts(ent) > 0 || tree_decls(ent) > 0)
         tree_rewrite(ent, rewrite_refs, &params);
   }
Exemple #19
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)));
   }
}