END_TEST START_TEST(test_prefix) { ident_t a, b, c, d, e, f; a = ident_new("foo"); b = ident_new("bar"); c = ident_prefix(a, b, '.'); fail_unless(c == ident_new("foo.bar")); fail_if(c == a); fail_if(c == b); d = ident_prefix(ident_prefix(c, c, '.'), ident_new("carrot"), '/'); fail_unless(d == ident_new("foo.bar.foo.bar/carrot")); fail_if(d == c); e = ident_prefix(NULL, a, '?'); fail_unless(e == a); f = ident_prefix(a, b, '\0'); fail_unless(f == ident_new("foobar")); }
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 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); }
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; } }
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 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 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; }
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 ident_t hpathf(ident_t path, char sep, const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *buf = xvasprintf(fmt, ap); va_end(ap); // LRM specifies instance path is lowercase char *p = buf; while (*p != '\0') { *p = tolower((int)*p); ++p; } ident_t id = ident_new(buf); free(buf); return ident_prefix(path, id, sep); }
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; }
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 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; }