type_t array_aggregate_type(type_t array, int from_dim) { if (type_is_unconstrained(array)) { const int nindex = type_index_constrs(array); assert(from_dim < nindex); type_t type = type_new(T_UARRAY); type_set_ident(type, type_ident(array)); type_set_elem(type, type_elem(array)); for (int i = from_dim; i < nindex; i++) type_add_index_constr(type, type_index_constr(array, i)); return type; } else { const int ndims = type_dims(array); assert(from_dim < ndims); type_t type = type_new(T_CARRAY); type_set_ident(type, type_ident(array)); type_set_elem(type, type_elem(array)); for (int i = from_dim; i < ndims; i++) type_add_dim(type, type_dim(array, i)); return type; } }
void type_replace(type_t t, type_t a) { assert(t != NULL); assert(IS(t, T_INCOMPLETE)); t->kind = a->kind; t->ident = a->ident; const imask_t has = has_map[t->kind]; if (has & I_DIMS) { const int ndims = type_dims(a); for (int i = 0; i < ndims; i++) type_add_dim(t, type_dim(a, i)); } switch (a->kind) { case T_UARRAY: for (unsigned i = 0; i < type_index_constrs(a); i++) type_add_index_constr(t, type_index_constr(a, i)); // Fall-through case T_CARRAY: type_set_elem(t, type_elem(a)); break; case T_SUBTYPE: type_set_base(t, type_base(a)); break; case T_FUNC: type_set_result(t, type_result(a)); break; case T_INTEGER: case T_REAL: break; case T_ENUM: for (unsigned i = 0; i < type_enum_literals(a); i++) type_enum_add_literal(t, type_enum_literal(a, i)); break; case T_RECORD: for (unsigned i = 0; i < type_fields(a); i++) type_add_field(t, type_field(a, i)); break; default: assert(false); } }
type_t index_type_of(type_t type, int dim) { if (type_is_unconstrained(type)) return type_index_constr(type_base_recur(type), dim); else if (type_kind(type) == T_ENUM) return type; else { tree_t left = type_dim(type, dim).left; // If the left bound has not been assigned a type then there is some // error with it so just return a dummy type here return tree_has_type(left) ? tree_type(left) : type; } }
unsigned type_width(type_t type) { if (type_is_array(type)) { const unsigned elem_w = type_width(type_elem(type)); unsigned w = 1; const int ndims = type_dims(type); for (int i = 0; i < ndims; i++) { int64_t low, high; range_bounds(type_dim(type, i), &low, &high); w *= MAX(high - low + 1, 0) * elem_w; } return w; } else if (type_is_record(type)) { type_t base = type_base_recur(type); unsigned w = 0; const int nfields = type_fields(base); for (int i = 0; i < nfields; i++) w += type_width(tree_type(type_field(base, i))); return w; } else return 1; }
static void vcd_process_signal(tree_t d, int *next_key) { type_t type = tree_type(d); type_t base = type_base_recur(type); vcd_data_t *data = xmalloc(sizeof(vcd_data_t)); memset(data, '\0', sizeof(vcd_data_t)); int msb = 0, lsb = 0; if (type_is_array(type)) { if (type_dims(type) > 1) { warn_at(tree_loc(d), "cannot represent multidimensional arrays " "in VCD format"); free(data); return; } range_t r = type_dim(type, 0); int64_t low, high; range_bounds(r, &low, &high); data->dir = r.kind; data->size = high - low + 1; msb = assume_int(r.left); lsb = assume_int(r.right); type_t elem = type_elem(type); if (!vcd_can_fmt_chars(elem, data)) { warn_at(tree_loc(d), "cannot represent arrays of type %s " "in VCD format", type_pp(elem)); free(data); return; } } else { switch (type_kind(base)) { case T_INTEGER: { int64_t low, high; range_bounds(type_dim(type, 0), &low, &high); data->size = ilog2(high - low + 1); data->fmt = vcd_fmt_int; } break; case T_ENUM: if (vcd_can_fmt_chars(type, data)) { data->size = 1; break; } // Fall-through default: warn_at(tree_loc(d), "cannot represent type %s in VCD format", type_pp(type)); free(data); return; } } const char *name_base = strrchr(istr(tree_ident(d)), ':') + 1; const size_t base_len = strlen(name_base); char name[base_len + 64]; strncpy(name, name_base, base_len + 64); if (type_is_array(type)) snprintf(name + base_len, 64, "[%d:%d]\n", msb, lsb); tree_add_attr_ptr(d, vcd_data_i, data); data->watch = rt_set_event_cb(d, vcd_event_cb, data, true); vcd_key_fmt(*next_key, data->key); fprintf(vcd_file, "$var reg %d %s %s $end\n", (int)data->size, data->key, name); ++(*next_key); }
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 void fst_process_signal(tree_t d) { type_t type = tree_type(d); type_t base = type_base_recur(type); fst_data_t *data = xmalloc(sizeof(fst_data_t)); memset(data, '\0', sizeof(fst_data_t)); int msb = 0, lsb = 0; enum fstVarType vt; enum fstSupplementalDataType sdt; if (type_is_array(type)) { if (type_dims(type) > 1) { warn_at(tree_loc(d), "cannot represent multidimensional arrays " "in FST format"); free(data); return; } range_t r = type_dim(type, 0); int64_t low, high; range_bounds(r, &low, &high); data->dir = r.kind; data->size = high - low + 1; msb = assume_int(r.left); lsb = assume_int(r.right); type_t elem = type_elem(type); if (!fst_can_fmt_chars(elem, data, &vt, &sdt)) { warn_at(tree_loc(d), "cannot represent arrays of type %s " "in FST format", type_pp(elem)); free(data); return; } else { ident_t ident = type_ident(base); if (ident == unsigned_i) sdt = FST_SDT_VHDL_UNSIGNED; else if (ident == signed_i) sdt = FST_SDT_VHDL_SIGNED; } } else { switch (type_kind(base)) { case T_INTEGER: { ident_t ident = type_ident(type); if (ident == natural_i) sdt = FST_SDT_VHDL_NATURAL; else if (ident == positive_i) sdt = FST_SDT_VHDL_POSITIVE; else sdt = FST_SDT_VHDL_INTEGER; int64_t low, high; range_bounds(type_dim(type, 0), &low, &high); vt = FST_VT_VCD_INTEGER; data->size = ilog2(high - low + 1); data->fmt = fst_fmt_int; } break; case T_ENUM: if (!fst_can_fmt_chars(type, data, &vt, &sdt)) { ident_t ident = type_ident(base); if (ident == std_bool_i) sdt = FST_SDT_VHDL_BOOLEAN; else if (ident == std_char_i) sdt = FST_SDT_VHDL_CHARACTER; else sdt = FST_SDT_NONE; vt = FST_VT_GEN_STRING; data->size = 0; data->fmt = fst_fmt_enum; } else data->size = 1; break; case T_PHYSICAL: { sdt = FST_SDT_NONE; vt = FST_VT_GEN_STRING; data->size = 0; data->type.units = fst_make_unit_map(type); data->fmt = fst_fmt_physical; } break; default: warn_at(tree_loc(d), "cannot represent type %s in FST format", type_pp(type)); free(data); return; } } enum fstVarDir dir = FST_VD_IMPLICIT; switch (tree_attr_int(d, fst_dir_i, -1)) { case PORT_IN: dir = FST_VD_INPUT; break; case PORT_OUT: dir = FST_VD_OUTPUT; break; case PORT_INOUT: dir = FST_VD_INOUT; break; case PORT_BUFFER: dir = FST_VD_BUFFER; break; } const char *name_base = strrchr(istr(tree_ident(d)), ':') + 1; const size_t base_len = strlen(name_base); char name[base_len + 64]; strncpy(name, name_base, base_len + 64); if (type_is_array(type)) snprintf(name + base_len, 64, "[%d:%d]\n", msb, lsb); data->handle = fstWriterCreateVar2( fst_ctx, vt, dir, data->size, name, 0, type_pp(type), FST_SVT_VHDL_SIGNAL, sdt); tree_add_attr_ptr(d, fst_data_i, data); data->watch = rt_set_event_cb(d, fst_event_cb, data, true); }
static int shell_cmd_show(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { const char *help = "show - Display simulation objects\n" "\n" "Usage: show LIST...\n" "\n" "Prints a representation of each simulation object in LIST. Typically\n" "this will be a list of signal names and the output will show their\n" "current value.\n" "\n" "Examples:\n" " show {:top:foo} Print value of signal :top_foo\n" " show [signals] Print value of all signals\n"; if (show_help(objc, objv, help)) return TCL_OK; if (objc == 1) { warnf("nothing to show (try -help for usage)"); return TCL_OK; } hash_t *decl_hash = (hash_t *)cd; for (int i = 1; i < objc; i++) { int length; if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK) return TCL_ERROR; for (int j = 0; j < length; j++) { Tcl_Obj *obj; if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK) return TCL_ERROR; const char *str = Tcl_GetString(obj); tree_t t = hash_get(decl_hash, ident_new(str)); if (t == NULL) return tcl_error(interp, "object not found: %s", str); tree_kind_t kind = tree_kind(t); switch (kind) { case T_SIGNAL_DECL: { size_t len = 1; type_t type = tree_type(t); while (type_is_array(type)) { int64_t low = 0, high = 0; range_bounds(type_dim(type, 0), &low, &high); len *= (high - low + 1); type = type_elem(type); } slave_read_signal_msg_t msg = { .index = tree_index(t), .len = len }; slave_post_msg(SLAVE_READ_SIGNAL, &msg, sizeof(msg)); const size_t rsz = sizeof(reply_read_signal_msg_t) + (msg.len * sizeof(uint64_t)); reply_read_signal_msg_t *reply = xmalloc(rsz); slave_get_reply(REPLY_READ_SIGNAL, reply, rsz); const char *type_str = type_pp(type); const char *short_name = strrchr(type_str, '.'); printf("%-30s%-20s%s\n", str, (short_name != NULL ? short_name + 1 : type_str), pprint(t, reply->values, msg.len)); free(reply); } break; default: return tcl_error(interp, "cannot show tree kind %s", tree_kind_str(kind)); } } } return TCL_OK; }
int64_t rebase_index(type_t array_type, int dim, int64_t value) { range_t r = type_dim(array_type, dim); const int64_t left = assume_int(r.left); return (r.kind == RANGE_TO) ? value - left : left - value; }
tree_t make_default_value(type_t type, const loc_t *loc) { type_t base = type_base_recur(type); switch (type_kind(base)) { case T_UARRAY: assert(type_kind(type) == T_SUBTYPE); // Fall-through case T_CARRAY: { tree_t def = NULL; const int ndims = type_dims(type); for (int i = ndims - 1; i >= 0; i--) { tree_t val = (def ? def : make_default_value(type_elem(base), loc)); def = tree_new(T_AGGREGATE); tree_set_type(def, array_aggregate_type(type, i)); tree_t a = tree_new(T_ASSOC); tree_set_subkind(a, A_OTHERS); tree_set_value(a, val); tree_add_assoc(def, a); } tree_set_type(def, type); tree_set_loc(def, loc); return def; } case T_INTEGER: case T_PHYSICAL: case T_REAL: return type_dim(type, 0).left; case T_ENUM: { int64_t val = 0; const bool folded = folded_int(type_dim(type, 0).left, &val); if (folded) return make_ref(type_enum_literal(base, (unsigned) val)); else return type_dim(type, 0).left; } case T_RECORD: { tree_t def = tree_new(T_AGGREGATE); tree_set_loc(def, loc); const int nfields = type_fields(base); for (int i = 0; i < nfields; i++) { tree_t field = type_field(base, i); tree_t a = tree_new(T_ASSOC); tree_set_subkind(a, A_POS); tree_set_value(a, make_default_value(tree_type(field), tree_loc(field))); tree_add_assoc(def, a); } tree_set_type(def, type); return def; } case T_ACCESS: { tree_t null = tree_new(T_LITERAL); tree_set_loc(null, loc); tree_set_subkind(null, L_NULL); tree_set_type(null, type); return null; } case T_UNRESOLVED: return NULL; default: fatal_trace("cannot handle type %s in %s", type_kind_str(type_kind(base)), __func__); } }
tree_t make_default_value(type_t type, const loc_t *loc) { type_t base = type_base_recur(type); switch (type_kind(base)) { case T_UARRAY: assert(type_kind(type) == T_SUBTYPE); // Fall-through case T_CARRAY: { tree_t def = NULL; const int ndims = type_dims(type); for (int i = ndims - 1; i >= 0; i--) { tree_t val = (def ? def : make_default_value(type_elem(base), loc)); def = tree_new(T_AGGREGATE); tree_set_type(def, array_aggregate_type(type, i)); tree_t a = tree_new(T_ASSOC); tree_set_subkind(a, A_OTHERS); tree_set_value(a, val); tree_add_assoc(def, a); } tree_set_type(def, type); tree_set_loc(def, loc); return def; } case T_INTEGER: case T_PHYSICAL: case T_REAL: return type_dim(type, 0).left; case T_ENUM: return make_ref(type_enum_literal(base, 0)); case T_RECORD: { tree_t def = tree_new(T_AGGREGATE); tree_set_loc(def, loc); const int nfields = type_fields(base); for (int i = 0; i < nfields; i++) { tree_t field = type_field(base, i); tree_t a = tree_new(T_ASSOC); tree_set_subkind(a, A_POS); tree_set_value(a, make_default_value(tree_type(field), tree_loc(field))); tree_add_assoc(def, a); } tree_set_type(def, type); return def; } case T_ACCESS: { tree_t null = tree_new(T_LITERAL); tree_set_loc(null, loc); tree_set_subkind(null, L_NULL); tree_set_type(null, type); return null; } default: assert(false); } }