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)); } }
static int analyse(int argc, char **argv) { set_work_lib(); static struct option long_options[] = { { "bootstrap", no_argument, 0, 'b' }, { "dump-llvm", no_argument, 0, 'd' }, { "prefer-explicit", 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 'b': opt_set_int("bootstrap", 1); break; case 'd': opt_set_int("dump-llvm", 1); break; case 'p': opt_set_int("prefer-explicit", 1); break; default: abort(); } } size_t unit_list_sz = 32; tree_t *units LOCAL = xmalloc(sizeof(tree_t) * unit_list_sz); int n_units = 0; for (int i = optind; i < argc; i++) { input_from_file(argv[i]); tree_t unit; while ((unit = parse()) && sem_check(unit)) ARRAY_APPEND(units, unit, n_units, unit_list_sz); } for (int i = 0; i < n_units; i++) { simplify(units[i]); bounds_check(units[i]); } if (parse_errors() + sem_errors() + bounds_errors() > 0) return EXIT_FAILURE; for (int i = 0; i < n_units; i++) { tree_kind_t kind = tree_kind(units[i]); const bool need_cgen = (kind == T_PACK_BODY) || ((kind == T_PACKAGE) && pack_needs_cgen(units[i])); if (need_cgen) opt(units[i]); else units[i] = NULL; } lib_save(lib_work()); for (int i = 0; i < n_units; i++) { if (units[i] != NULL) cgen(units[i]); } return EXIT_SUCCESS; }
static int analyse(int argc, char **argv) { set_work_lib(); static struct option long_options[] = { { "bootstrap", no_argument, 0, 'b' }, { "dump-llvm", no_argument, 0, 'd' }, { "dump-vcode", optional_argument, 0, 'v' }, { "prefer-explicit", no_argument, 0, 'p' }, // DEPRECATED { "relax", required_argument, 0, 'r' }, { 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 '?': fatal("unrecognised analyse option %s", argv[optind - 1]); case 'b': opt_set_int("bootstrap", 1); break; case 'd': opt_set_int("dump-llvm", 1); break; case 'v': opt_set_str("dump-vcode", optarg ?: ""); break; case 'p': warnf("the --prefer-explict option is deprecated: use " "--relax=prefer-explict instead"); opt_set_int("relax", RELAX_PREFER_EXPLICT); break; case 'r': opt_set_int("relax", parse_relax(optarg)); break; default: abort(); } } size_t unit_list_sz = 32; tree_t *units LOCAL = xmalloc(sizeof(tree_t) * unit_list_sz); int n_units = 0; for (int i = optind; i < argc; i++) { input_from_file(argv[i]); tree_t unit; while ((unit = parse()) && sem_check(unit)) ARRAY_APPEND(units, unit, n_units, unit_list_sz); } for (int i = 0; i < n_units; i++) { simplify(units[i]); bounds_check(units[i]); } if (parse_errors() + sem_errors() + bounds_errors() > 0) return EXIT_FAILURE; for (int i = 0; i < n_units; i++) { tree_kind_t kind = tree_kind(units[i]); const bool need_cgen = (kind == T_PACK_BODY) || ((kind == T_PACKAGE) && pack_needs_cgen(units[i])); if (need_cgen) opt(units[i]); else units[i] = NULL; } lib_save(lib_work()); for (int i = 0; i < n_units; i++) { if (units[i] != NULL) { lower_unit(units[i]); cgen(units[i]); } } return EXIT_SUCCESS; }
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; }
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; }