static bool fst_can_fmt_chars(type_t type, fst_data_t *data, enum fstVarType *vt, enum fstSupplementalDataType *sdt) { type_t base = type_base_recur(type); ident_t name = type_ident(base); if (name == std_ulogic_i) { if (type_ident(type) == std_logic_i) *sdt = (data->size > 1) ? FST_SDT_VHDL_STD_LOGIC_VECTOR : FST_SDT_VHDL_STD_LOGIC; else *sdt = (data->size > 1) ? FST_SDT_VHDL_STD_ULOGIC_VECTOR : FST_SDT_VHDL_STD_ULOGIC; *vt = FST_VT_SV_LOGIC; data->fmt = fst_fmt_chars; data->type.map = "UX01ZWLH-"; return true; } else if (name == std_bit_i) { *sdt = FST_SDT_VHDL_BIT; *vt = FST_VT_SV_LOGIC; data->fmt = fst_fmt_chars; data->type.map = "01"; return true; } else if ((name == std_char_i) && (data->size > 0)) { *sdt = FST_SDT_VHDL_STRING; *vt = FST_VT_GEN_STRING; data->fmt = fst_fmt_chars; data->type.map = NULL; return true; } else return 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; } }
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; }
static bool vcd_can_fmt_chars(type_t type, vcd_data_t *data) { type_t base = type_base_recur(type); ident_t name = type_ident(base); if (name == std_ulogic_i) { data->fmt = vcd_fmt_chars; data->map = "xx01zx01x"; return true; } else if (name == std_bit_i) { data->fmt = vcd_fmt_chars; data->map = "01"; return true; } else return false; }
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); }
unsigned array_dimension(type_t a) { return (type_is_unconstrained(a) ? type_index_constrs(type_base_recur(a)) : type_dims(a)); }
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__); } }
bool parse_value(type_t type, const char *str, int64_t *value) { while (isspace((int)*str)) ++str; switch (type_kind(type_base_recur(type))) { case T_INTEGER: { int64_t sum = 0; while (isdigit((int)*str) || (*str == '_')) { if (*str != '_') { sum *= 10; sum += (*str - '0'); } ++str; } *value = sum; } break; case T_ENUM: { bool upcase = true; char *copy = strdup(str), *p; for (p = copy; (*p != '\0') && !isspace((int)*p); p++, str++) { if (*p == '\'') upcase = false; if (upcase) *p = toupper((int)*p); } *p = '\0'; ident_t id = ident_new(copy); free(copy); *value = -1; const int nlits = type_enum_literals(type); for (int i = 0; (*value == -1) && (i < nlits); i++) { if (tree_ident(type_enum_literal(type, i)) == id) *value = i; } if (*value == -1) return false; } break; default: break; } while (*str != '\0') { if (!isspace((int)*str)) { str++; return false; } else { str++; } } return true; }
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); } }