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; }
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; }
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 find_arch(ident_t name, int kind, void *context) { lib_search_params_t *params = context; ident_t prefix = ident_until(name, '-'); if ((kind == T_ARCH) && (prefix == params->name)) { tree_t t = lib_get_check_stale(params->lib, name); assert(t != NULL); if (*(params->tree) == NULL) *(params->tree) = t; else { lib_mtime_t old_mtime = lib_mtime(params->lib, tree_ident(*(params->tree))); lib_mtime_t new_mtime = lib_mtime(params->lib, tree_ident(t)); if (new_mtime == old_mtime) { // Analysed at the same time: compare line number // Note this assumes both architectures are from the same // file but this shouldn't be a problem with high-resolution // timestamps uint16_t new_line = tree_loc(t)->first_line; uint16_t old_line = tree_loc(*(params->tree))->first_line; if (new_line > old_line) *(params->tree) = t; } else if (new_mtime > old_mtime) *(params->tree) = t; } } }
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; }
static bool link_find_native_library(lib_t lib, tree_t unit, FILE *deps) { #ifdef ENABLE_NATIVE ident_t name = tree_ident(unit); char *so_name = xasprintf("_%s.so", istr(name)); lib_mtime_t so_mt; if (!lib_stat(lib, so_name, &so_mt)) { free(so_name); return false; } lib_mtime_t unit_mt = lib_mtime(lib, name); if (unit_mt > so_mt) { warnf("unit %s has stale native shared library", istr(name)); free(so_name); return false; } if (deps != NULL) { char path[PATH_MAX]; lib_realpath(lib, so_name, path, sizeof(path)); fprintf(deps, "%s\n", path); } free(so_name); return true; #else // ENABLE_NATIVE return false; #endif // ENABLE_NATIVE }
static void link_context_bc_fn(lib_t lib, tree_t unit, FILE *deps) { if (!link_find_native_library(lib, unit, deps)) { link_arg_bc(lib, tree_ident(unit)); n_linked_bc++; } }
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 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))); }
static void event_watch(event_watch_msg_t *event, tree_rd_ctx_t ctx) { tree_t decl = tree_read_recall(ctx, event->index); printf("%s: update %s ", event->now_text, istr(tree_ident(decl))); printf("%s -> ", pprint(decl, &(event->last), 1)); printf("%s\n", pprint(decl, &(event->value), 1)); }
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; }
void shell_run(tree_t e, struct tree_rd_ctx *ctx) { const int ndecls = tree_decls(e); hash_t *decl_hash = hash_new(ndecls * 2, true); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(e, i); hash_put(decl_hash, tree_ident(d), d); } Tcl_Interp *interp = Tcl_CreateInterp(); bool have_quit = false; Tcl_CreateExitHandler(shell_exit_handler, &have_quit); shell_cmd_t shell_cmds[] = { CMD(quit, &have_quit, "Exit simulation"), CMD(run, ctx, "Start or resume simulation"), CMD(restart, NULL, "Restart simulation"), CMD(show, decl_hash, "Display simulation objects"), CMD(help, shell_cmds, "Display this message"), CMD(copyright, NULL, "Display copyright information"), CMD(signals, e, "Find signal objects in the design"), CMD(now, NULL, "Display current simulation time"), CMD(watch, decl_hash, "Trace changes to a signal"), CMD(unwatch, decl_hash, "Stop tracing signals"), { NULL, NULL, NULL, NULL} }; qsort(shell_cmds, ARRAY_LEN(shell_cmds) - 1, sizeof(shell_cmd_t), compare_shell_cmd); for (shell_cmd_t *c = shell_cmds; c->name != NULL; c++) Tcl_CreateObjCommand(interp, c->name, c->fn, c->cd, NULL); show_banner(); slave_post_msg(SLAVE_RESTART, NULL, 0); char *line; while (!have_quit && (line = shell_get_line())) { switch (Tcl_Eval(interp, line)) { case TCL_OK: break; case TCL_ERROR: errorf("%s", Tcl_GetStringResult(interp)); break; default: assert(false); } free(line); } Tcl_Exit(EXIT_SUCCESS); }
static char *lxt_fmt_name(tree_t decl) { char *s = strdup(istr(tree_ident(decl)) + 1); for (char *p = s; *p != '\0'; p++) { if (*p == ':') *p = '.'; } return s; }
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)); }
static void elab_pseudo_context(tree_t out, tree_t src) { // Add a pseudo use clause for an entity or architecture so the // makefile generator can find the dependencies ident_t name = tree_ident(src); const int nctx = tree_contexts(out); for (int i = 0; i < nctx; i++) { tree_t c = tree_context(out, i); if (tree_kind(c) != T_USE) continue; else if (tree_ident(c) == name) return; } tree_t c = tree_new(T_USE); tree_set_ident(c, name); tree_add_context(out, c); }
static void event_watch(uint64_t now, tree_t decl, watch_t *w, void *user) { uint64_t value[1]; rt_watch_value(w, value, 1, false); uint64_t last[1]; rt_watch_value(w, last, 1, true); LOCAL_TEXT_BUF last_tb = pprint(decl, last, 1); LOCAL_TEXT_BUF now_tb = pprint(decl, value, 1); printf("%s: update %s %s -> %s\n", fmt_time(rt_now(NULL)), istr(tree_ident(decl)), tb_get(last_tb), tb_get(now_tb)); }
END_TEST START_TEST(test_issue19) { input_from_file(TESTDIR "/elab/issue19.vhd"); const error_t expect[] = { { -1, NULL } }; expect_errors(expect); tree_t e = run_elab(); tree_t tmp = NULL; const int ndecls = tree_decls(e); for (int i = 0; (i < ndecls) && (tmp == NULL); i++) { tree_t t = tree_decl(e, i); if (icmp(tree_ident(t), ":comp6:c1:tmp")) tmp = t; } fail_if(tmp == NULL); tree_t value = tree_value(tmp); fail_unless(tree_kind(value) == T_LITERAL); fail_unless(tree_ival(value) == 32); for (int i = 0; (i < ndecls) && (tmp == NULL); i++) { tree_t t = tree_decl(e, i); if (icmp(tree_ident(t), ":comp6:c1:tmp3")) tmp = t; } fail_if(tmp == NULL); value = tree_value(tmp); fail_unless(tree_kind(value) == T_LITERAL); fail_unless(tree_ival(value) == 32); }
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; }
static bool elab_have_context(tree_t unit, ident_t name) { const int ndest = tree_contexts(unit); for (int i = 0; i < ndest; i++) { tree_t c2 = tree_context(unit, i); if (tree_kind(c2) != T_USE) continue; if (tree_ident(c2) == name) return true; } return false; }
static fst_unit_t *fst_make_unit_map(type_t type) { type_t base = type_base_recur(type); const int nunits = type_units(base); fst_unit_t *map = xmalloc(nunits * sizeof(fst_unit_t)); for (int i = 0; i < nunits; i++) { tree_t unit = type_unit(base, nunits - 1 - i); map[i].mult = assume_int(tree_value(unit)); map[i].name = strdup(istr(tree_ident(unit))); } return map; }
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); }
static void elab_use_clause(tree_t use, const elab_ctx_t *ctx) { tree_set_ident2(use, all_i); ident_t name = tree_ident(use); ident_t lname = ident_until(name, '.'); elab_ctx_t new_ctx = *ctx; new_ctx.library = elab_find_lib(lname, ctx); if (name == lname) lib_walk_index(new_ctx.library, elab_context_walk_fn, &new_ctx); else if (!elab_have_context(ctx->out, name)) elab_add_context(use, &new_ctx); }
static void link_context(tree_t ctx, FILE *deps, context_fn_t fn) { ident_t cname = tree_ident(ctx); ident_t lname = ident_until(cname, '.'); lib_t lib = lib_find(istr(lname), true, true); if (lib == NULL) fatal("cannot link library %s", istr(lname)); if (lname == cname) { lib_walk_params_t params = { .lib = lib, .deps = deps, .fn = fn }; lib_walk_index(lib, link_walk_lib, ¶ms); }
void vcd_restart(void) { if (vcd_file == NULL) return; vcd_emit_header(); int next_key = 0; const int ndecls = tree_decls(vcd_top); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(vcd_top, i); switch (tree_kind(d)) { case T_HIER: fprintf(vcd_file, "$scope module %s $end\n", istr(tree_ident(d))); break; case T_SIGNAL_DECL: if (wave_should_dump(d)) vcd_process_signal(d, &next_key); break; default: break; } int npop = tree_attr_int(d, ident_new("scope_pop"), 0); while (npop-- > 0) fprintf(vcd_file, "$upscope $end\n"); } fprintf(vcd_file, "$enddefinitions $end\n"); fprintf(vcd_file, "$dumpvars\n"); last_time = UINT64_MAX; for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(vcd_top, i); if (tree_kind(d) == T_SIGNAL_DECL) { vcd_data_t *data = tree_attr_ptr(d, vcd_data_i); if (likely(data != NULL)) vcd_event_cb(0, d, data->watch, data); } } fprintf(vcd_file, "$end\n"); }
static void opt_tag_last_value_attr_ref(tree_t t) { static ident_t last_value_attr_i = NULL; if (last_value_attr_i == NULL) last_value_attr_i = ident_new("LAST_VALUE"); if (tree_ident(t) == last_value_attr_i) { tree_t signal = tree_ref(tree_name(t)); if (tree_kind(signal) != T_SIGNAL_DECL) return; // A signal in a package will not have nets assigned yet so we cannot // optimise out 'LAST_VALUE if (tree_nets(signal) > 0) tree_add_attr_int(signal, last_value_i, 1); } }
static ident_t elab_formal_name(tree_t t) { tree_kind_t kind; while ((kind = tree_kind(t)) != T_REF) { switch (kind) { case T_ARRAY_REF: case T_ARRAY_SLICE: t = tree_value(t); break; default: fatal_at(tree_loc(t), "sorry, this kind of formal is not supported %s", tree_kind_str(kind)); } } return tree_ident(t); }
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); }
tree_t str_to_literal(const char *start, const char *end, type_t type) { tree_t t = tree_new(T_LITERAL); tree_set_subkind(t, L_STRING); type_t elem = NULL; if (type != NULL) { tree_set_type(t, type); elem = type_elem(type); } char last = '\0'; for (const char *p = start; *p != '\0' && p != end; p++) { if (*p == -127) continue; else if (*p == '"' && last == '"') { last = '\0'; continue; } else last = *p; const char ch[] = { '\'', *p, '\'', '\0' }; ident_t id = ident_new(ch); tree_t ref = tree_new(T_REF); tree_set_ident(ref, id); tree_add_char(t, ref); if (elem != NULL) { const int nlit = type_enum_literals(elem); for (int i = 0; i < nlit; i++) { tree_t lit = type_enum_literal(elem, i); if (tree_ident(lit) == id) { tree_set_ref(ref, lit); break; } } } } return t; }
static void elab_copy_context(tree_t src, const elab_ctx_t *ctx) { const int nsrc = tree_contexts(src); for (int i = 0; i < nsrc; i++) { tree_t c = tree_context(src, i); if (tree_kind(c) != T_USE) continue; tree_set_ident2(c, all_i); ident_t name = tree_ident(c); ident_t lname = ident_until(name, '.'); elab_ctx_t new_ctx = *ctx; new_ctx.library = elab_find_lib(lname, ctx); if (name == lname) lib_walk_index(new_ctx.library, elab_context_walk_fn, &new_ctx); else if (!elab_have_context(ctx->out, name)) elab_add_context(c, &new_ctx); } }
static void fst_process_hier(tree_t h) { const tree_kind_t scope_kind = tree_subkind(h); enum fstScopeType st; switch (scope_kind) { case T_ARCH: st = FST_ST_VHDL_ARCHITECTURE; break; case T_BLOCK: st = FST_ST_VHDL_BLOCK; break; case T_FOR_GENERATE: st = FST_ST_VHDL_FOR_GENERATE; break; case T_PACKAGE: st = FST_ST_VHDL_PACKAGE; break; default: st = FST_ST_VHDL_ARCHITECTURE; warn_at(tree_loc(h), "no FST scope type for %s", tree_kind_str(scope_kind)); break; } const loc_t *loc = tree_loc(h); fstWriterSetSourceStem(fst_ctx, loc->file, loc->first_line, 1); fstWriterSetScope(fst_ctx, st, istr(tree_ident(h)), tree_has_ident2(h) ? istr(tree_ident2(h)) : ""); }