static void cover_report_file(cover_file_t *f, const char *dir) { char buf[256]; snprintf(buf, sizeof(buf), "%s/%s", dir, cover_file_url(f)); FILE *fp = lib_fopen(lib_work(), buf, "w"); if (fp == NULL) fatal("failed to create %s", buf); fprintf(fp, "<html>\n" "<head>\n" " <title>Coverage report for %s</title>\n" "</head>\n" "<body>\n", f->name); fprintf(fp, "<table>\n"); for (int i = 0; i < f->n_lines; i++) { cover_line_t *l = &(f->lines[i]); cover_report_line(fp, l); } fprintf(fp, "</table>\n"); fprintf(fp, "<body>\n</html>\n"); fclose(fp); }
static int list_cmd(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 list option %s", argv[optind - 1]); default: abort(); } } lib_walk_index(lib_work(), list_walk_fn, NULL); argc -= next_cmd - 1; argv += next_cmd - 1; return argc > 1 ? process_command(argc, argv) : EXIT_SUCCESS; }
static void cover_index(ident_t name, const char *dir) { char buf[256]; snprintf(buf, sizeof(buf), "%s/index.html", dir); FILE *fp = lib_fopen(lib_work(), buf, "w"); if (fp == NULL) fatal("failed to create %s", buf); fprintf(fp, "<html>\n" "<head>\n" " <title>Coverage report for %s</title>\n" "</head>\n" "<body>\n", istr(name)); fprintf(fp, "<ul>\n"); for (cover_file_t *f = files; f != NULL; f = f->next) { fprintf(fp, "<li><a href=\"%s\">%s</a></li>\n", cover_file_url(f), f->name); } fprintf(fp, "</ul>\n"); fprintf(fp, "<body>\n</html>\n"); fclose(fp); }
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; }
static lib_t elab_find_lib(ident_t name, const elab_ctx_t *ctx) { lib_t tmp = lib_work(); lib_set_work(ctx->library); lib_t lib = lib_find(ident_until(name, '.'), true); lib_set_work(tmp); return lib; }
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; }
static lib_t elab_find_lib(ident_t name, const elab_ctx_t *ctx) { lib_t tmp = lib_work(); lib_set_work(ctx->library); lib_t lib = lib_find(istr(ident_until(name, '.')), true, true); if (lib == NULL) fatal("cannot continue"); lib_set_work(tmp); return lib; }
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; }
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; }
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; }
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; }
static ident_t to_unit_name(const char *str) { char *name = strdup(str); for (char *p = name; *p; p++) *p = toupper((int)*p); ident_t i = ident_prefix(lib_name(lib_work()), ident_new(name), '.'); free(name); return i; }
void jit_init(ident_t top) { ident_t orig = ident_strip(top, ident_new(".elab")); ident_t final = ident_prefix(orig, ident_new("final"), '.'); char bc_fname[64], so_fname[64];; snprintf(bc_fname, sizeof(bc_fname), "_%s.bc", istr(final)); #if defined __CYGWIN__ snprintf(so_fname, sizeof(so_fname), "_%s.dll", istr(final)); #else snprintf(so_fname, sizeof(so_fname), "_%s.so", istr(final)); #endif char bc_path[PATH_MAX], so_path[PATH_MAX]; lib_realpath(lib_work(), bc_fname, bc_path, sizeof(bc_path)); lib_realpath(lib_work(), so_fname, so_path, sizeof(so_path)); using_jit = (jit_mod_time(bc_path) > jit_mod_time(so_path)); if (using_jit) jit_init_llvm(bc_path); else jit_init_native(so_path); }
static void group_write_netdb(tree_t top, group_nets_ctx_t *ctx) { char *name = xasprintf("_%s.netdb", istr(tree_ident(top))); fbuf_t *f = lib_fbuf_open(lib_work(), name, FBUF_OUT); if (f == NULL) fatal("failed to create net database file %s", name); free(name); for (group_t *it = ctx->groups; it != NULL; it = it->next) { write_u32(it->gid, f); write_u32(it->first, f); write_u32(it->length, f); } write_u32(GROUPID_INVALID, f); fbuf_close(f); }
void cover_report(tree_t top, const int32_t *stmts) { stmt_tag_i = ident_new("stmt_tag"); tree_visit(top, cover_report_stmts_fn, (void *)stmts); ident_t name = ident_strip(tree_ident(top), ident_new(".elab")); char dir[256]; snprintf(dir, sizeof(dir), "%s.cover", istr(name)); lib_t work = lib_work(); lib_mkdir(work, dir); for (cover_file_t *f = files; f != NULL; f = f->next) cover_report_file(f, dir); cover_index(name, dir); char output[PATH_MAX]; lib_realpath(work, dir, output, sizeof(output)); notef("coverage report generated in %s/", output); }
static int run(int argc, char **argv) { set_work_lib(); static struct option long_options[] = { { "trace", no_argument, 0, 't' }, { "batch", no_argument, 0, 'b' }, { "command", no_argument, 0, 'c' }, { "stop-time", required_argument, 0, 's' }, { "stats", no_argument, 0, 'S' }, { "wave", optional_argument, 0, 'w' }, { "stop-delta", required_argument, 0, 'd' }, { "format", required_argument, 0, 'f' }, { "include", required_argument, 0, 'i' }, { "exclude", required_argument, 0, 'e' }, { 0, 0, 0, 0 } }; enum { BATCH, COMMAND } mode = BATCH; enum { LXT, FST, VCD} wave_fmt = FST; uint64_t stop_time = UINT64_MAX; const char *wave_fname = NULL; int c, index = 0; const char *spec = "bcw::"; 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 't': opt_set_int("rt_trace_en", 1); break; case 'b': mode = BATCH; break; case 'c': mode = COMMAND; break; case 's': stop_time = parse_time(optarg); break; case 'f': if (strcmp(optarg, "vcd") == 0) wave_fmt = VCD; else if (strcmp(optarg, "fst") == 0) wave_fmt = FST; else if (strcmp(optarg, "lxt") == 0) wave_fmt = LXT; else fatal("invalid waveform format: %s", optarg); break; case 'S': opt_set_int("rt-stats", 1); break; case 'w': if (optarg == NULL) wave_fname = ""; else wave_fname = optarg; break; case 'd': opt_set_int("stop-delta", parse_int(optarg)); break; case 'i': wave_include_glob(optarg); break; case 'e': wave_exclude_glob(optarg); break; default: abort(); } } if (optind == argc) fatal("missing top-level unit name"); ident_t top = to_unit_name(argv[optind]); ident_t ename = ident_prefix(top, ident_new("elab"), '.'); tree_rd_ctx_t ctx; tree_t e = lib_get_ctx(lib_work(), ename, &ctx); if (e == NULL) fatal("%s not elaborated", istr(top)); else if (tree_kind(e) != T_ELAB) fatal("%s not suitable top level", istr(top)); if (wave_fname != NULL) { const char *name_map[] = { "LXT", "FST", "VCD" }; const char *ext_map[] = { "lxt", "fst", "vcd" }; char *tmp = NULL; if (*wave_fname == '\0') { tmp = xasprintf("%s.%s", argv[optind], ext_map[wave_fmt]); wave_fname = tmp; notef("writing %s waveform data to %s", name_map[wave_fmt], tmp); } wave_include_file(argv[optind]); switch (wave_fmt) { case LXT: lxt_init(wave_fname, e); break; case VCD: vcd_init(wave_fname, e); break; case FST: fst_init(wave_fname, e); break; } if (tmp != NULL) free(tmp); } if (mode == BATCH) rt_batch_exec(e, stop_time, ctx); else { bool master = slave_fork(); if (master) shell_run(e, ctx); else rt_slave_exec(e, ctx); } tree_read_end(ctx); return EXIT_SUCCESS; }
static int run(int argc, char **argv) { static struct option long_options[] = { { "trace", no_argument, 0, 't' }, { "batch", no_argument, 0, 'b' }, { "command", no_argument, 0, 'c' }, { "stop-time", required_argument, 0, 's' }, { "stats", no_argument, 0, 'S' }, { "wave", optional_argument, 0, 'w' }, { "stop-delta", required_argument, 0, 'd' }, { "format", required_argument, 0, 'f' }, { "include", required_argument, 0, 'i' }, { "exclude", required_argument, 0, 'e' }, { "exit-severity", required_argument, 0, 'x' }, #if ENABLE_VHPI { "load", required_argument, 0, 'l' }, { "vhpi-trace", no_argument, 0, 'T' }, #endif { 0, 0, 0, 0 } }; enum { BATCH, COMMAND } mode = BATCH; enum { LXT, FST, VCD} wave_fmt = FST; uint64_t stop_time = UINT64_MAX; const char *wave_fname = NULL; const char *vhpi_plugins = NULL; static bool have_run = false; if (have_run) fatal("multiple run commands are not supported"); have_run = true; const int next_cmd = scan_cmd(2, argc, argv); int c, index = 0; const char *spec = "bcw::l:"; while ((c = getopt_long(next_cmd, argv, spec, long_options, &index)) != -1) { switch (c) { case 0: // Set a flag break; case '?': fatal("unrecognised run option %s", argv[optind - 1]); case 't': opt_set_int("rt_trace_en", 1); break; case 'T': opt_set_int("vhpi_trace_en", 1); break; case 'b': mode = BATCH; break; case 'c': mode = COMMAND; break; case 's': stop_time = parse_time(optarg); break; case 'f': if (strcmp(optarg, "vcd") == 0) wave_fmt = VCD; else if (strcmp(optarg, "fst") == 0) wave_fmt = FST; else if (strcmp(optarg, "lxt") == 0) wave_fmt = LXT; else fatal("invalid waveform format: %s", optarg); break; case 'S': opt_set_int("rt-stats", 1); break; case 'w': if (optarg == NULL) wave_fname = ""; else wave_fname = optarg; break; case 'd': opt_set_int("stop-delta", parse_int(optarg)); break; case 'i': wave_include_glob(optarg); break; case 'e': wave_exclude_glob(optarg); break; case 'l': vhpi_plugins = optarg; break; case 'x': rt_set_exit_severity(parse_severity(optarg)); break; default: abort(); } } set_top_level(argv, next_cmd); ident_t ename = ident_prefix(top_level, ident_new("elab"), '.'); tree_rd_ctx_t ctx; tree_t e = lib_get_ctx(lib_work(), ename, &ctx); if (e == NULL) fatal("%s not elaborated", istr(top_level)); else if (tree_kind(e) != T_ELAB) fatal("%s not suitable top level", istr(top_level)); if (wave_fname != NULL) { const char *name_map[] = { "LXT", "FST", "VCD" }; const char *ext_map[] = { "lxt", "fst", "vcd" }; char *tmp LOCAL = NULL; if (*wave_fname == '\0') { tmp = xasprintf("%s.%s", argv[optind], ext_map[wave_fmt]); wave_fname = tmp; notef("writing %s waveform data to %s", name_map[wave_fmt], tmp); } wave_include_file(argv[optind]); switch (wave_fmt) { case LXT: lxt_init(wave_fname, e); break; case VCD: vcd_init(wave_fname, e); break; case FST: fst_init(wave_fname, e); break; } } rt_start_of_tool(e, ctx); if (vhpi_plugins != NULL) vhpi_load_plugins(e, vhpi_plugins); rt_restart(e); if (mode == COMMAND) shell_run(e, ctx); else rt_run_sim(stop_time); rt_end_of_tool(e); tree_read_end(ctx); argc -= next_cmd - 1; argv += next_cmd - 1; return argc > 1 ? process_command(argc, argv) : EXIT_SUCCESS; }
static void teardown(void) { lib_free(lib_work()); }
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; }
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; }