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; }
const char *type_pp_minify(type_t t, minify_fn_t fn) { assert(t != NULL); switch (type_kind(t)) { case T_FUNC: case T_PROC: { char *buf = get_fmt_buf(256); static_printf_begin(buf, 256); const char *fname = (*fn)(istr(type_ident(t))); static_printf(buf, "%s(", fname); const int nparams = type_params(t); for (int i = 0; i < nparams; i++) static_printf(buf, "%s%s", (i == 0 ? "" : ", "), (*fn)(istr(type_ident(type_param(t, i))))); static_printf(buf, ")"); if (type_kind(t) == T_FUNC) static_printf(buf, " return %s", (*fn)(istr(type_ident(type_result(t))))); return buf; } default: return (*fn)(istr(type_ident(t))); } }
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; } }
ident_t type_ident(type_t t) { assert(t != NULL); if (t->ident == NULL) { char *buf; switch (t->kind) { case T_SUBTYPE: return type_ident(type_base(t)); case T_ACCESS: buf = xasprintf("access to %s", istr(type_ident(type_access(t)))); break; case T_NONE: buf = xasprintf("none"); break; default: assert(false); } ident_t ident = ident_new(buf); free(buf); return ident; } else return t->ident; }
void type_write(type_t t, type_wr_ctx_t ctx) { fbuf_t *f = tree_write_file(ctx->tree_ctx); if (t == NULL) { write_u16(UINT16_C(0xffff), f); // Null marker return; } if (t->generation == ctx->generation) { // Already visited this type write_u16(UINT16_C(0xfffe), f); // Back reference marker write_u32(t->index, f); return; } t->generation = ctx->generation; t->index = (ctx->n_types)++; write_u16(t->kind, f); // Call type_ident here to generate an arbitrary name if needed ident_write(type_ident(t), ctx->ident_ctx); const uint32_t has = has_map[t->kind]; const int nitems = __builtin_popcount(has); uint32_t mask = 1; for (int n = 0; n < nitems; mask <<= 1) { if (has & mask) { if (ITEM_TYPE_ARRAY & mask) { type_array_t *a = &(t->items[n].type_array); write_u16(a->count, f); for (unsigned i = 0; i < a->count; i++) type_write(a->items[i], ctx); } else if (ITEM_TYPE & mask) type_write(t->items[n].type, ctx); else if (ITEM_TREE & mask) tree_write(t->items[n].tree, ctx->tree_ctx); else if (ITEM_TREE_ARRAY & mask) { tree_array_t *a = &(t->items[n].tree_array); write_u16(a->count, f); for (unsigned i = 0; i < a->count; i++) tree_write(a->items[i], ctx->tree_ctx); } else if (ITEM_RANGE_ARRAY & mask) { range_array_t *a = &(t->items[n].range_array); write_u16(a->count, f); for (unsigned i = 0; i < a->count; i++) { write_u8(a->items[i].kind, f); tree_write(a->items[i].left, ctx->tree_ctx); tree_write(a->items[i].right, ctx->tree_ctx); } } else item_without_type(mask); n++; } } }
bool folded_bool(tree_t t, bool *b) { if (tree_kind(t) == T_REF) { tree_t decl = tree_ref(t); if (tree_kind(decl) == T_ENUM_LIT && type_ident(tree_type(decl)) == std_bool_i) { *b = (tree_pos(decl) == 1); return true; } } return false; }
bool folded_bool(tree_t t, bool *b) { ident_t std_bool_i = ident_new("STD.STANDARD.BOOLEAN"); if (tree_kind(t) == T_REF) { tree_t decl = tree_ref(t); if (tree_kind(decl) == T_ENUM_LIT && type_ident(tree_type(decl)) == std_bool_i) { *b = (tree_pos(decl) == 1); return true; } } return false; }
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; }
static bool lxt_can_fmt_enum_chars(type_t type, lxt_data_t *data, int *flags) { ident_t name = type_ident(type); if (icmp(name, "IEEE.STD_LOGIC_1164.STD_ULOGIC")) { data->fmt = lxt_fmt_chars; data->map = std_logic_map; *flags = LT_SYM_F_BITS; return true; } else if (icmp(name, "STD.STANDARD.BIT")) { data->fmt = lxt_fmt_chars; data->map = bit_map; *flags = LT_SYM_F_BITS; return true; } else if (icmp(name, "STD.STANDARD.CHARACTER")) { data->fmt = lxt_fmt_chars; data->map = NULL; *flags = LT_SYM_F_STRING; return true; } else return false; }
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); }
bool type_eq(type_t a, type_t b) { assert(a != NULL); assert(b != NULL); type_kind_t kind_a = type_kind(a); type_kind_t kind_b = type_kind(b); if ((kind_a == T_UNRESOLVED) || (kind_b == T_UNRESOLVED)) return false; if (a == b) return true; // Subtypes are convertible to the base type while ((kind_a = type_kind(a)) == T_SUBTYPE) a = type_base(a); while ((kind_b = type_kind(b)) == T_SUBTYPE) b = type_base(b); const bool compare_c_u_arrays = (kind_a == T_CARRAY && kind_b == T_UARRAY) || (kind_a == T_UARRAY && kind_b == T_CARRAY); if ((kind_a != kind_b) && !compare_c_u_arrays) return false; // Universal integer type is equal to any other integer type type_t universal_int = type_universal_int(); ident_t uint_i = type_ident(universal_int); if (kind_a == T_INTEGER && (type_ident(a) == uint_i || type_ident(b) == uint_i)) return true; // Universal real type is equal to any other real type type_t universal_real = type_universal_real(); ident_t ureal_i = type_ident(universal_real); if (kind_a == T_REAL && (type_ident(a) == ureal_i || type_ident(b) == ureal_i)) return true; // XXX: this is not quite right as structurally equivalent types // may be declared in different scopes with the same name but // shouldn't compare equal if (type_ident(a) != type_ident(b)) return false; // Access types are equal if the pointed to type is the same if (kind_a == T_ACCESS) return type_eq(type_access(a), type_access(b)); if (compare_c_u_arrays) return type_eq(type_elem(a), type_elem(b)); const imask_t has = has_map[a->kind]; if ((has & I_DIMS) && (type_dims(a) != type_dims(b))) return false; if (type_kind(a) == T_FUNC) { if (!type_eq(type_result(a), type_result(b))) return false; } if (has & I_PARAMS) { if (type_params(a) != type_params(b)) return false; const int nparams = type_params(a); for (int i = 0; i < nparams; i++) { if (!type_eq(type_param(a, i), type_param(b, i))) return false; } } return true; }