예제 #1
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);
}
예제 #2
0
static int make_cmd(int argc, char **argv)
{
   set_work_lib();

   static struct option long_options[] = {
      { "deps-only", no_argument, 0, 'd' },
      { "native",    no_argument, 0, 'n' },
      { "posix",     no_argument, 0, 'p' },
      { 0, 0, 0, 0 }
   };

   int c, index = 0;
   const char *spec = "";
   optind = 1;
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         // getopt_long already printed an error message
         exit(EXIT_FAILURE);
      case 'd':
         opt_set_int("make-deps-only", 1);
         break;
      case 'n':
         opt_set_int("native", 1);
         break;
      case 'p':
         opt_set_int("make-posix", 1);
         break;
      default:
         abort();
      }
   }

   const int count = argc - optind;
   tree_t *targets = xmalloc(count * sizeof(tree_t));

   lib_t work = lib_work();

   for (int i = optind; i < argc; i++) {
      ident_t name = to_unit_name(argv[i]);
      ident_t elab = ident_prefix(name, ident_new("elab"), '.');
      if ((targets[i - optind] = lib_get(work, elab)) == NULL) {
         if ((targets[i - optind] = lib_get(work, name)) == NULL)
            fatal("cannot find unit %s in library %s",
                  istr(name), istr(lib_name(work)));
      }
   }

   make(targets, count, stdout);

   return EXIT_SUCCESS;
}
예제 #3
0
파일: nvc.c 프로젝트: jkone27/nvc
static int make_cmd(int argc, char **argv)
{
   static struct option long_options[] = {
      { "deps-only", no_argument, 0, 'd' },
      { "native",    no_argument, 0, 'n' },
      { "posix",     no_argument, 0, 'p' },
      { 0, 0, 0, 0 }
   };

   const int next_cmd = scan_cmd(2, argc, argv);
   int c, index = 0;
   const char *spec = "";
   while ((c = getopt_long(next_cmd, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         fatal("unrecognised make option %s", argv[optind - 1]);
      case 'd':
         opt_set_int("make-deps-only", 1);
         break;
      case 'n':
         opt_set_int("native", 1);
         break;
      case 'p':
         opt_set_int("make-posix", 1);
         break;
      default:
         abort();
      }
   }

   const int count = next_cmd - optind;
   tree_t *targets = xmalloc(count * sizeof(tree_t));

   lib_t work = lib_work();

   for (int i = optind; i < next_cmd; i++) {
      ident_t name = to_unit_name(argv[i]);
      ident_t elab = ident_prefix(name, ident_new("elab"), '.');
      if ((targets[i - optind] = lib_get(work, elab)) == NULL) {
         if ((targets[i - optind] = lib_get(work, name)) == NULL)
            fatal("cannot find unit %s in library %s",
                  istr(name), istr(lib_name(work)));
      }
   }

   make(targets, count, stdout);

   argc -= next_cmd - 1;
   argv += next_cmd - 1;

   return argc > 1 ? process_command(argc, argv) : EXIT_SUCCESS;
}
예제 #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
파일: link.c 프로젝트: ifreemyli/nvc
static void link_context_package(tree_t unit, lib_t lib,
                                 FILE *deps, context_fn_t fn)
{
   assert(n_linked < MAX_ARGS - 1);

   if (pack_needs_cgen(unit) && !link_already_have(unit)) {
      (*fn)(lib, unit, deps);
      linked[n_linked++] = unit;
   }

   link_all_context(unit, deps, fn);

   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) {
      if (link_needs_body(unit))
         fatal("missing body for package %s", istr(name));
      else
         return;
   }

   link_all_context(body, deps, fn);

   if (!link_already_have(body)) {
      (*fn)(lib, body, deps);
      linked[n_linked++] = body;
   }
}
예제 #6
0
static int codegen(int argc, char **argv)
{
   set_work_lib();

   static struct option long_options[] = {
      {0, 0, 0, 0}
   };

   int c, index = 0;
   const char *spec = "";
   optind = 1;
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         // getopt_long already printed an error message
         exit(EXIT_FAILURE);
      default:
         abort();
      }
   }

   if (optind == argc)
      fatal("missing top-level unit name");

   ident_t unit_i = to_unit_name(argv[optind]);
   tree_t pack = lib_get(lib_work(), unit_i);
   if (pack == NULL)
      fatal("cannot find unit %s in library %s",
            istr(unit_i), istr(lib_name(lib_work())));

   if (tree_kind(pack) != T_PACKAGE)
      fatal("this command can only be used with packages");

   if (pack_needs_cgen(pack))
      link_package(pack);

   ident_t body_i = ident_prefix(unit_i, ident_new("body"), '-');
   tree_t body = lib_get(lib_work(), body_i);
   if (body != NULL)
      link_package(body);

   return EXIT_SUCCESS;
}
예제 #7
0
파일: link.c 프로젝트: ifreemyli/nvc
static void link_walk_lib(ident_t name, int kind, void *context)
{
   lib_walk_params_t *params = context;

   if (kind == T_PACKAGE)
      link_context_package(lib_get(params->lib, name), params->lib,
                           params->deps, params->fn);
}
예제 #8
0
파일: nvc.c 프로젝트: jkone27/nvc
static int codegen(int argc, char **argv)
{
   static struct option long_options[] = {
      { 0, 0, 0, 0 }
   };

   const int next_cmd = scan_cmd(2, argc, argv);
   int c, index = 0;
   const char *spec = "";
   while ((c = getopt_long(next_cmd, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         fatal("unrecognised codegen option %s", argv[optind - 1]);
      default:
         abort();
      }
   }

   set_top_level(argv, next_cmd);

   tree_t pack = lib_get(lib_work(), top_level);
   if (pack == NULL)
      fatal("cannot find unit %s in library %s",
            istr(top_level), istr(lib_name(lib_work())));

   if (tree_kind(pack) != T_PACKAGE)
      fatal("this command can only be used with packages");

   if (pack_needs_cgen(pack))
      link_package(pack);

   ident_t body_i = ident_prefix(top_level, ident_new("body"), '-');
   tree_t body = lib_get(lib_work(), body_i);
   if (body != NULL)
      link_package(body);

   argc -= next_cmd - 1;
   argv += next_cmd - 1;

   return argc > 1 ? process_command(argc, argv) : EXIT_SUCCESS;
}
예제 #9
0
static int dump_cmd(int argc, char **argv)
{
   set_work_lib();

   static struct option long_options[] = {
      {"elab", no_argument, 0, 'e'},
      {"body", no_argument, 0, 'b'},
      {"nets", no_argument, 0, 'n'},
      {0, 0, 0, 0}
   };

   bool add_elab = false, add_body = false, nets = false;
   int c, index = 0;
   const char *spec = "eb";
   optind = 1;
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         // getopt_long already printed an error message
         exit(EXIT_FAILURE);
      case 'e':
         add_elab = true;
         break;
      case 'b':
         add_body = true;
         break;
      case 'n':
         add_elab = true;
         nets = true;
         break;
      default:
         abort();
      }
   }

   if (optind == argc)
      fatal("missing unit name");

   for (int i = optind; i < argc; i++) {
      ident_t name = to_unit_name(argv[i]);
      if (add_elab)
         name = ident_prefix(name, ident_new("elab"), '.');
      else if (add_body)
         name = ident_prefix(name, ident_new("body"), '-');
      tree_t top = lib_get(lib_work(), name);
      if (top == NULL)
         fatal("%s not analysed", istr(name));
      (nets ? dump_nets : dump)(top);
   }

   return EXIT_SUCCESS;
}
예제 #10
0
파일: nvc.c 프로젝트: jkone27/nvc
static int dump_cmd(int argc, char **argv)
{
   static struct option long_options[] = {
      { "elab", no_argument, 0, 'E' },
      { "body", no_argument, 0, 'b' },
      { "nets", no_argument, 0, 'n' },
      { 0, 0, 0, 0 }
   };

   const int next_cmd = scan_cmd(2, argc, argv);
   bool add_elab = false, add_body = false, nets = false;
   int c, index = 0;
   const char *spec = "Eb";
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 0:
         // Set a flag
         break;
      case '?':
         fatal("unrecognised dump option %s", argv[optind - 1]);
      case 'E':
         add_elab = true;
         break;
      case 'b':
         add_body = true;
         break;
      case 'n':
         add_elab = true;
         nets = true;
         break;
      default:
         abort();
      }
   }

   if (optind == next_cmd)
      fatal("missing unit name");

   for (int i = optind; i < next_cmd; i++) {
      ident_t name = to_unit_name(argv[i]);
      if (add_elab)
         name = ident_prefix(name, ident_new("elab"), '.');
      else if (add_body)
         name = ident_prefix(name, ident_new("body"), '-');
      tree_t top = lib_get(lib_work(), name);
      if (top == NULL)
         fatal("%s not analysed", istr(name));
      (nets ? dump_nets : dump)(top);
   }

   argc -= next_cmd - 1;
   argv += next_cmd - 1;

   return argc > 1 ? process_command(argc, argv) : EXIT_SUCCESS;
}
예제 #11
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));
   }
}
예제 #12
0
static int elaborate(int argc, char **argv)
{
   set_work_lib();

   static struct option long_options[] = {
      {"disable-opt", no_argument, 0, 'o'},
      {"dump-llvm", no_argument, 0, 'd'},
      {"native", no_argument, 0, 'n'},
      {"cover", no_argument, 0, 'c'},
      {0, 0, 0, 0}
   };

   int c, index = 0;
   const char *spec = "";
   optind = 1;
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 'o':
         opt_set_int("optimise", 0);
         break;
      case 'd':
         opt_set_int("dump-llvm", 1);
         break;
      case 'n':
         opt_set_int("native", 1);
         break;
      case 'c':
         opt_set_int("cover", 1);
         break;
      case 0:
         // Set a flag
         break;
      case '?':
         // getopt_long already printed an error message
         exit(EXIT_FAILURE);
      default:
         abort();
      }
   }

   if (optind == argc)
      fatal("missing top-level unit name");

   ident_t unit_i = to_unit_name(argv[optind]);
   tree_t unit = lib_get(lib_work(), unit_i);
   if (unit == NULL)
      fatal("cannot find unit %s in library %s",
            istr(unit_i), istr(lib_name(lib_work())));

   tree_t e = elab(unit);
   if (e == NULL)
      return EXIT_FAILURE;

   opt(e);
   group_nets(e);

   // Save the library now so the code generator can attach temporary
   // meta data to trees
   lib_save(lib_work());

   cgen(e);
   link_bc(e);

   return EXIT_SUCCESS;
}
예제 #13
0
파일: nvc.c 프로젝트: ifreemyli/nvc
static int elaborate(int argc, char **argv)
{
   set_work_lib();

   static struct option long_options[] = {
      { "disable-opt", no_argument,       0, 'o' },
      { "dump-llvm",   no_argument,       0, 'd' },
      { "dump-vcode",  optional_argument, 0, 'V' },
      { "native",      no_argument,       0, 'n' },
      { "cover",       no_argument,       0, 'c' },
      { "verbose",     no_argument,       0, 'v' },
      { 0, 0, 0, 0 }
   };

   bool verbose = false;
   int c, index = 0;
   const char *spec = "v";
   optind = 1;
   while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) {
      switch (c) {
      case 'o':
         opt_set_int("optimise", 0);
         break;
      case 'd':
         opt_set_int("dump-llvm", 1);
         break;
      case 'V':
         opt_set_str("dump-vcode", optarg ?: "");
         break;
      case 'n':
         opt_set_int("native", 1);
         break;
      case 'c':
         opt_set_int("cover", 1);
         break;
      case 'v':
         verbose = true;
         break;
      case 0:
         // Set a flag
         break;
      case '?':
         fatal("unrecognised elaborate option %s", argv[optind - 1]);
      default:
         abort();
      }
   }

   if (optind == argc)
      fatal("missing top-level unit name");

   elab_verbose(verbose, "initialising");

   ident_t unit_i = to_unit_name(argv[optind]);
   tree_t unit = lib_get(lib_work(), unit_i);
   if (unit == NULL)
      fatal("cannot find unit %s in library %s",
            istr(unit_i), istr(lib_name(lib_work())));

   elab_verbose(verbose, "loading top-level unit");

   tree_t e = elab(unit);
   if (e == NULL)
      return EXIT_FAILURE;

   elab_verbose(verbose, "elaborating design");

   opt(e);
   elab_verbose(verbose, "optimising design");

   group_nets(e);
   elab_verbose(verbose, "grouping nets");

   // Save the library now so the code generator can attach temporary
   // meta data to trees
   lib_save(lib_work());
   elab_verbose(verbose, "saving library");

   lower_unit(e);
   elab_verbose(verbose, "generating intermediate code");

   cgen(e);
   elab_verbose(verbose, "generating LLVM");

   link_bc(e);
   elab_verbose(verbose, "linking");

   return EXIT_SUCCESS;
}