Example #1
0
File: opt.c Project: 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);
}
Example #2
0
File: group.c Project: nickg/nvc
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);
   }
}
Example #3
0
END_TEST

START_TEST(test_copy1)
{
   input_from_file(TESTDIR "/elab/copy1.vhd");

   const error_t expect[] = {
      { -1, NULL }
   };
   expect_errors(expect);

   tree_t e = run_elab();

   int nfuncs = 0, nshared = 0;

   const int ndecls = tree_decls(e);
   for (int i = 0; i < ndecls; i++) {
      tree_t t = tree_decl(e, i);
      if (tree_kind(t) == T_FUNC_BODY)
         nfuncs++;
      else if (tree_kind(t) == T_VAR_DECL)
         nshared++;
   }

   fail_unless(nfuncs == 1);
   fail_unless(nshared == 2);
}
Example #4
0
File: opt.c Project: chiggs/nvc
static tree_t opt_delete_wait_only_fn(tree_t t, void *ctx)
{
   if (tree_kind(t) != T_PROCESS)
      return t;

   if ((tree_stmts(t) == 1) && (tree_kind(tree_stmt(t, 0)) == T_WAIT))
      return NULL;
   else
      return t;
}
Example #5
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)));
   }
}
Example #6
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;
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
File: opt.c Project: chiggs/nvc
void opt(tree_t top)
{
   if (tree_kind(top) == T_ELAB)
      opt_delete_wait_only(top);

   tree_visit(top, opt_tag, NULL);
}
Example #10
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);
}
Example #11
0
File: opt.c Project: 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);
   }
}
Example #12
0
File: group.c Project: nickg/nvc
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;
   }
}
Example #13
0
File: group.c Project: nickg/nvc
static void ungroup_name(tree_t name, group_nets_ctx_t *ctx)
{
   switch (tree_kind(name)) {
   case T_ARRAY_REF:
   case T_ARRAY_SLICE:
   case T_RECORD_REF:
      ungroup_name(tree_value(name), ctx);
      break;
   case T_REF:
      ungroup_ref(name, ctx);
      break;
   default:
      fatal_trace("cannot handle tree type %s in ungroup_name",
                  tree_kind_str(tree_kind(name)));
   }
}
Example #14
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;
}
Example #15
0
File: group.c Project: nickg/nvc
static void group_nets_visit_fn(tree_t t, void *_ctx)
{
   group_nets_ctx_t *ctx = _ctx;

   switch (tree_kind(t)) {
   case T_SIGNAL_ASSIGN:
      group_target(tree_target(t), ctx);
      break;

   case T_WAIT:
      {
         const int ntriggers = tree_triggers(t);
         for (int i = 0; i < ntriggers; i++)
            group_target(tree_trigger(t, i), ctx);
      }
      break;

   case T_PCALL:
      ungroup_proc_params(t, ctx);
      break;

   case T_SIGNAL_DECL:
      // Ensure that no group is larger than a signal declaration
      group_decl(t, ctx, 0, -1);
      break;

   default:
      break;
   }
}
Example #16
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;
}
Example #17
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;
}
Example #18
0
File: vcd.c Project: SnookEE/nvc
void vcd_restart(void)
{
   if (vcd_file == NULL)
      return;

   vcd_emit_header();

   int next_key = 0;
   const int ndecls = tree_decls(vcd_top);
   for (int i = 0; i < ndecls; i++) {
      tree_t d = tree_decl(vcd_top, i);
      switch (tree_kind(d)) {
      case T_HIER:
         fprintf(vcd_file, "$scope module %s $end\n", istr(tree_ident(d)));
         break;
      case T_SIGNAL_DECL:
         if (wave_should_dump(d))
            vcd_process_signal(d, &next_key);
         break;
      default:
         break;
      }

      int npop = tree_attr_int(d, ident_new("scope_pop"), 0);
      while (npop-- > 0)
         fprintf(vcd_file, "$upscope $end\n");
   }

   fprintf(vcd_file, "$enddefinitions $end\n");

   fprintf(vcd_file, "$dumpvars\n");

   last_time = UINT64_MAX;

   for (int i = 0; i < ndecls; i++) {
      tree_t d = tree_decl(vcd_top, i);
      if (tree_kind(d) == T_SIGNAL_DECL) {
         vcd_data_t *data = tree_attr_ptr(d, vcd_data_i);
         if (likely(data != NULL))
            vcd_event_cb(0, d, data->watch, data);
      }
   }

   fprintf(vcd_file, "$end\n");
}
Example #19
0
bool folded_int(tree_t t, int64_t *l)
{
   if ((tree_kind(t) == T_LITERAL) && (tree_subkind(t) == L_INT)) {
      *l = tree_ival(t);
      return true;
   }
   else
      return false;
}
Example #20
0
static void elab_copy_context(tree_t src, const elab_ctx_t *ctx)
{
   const int nsrc = tree_contexts(src);
   for (int i = 0; i < nsrc; i++) {
      tree_t c = tree_context(src, i);
      if (tree_kind(c) == T_USE)
         elab_use_clause(c, ctx);
   }
}
Example #21
0
File: group.c Project: nickg/nvc
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);
   }
}
Example #22
0
bool folded_real(tree_t t, double *l)
{
   if ((tree_kind(t) == T_LITERAL) && (tree_subkind(t) == L_REAL)) {
      *l = tree_dval(t);
      return true;
   }
   else
      return false;
}
Example #23
0
File: shell.c Project: a4a881d4/nvc
static int shell_cmd_watch(ClientData cd, Tcl_Interp *interp,
                           int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "watch - Trace changes to a signal\n"
      "\n"
      "Usage: watch SIGNALS...\n"
      "\n"
      "Prints a message every time an update occurs to a signal listed."
      "\n"
      "Examples:\n"
      "  watch [signals {clk}]  Trace updates to all signals named clk\n";

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

   if (objc == 1) {
      warnf("nothing to watch (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);

         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);
         else if (tree_kind(t) != T_SIGNAL_DECL)
            return tcl_error(interp, "not a signal: %s", str);
         else if (type_is_array(tree_type(t)))
            return tcl_error(interp, "only scalar signals may be watched");
         // TODO: make this work for arrays

         slave_watch_msg_t msg = {
            .index = tree_index(t)
         };
         slave_post_msg(SLAVE_WATCH, &msg, sizeof(msg));
      }
   }

   return TCL_OK;
}
Example #24
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");
   }
}
Example #25
0
VOID paste_tree(WORD dobj, WORD dx, WORD dy, WORD dup)
{
	if (tree_kind(rcs_clipkind))
	{
		if (ins_tree(ad_clip, ROOT, rcs_clipkind, dobj, dx, dy) != -1L)
		{
			if (!dup)
				clr_clip();
		}
	}
}
Example #26
0
static bool folded(tree_t t)
{
   tree_kind_t kind = tree_kind(t);
   if (kind == T_LITERAL)
      return true;
   else if (kind == T_REF) {
      bool dummy;
      return folded_bool(t, &dummy);
   }
   else
      return false;
}
Example #27
0
File: shell.c Project: a4a881d4/nvc
static int shell_cmd_unwatch(ClientData cd, Tcl_Interp *interp,
                             int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "unwatch - Stop tracing signals\n"
      "\n"
      "Usage: unwatch SIGNALS...\n"
      "\n"
      "Clears any watch callback on SIGNALS. Note this will also stop any\n"
      "VCD or other waveform capture for these signals.\n"
      "\n"
      "Examples:\n"
      "  watch [signals {clk}]  Stop tracing updates to clk\n";

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

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

   hash_t *decl_hash = (hash_t *)cd;

   // TODO: refactor this code to avoid duplication with "watch" and "show"
   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);
         else if (tree_kind(t) != T_SIGNAL_DECL)
            return tcl_error(interp, "not a signal: %s", str);

         slave_unwatch_msg_t msg = {
            .index = tree_index(t)
         };
         slave_post_msg(SLAVE_UNWATCH, &msg, sizeof(msg));
      }
   }

   return TCL_OK;
}
Example #28
0
END_TEST

