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 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; }
END_TEST START_TEST(test_copy1) { input_from_file(TESTDIR "/elab/copy1.vhd"); const error_t expect[] = { { -1, NULL } }; expect_errors(expect); tree_t e = run_elab(); int nfuncs = 0, nshared = 0; const int ndecls = tree_decls(e); for (int i = 0; i < ndecls; i++) { tree_t t = tree_decl(e, i); if (tree_kind(t) == T_FUNC_BODY) nfuncs++; else if (tree_kind(t) == T_VAR_DECL) nshared++; } fail_unless(nfuncs == 1); fail_unless(nshared == 2); }
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"); }
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); }
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); }
void fst_restart(void) { if (fst_ctx == NULL) return; const int ndecls = tree_decls(fst_top); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(fst_top, i); switch (tree_kind(d)) { case T_SIGNAL_DECL: if (wave_should_dump(d)) fst_process_signal(d); break; case T_HIER: fst_process_hier(d); break; default: break; } int npop = tree_attr_int(d, ident_new("scope_pop"), 0); while (npop-- > 0) fstWriterSetUpscope(fst_ctx); } last_time = UINT64_MAX; for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(fst_top, i); if (tree_kind(d) == T_SIGNAL_DECL) { fst_data_t *data = tree_attr_ptr(d, fst_data_i); if (likely(data != NULL)) fst_event_cb(0, d, data->watch, data); } } }
void lxt_restart(void) { if (trace == NULL) return; lt_set_timescale(trace, -15); lt_symbol_bracket_stripping(trace, 0); lt_set_clock_compress(trace); const int ndecls = tree_decls(lxt_top); for (int i = 0; i < ndecls; i++) { tree_t d = tree_decl(lxt_top, i); if (tree_kind(d) != T_SIGNAL_DECL) continue; else if (!wave_should_dump(d)) continue; type_t type = tree_type(d); int rows, msb, lsb; if (type_is_array(type)) { rows = type_dims(type) - 1; if ((rows > 0) || type_is_array(type_elem(type))) { warn_at(tree_loc(d), "cannot emit arrays of greater than one " "dimension or arrays of arrays in LXT yet"); continue; } range_t r = type_dim(type, 0); msb = assume_int(r.left); lsb = assume_int(r.right); } else { rows = 0; msb = lsb = -1; } lxt_data_t *data = xmalloc(sizeof(lxt_data_t)); memset(data, '\0', sizeof(lxt_data_t)); int flags = 0; if (type_is_array(type)) { // Only arrays of CHARACTER, BIT, STD_ULOGIC are supported type_t elem = type_base_recur(type_elem(type)); if ((type_kind(elem) != T_ENUM) || !lxt_can_fmt_enum_chars(elem, data, &flags)) { warn_at(tree_loc(d), "cannot represent arrays of type %s " "in LXT format", type_pp(elem)); free(data); continue; } data->dir = type_dim(type, 0).kind; } else { type_t base = type_base_recur(type); switch (type_kind(base)) { case T_INTEGER: data->fmt = lxt_fmt_int; flags = LT_SYM_F_INTEGER; break; case T_ENUM: if (!lxt_can_fmt_enum_chars(base, data, &flags)) { data->fmt = lxt_fmt_enum; flags = LT_SYM_F_STRING; } break; default: warn_at(tree_loc(d), "cannot represent type %s in LXT format", type_pp(type)); free(data); continue; } } char *name = lxt_fmt_name(d); data->sym = lt_symbol_add(trace, name, rows, msb, lsb, flags); free(name); tree_add_attr_ptr(d, lxt_data_i, data); watch_t *w = rt_set_event_cb(d, lxt_event_cb, data, true); (*data->fmt)(d, w, data); } last_time = (lxttime_t)-1; }
static int shell_cmd_signals(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { const char *help = "signals - Find signal objects in the design\n" "\n" "Usage: signals [GLOB]\n" "\n" "Returns a list of signal names. Pass to `show' to see current values\n" "and types. GLOB is either the fully qualified name of a signal; a\n" "pattern containing a wildcard character '*'; or an unqualified name\n" "without the hierarchy separator ':' which matches that name at any\n" "level.\n" "\n" "Examples:\n" " signals List of all signal objects\n" " signals {*foo*} Find signals containing `foo'\n" " signals {*:clk} Find signals named `clk' at any level\n" " signals {clk} Equivalent to the above\n" " show [signals] Display current value of all signals\n"; if (show_help(objc, objv, help)) return TCL_OK; tree_t top = cd; const int ndecls = tree_decls(top); Tcl_Obj *result = Tcl_NewListObj(0, NULL); if (objc == 1) { for (int j = 0; j < ndecls; j++) { tree_t d = tree_decl(top, j); if (tree_kind(d) != T_SIGNAL_DECL) continue; Tcl_Obj *obj = Tcl_NewStringObj(istr(tree_ident(d)), -1); Tcl_ListObjAppendElement(interp, result, obj); } } else { for (int i = 1; i < objc; i++) { const char *glob = Tcl_GetString(objv[i]); char *expand = NULL; if ((*glob != ':') && (*glob != '*')) { const size_t sz = strlen(glob) + 3; expand = xmalloc(sz); checked_sprintf(expand, sz, "*:%s", glob); glob = expand; } for (int j = 0; j < ndecls; j++) { tree_t d = tree_decl(top, j); if (tree_kind(d) != T_SIGNAL_DECL) continue; ident_t name = tree_ident(d); if (ident_glob(name, glob, -1)) { Tcl_Obj *obj = Tcl_NewStringObj(istr(name), -1); Tcl_ListObjAppendElement(interp, result, obj); } } if (expand != NULL) free(expand); } } Tcl_SetObjResult(interp, result); return TCL_OK; }