示例#1
0
文件: group.c 项目: nickg/nvc
static int group_net_to_field(type_t type, netid_t nid)
{
   int count = 0;
   if (type_is_record(type)) {
      const int nfields = type_fields(type);
      netid_t first = 0;
      for (int i = 0; i < nfields; i++) {
         tree_t field = type_field(type, i);
         type_t ftype = tree_type(field);
         const netid_t next = first + type_width(tree_type(field));
         if (nid >= first && nid < next) {
            if (type_is_array(ftype) || type_is_record(ftype))
               return count + group_net_to_field(ftype, nid - first);
            else
               return count;
         }
         first = next;
         count += type_width(ftype);
      }
      fatal_trace("group_net_to_field failed to find field for nid=%d type=%s",
                  nid, type_pp(type));
   }
   else if (type_is_array(type)) {
      type_t elem = type_elem(type);
      const int width = type_width(elem);
      if (type_is_record(elem))
         return (nid / width) * width + group_net_to_field(elem, nid % width);
      else
         return group_net_to_field(elem, nid % width);
   }
   else
      return 0;
}
示例#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;
}
示例#3
0
文件: group.c 项目: nickg/nvc
static void group_decl(tree_t decl, group_nets_ctx_t *ctx, int start, int n)
{
   netid_t first = NETID_INVALID;
   unsigned len = 0;
   type_t type = tree_type(decl);
   const int nnets = tree_nets(decl);
   const bool record = group_contains_record(type);
   int ffield = -1;
   assert((n == -1) | (start + n <= nnets));
   for (int i = start; i < (n == -1 ? nnets : start + n); i++) {
      netid_t nid = tree_net(decl, i);
      if (first == NETID_INVALID) {
         first  = nid;
         len    = 1;
         ffield = record ? group_net_to_field(type, i) : -1;
      }
      else if (nid == first + len
               && (!record || group_net_to_field(type, i) == ffield))
         ++len;
      else {
         group_add(ctx, first, len);
         first  = nid;
         len    = 1;
         ffield = record ? group_net_to_field(type, i) : -1;
      }
   }

   if (first != NETID_INVALID)
      group_add(ctx, first, len);
   else {
      // Array signal with null range
      tree_add_attr_int(decl, null_range_i, 1);
   }
}
示例#4
0
文件: eval.c 项目: manasdas17/nvc
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;
}
示例#5
0
文件: lxt.c 项目: SnookEE/nvc
static void lxt_fmt_enum(tree_t decl, watch_t *w, lxt_data_t *data)
{
   uint64_t val;
   rt_watch_value(w, &val, 1, false);

   tree_t lit = type_enum_literal(tree_type(decl), val);
   lt_emit_value_string(trace, data->sym, 0, (char *)istr(tree_ident(lit)));
}
示例#6
0
文件: common.c 项目: gr8linux/nvc
tree_t make_ref(tree_t to)
{
   tree_t t = tree_new(T_REF);
   tree_set_ident(t, tree_ident(to));
   tree_set_ref(t, to);
   tree_set_type(t, tree_type(to));
   return t;
}
示例#7
0
文件: shell.c 项目: 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;
}
示例#8
0
文件: common.c 项目: gr8linux/nvc
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;
}
示例#9
0
文件: common.c 项目: gr8linux/nvc
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;
}
示例#10
0
文件: fst.c 项目: SnookEE/nvc
static void fst_fmt_enum(tree_t decl, watch_t *w, fst_data_t *data)
{
   uint64_t val;
   rt_watch_value(w, &val, 1, false);

   tree_t lit = type_enum_literal(tree_type(decl), val);
   const char *str = istr(tree_ident(lit));

   fstWriterEmitVariableLengthValueChange(
      fst_ctx, data->handle, str, strlen(str));
}
示例#11
0
文件: factory.hpp 项目: gnzlbg/hm3
/// Is the block b readable by the grid readers?
inline bool is_readable(io::json const& b) {
  string type_str = io::read_field(b, "type", HM3_AT_);
  if (type_str == tree_type()) {
    return true;
    // } else if (type_str == single_type()) {
    //   return true;
  } else if (type_str == multi_type()) {
    return true;
  } else {
    return false;
  }
}
示例#12
0
文件: common.c 项目: gr8linux/nvc
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;
}
示例#13
0
文件: common.c 项目: gr8linux/nvc
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;
}
示例#14
0
文件: common.c 项目: gr8linux/nvc
type_t index_type_of(type_t type, int dim)
{
   if (type_is_unconstrained(type))
      return type_index_constr(type_base_recur(type), dim);
   else if (type_kind(type) == T_ENUM)
      return type;
   else {
      tree_t left = type_dim(type, dim).left;

      // If the left bound has not been assigned a type then there is some
      // error with it so just return a dummy type here
      return tree_has_type(left) ? tree_type(left) : type;
   }
}
示例#15
0
文件: common.c 项目: gr8linux/nvc
tree_t find_record_field(tree_t rref)
{
   ident_t fname = tree_ident(rref);
   type_t value_type = tree_type(tree_value(rref));

   const int nfields = type_fields(value_type);
   for (int i = 0; i < nfields; i++) {
      tree_t field = type_field(value_type, i);
      if (tree_ident(field) == fname)
         return field;
   }

   return NULL;
}
示例#16
0
文件: common.c 项目: sylphase/nvc
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;
}
示例#17
0
文件: common.c 项目: gr8linux/nvc
int record_field_to_net(type_t type, ident_t name)
{
   int offset = 0;

   const int nfields = type_fields(type);
   for (int i = 0; i < nfields; i++) {
      tree_t field = type_field(type, i);
      if (tree_ident(field) == name)
         return offset;
      else
         offset += type_width(tree_type(field));
   }

   assert(false);
}
示例#18
0
static STATEMENT *reduce_statement(MODULE *module, FUNCTION *func, BLOCK *block, STATEMENT *stmt)
{
    if (stmt == NULL)
        return stmt;
    
    if (tree_is_type(stmt, STMT_ASSIGN))
    {
        EXPRESSION *expr = tree_get_child(stmt, 1);
        expr = simplify_expression(module, func, block, expr, stmt);
        tree_get_child(stmt, 1) = expr;
    }
    else if (tree_is_type(stmt, STMT_IF))
    {
        EXPRESSION *cond = tree_get_child(stmt, 0);
        cond = simplify_expression(module, func, block, cond, stmt);
        tree_get_child(stmt, 0) = cond;
        reduce_block(module, func, tree_get_child(stmt, 1));
        reduce_block(module, func, tree_get_child(stmt, 2));
    }
    else if (tree_is_type(stmt, STMT_WHILE))
    {
        EXPRESSION *cond = tree_get_child(stmt, 0);
        BLOCK *body = tree_get_child(stmt, 1);
        if (!is_atomic(cond))
        {
            EXPRESSION *old_cond = cond;
            cond = atomise_expression(module, func, block, cond, stmt);
            tree_get_child(stmt, 0) = cond;
            STATEMENT *new_assign = make_assignment(cond, CAST_TO_EXPRESSION(tree_copy(old_cond)), CAST_TO_AST(cond)->source_line);
            tree_add_child(body, new_assign);
        }
        reduce_block(module, func, body);
    }
    else if (tree_is_type(stmt, STMT_RETURN))
    {
        EXPRESSION *expr = tree_get_child(stmt, 0);
        expr = atomise_expression(module, func, block, expr, stmt);
        tree_get_child(stmt, 0) = expr;
    }
    else if (tree_is_type(stmt, STMT_RESTART))
    {
        /* Do nothing. */
    }
    else
        error("Not sure how to reduce statement of type %d\n", tree_type(stmt));
    
    return stmt;
}
示例#19
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;
}
示例#20
0
char *get_escaped_op_symbol(EXPRESSION *expr)
{
    switch (tree_type(expr))
    {
        case EXPR_LEQ:
            return "&lt;=";
        case EXPR_GEQ:
            return "&gt;=";
        case EXPR_LT:
            return "&lt;";
        case EXPR_GT:
            return "&gt;";
        case EXPR_AND:
            return "&amp;&amp;";
        default:
            return get_op_symbol(expr);
    }
}
示例#21
0
文件: group.c 项目: 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)));
   }
}
示例#22
0
文件: type.c 项目: manasdas17/nvc
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;
}
示例#23
0
文件: test_lib.c 项目: SnookEE/nvc
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));
   }
}
示例#24
0
文件: vcd.c 项目: 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);
}
示例#25
0
文件: lxt.c 项目: 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;
}
示例#26
0
文件: shell.c 项目: SnookEE/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:
            {
               const size_t len = tree_nets(t);
               uint64_t *values LOCAL = xmalloc(len * sizeof(uint64_t));
               rt_signal_value(t, values, len);

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

               LOCAL_TEXT_BUF values_tb = pprint(t, values, len);
               printf("%-30s%-20s%s\n",
                      str,
                      (short_name != NULL ? short_name + 1 : type_str),
                      tb_get(values_tb));
            }
            break;

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

   return TCL_OK;
}
示例#27
0
文件: fst.c 项目: 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);
}
示例#28
0
文件: shell.c 项目: 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;
}
示例#29
0
文件: group.c 项目: 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)));
   }
}
示例#30
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)));
   }
}