START_TEST(test_issue19)
{
   input_from_file(TESTDIR "/elab/issue19.vhd");

   const error_t expect[] = {
      { -1, NULL }
   };
   expect_errors(expect);

   tree_t e = run_elab();

   tree_t tmp = NULL;
   const int ndecls = tree_decls(e);
   for (int i = 0; (i < ndecls) && (tmp == NULL); i++) {
      tree_t t = tree_decl(e, i);
      if (icmp(tree_ident(t), ":comp6:c1:tmp"))
         tmp = t;
   }

   fail_if(tmp == NULL);

   tree_t value = tree_value(tmp);
   fail_unless(tree_kind(value) == T_LITERAL);
   fail_unless(tree_ival(value) == 32);

   for (int i = 0; (i < ndecls) && (tmp == NULL); i++) {
      tree_t t = tree_decl(e, i);
      if (icmp(tree_ident(t), ":comp6:c1:tmp3"))
         tmp = t;
   }

   fail_if(tmp == NULL);

   value = tree_value(tmp);
   fail_unless(tree_kind(value) == T_LITERAL);
   fail_unless(tree_ival(value) == 32);
}
Example #29
0
File: group.c Project: 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)));
   }
}
Example #30
0
static bool elab_have_context(tree_t unit, ident_t name)
{
   const int ndest = tree_contexts(unit);
   for (int i = 0; i < ndest; i++) {
      tree_t c2 = tree_context(unit, i);
      if (tree_kind(c2) != T_USE)
         continue;

      if (tree_ident(c2) == name)
         return true;
   }

   return false;
}