/* GHDL Wavefile reader library. Copyright (C) 2005 Tristan Gingold GHDL is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GHDL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "ghwlib.h" /* Reopen H through decompressor DECOMP. */ static int ghw_openz (struct ghw_handler *h, const char *decomp, const char *filename) { int plen = strlen (decomp) + 1 + strlen(filename) + 1; char *p = malloc (plen); snprintf (p, plen, "%s %s", decomp, filename); fclose (h->stream); h->stream = popen(p, "r"); free (p); if (h->stream == NULL) return -1; h->stream_ispipe = 1; return 0; } int ghw_open (struct ghw_handler *h, const char *filename) { char hdr[16]; h->stream = fopen (filename, "rb"); if (h->stream == NULL) return -1; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; /* Check compression layer. */ if (!memcmp (hdr, "\x1f\x8b", 2)) { if (ghw_openz (h, "gzip -cd", filename) < 0) return -1; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; } else if (!memcmp (hdr, "BZ", 2)) { if (ghw_openz (h, "bzip2 -cd", filename) < 0) return -1; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; } else { h->stream_ispipe = 0; } /* Check magic. */ if (memcmp (hdr, "GHDLwave\n", 9) != 0) return -2; /* Check version. */ if (hdr[9] != 16 || hdr[10] != 0) return -2; h->version = hdr[11]; if (h->version > 1) return -3; if (hdr[12] == 1) h->word_be = 0; else if (hdr[12] == 2) h->word_be = 1; else return -4; #if 0 /* Endianness. */ { int endian; union { unsigned char b[4]; uint32_t i;} v; v.i = 0x11223344; if (v.b[0] == 0x11) endian = 2; else if (v.b[0] == 0x44) endian = 1; else return -3; if (hdr[12] != 1 && hdr[12] != 2) return -3; if (hdr[12] != endian) h->swap_word = 1; else h->swap_word = 0; } #endif h->word_len = hdr[13]; h->off_len = hdr[14]; if (hdr[15] != 0) return -5; h->hie = NULL; return 0; } int32_t ghw_get_i32 (struct ghw_handler *h, unsigned char *b) { if (h->word_be) return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); else return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); } int64_t ghw_get_i64 (struct ghw_handler *ghw_h, unsigned char *b) { int l, h; if (ghw_h->word_be) { h = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); l = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7] << 0); } else { l = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); h = (b[7] << 24) | (b[6] << 16) | (b[5] << 8) | (b[4] << 0); } return (((int64_t)h) << 32) | l; } int ghw_read_byte (struct ghw_handler *h, unsigned char *res) { int v; v = fgetc (h->stream); if (v == EOF) return -1; *res = v; return 0; } int ghw_read_uleb128 (struct ghw_handler *h, uint32_t *res) { uint32_t r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= (v & 0x7f) << off; if ((v & 0x80) == 0) break; off += 7; } *res = r; return 0; } int ghw_read_sleb128 (struct ghw_handler *h, int32_t *res) { int32_t r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= ((int32_t)(v & 0x7f)) << off; off += 7; if ((v & 0x80) == 0) { if ((v & 0x40) && off < 32) r |= -1 << off; break; } } *res = r; return 0; } int ghw_read_lsleb128 (struct ghw_handler *h, int64_t *res) { static const int64_t r_mask = -1; int64_t r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= ((int64_t)(v & 0x7f)) << off; off += 7; if ((v & 0x80) == 0) { if ((v & 0x40) && off < 64) r |= r_mask << off; break; } } *res = r; return 0; } int ghw_read_f64 (struct ghw_handler *h, double *res) { /* FIXME: handle byte order. */ if (fread (res, sizeof (*res), 1, h->stream) != 1) return -1; return 0; } const char * ghw_read_strid (struct ghw_handler *h) { uint32_t id; if (ghw_read_uleb128 (h, &id) != 0) return NULL; return h->str_table[id]; } union ghw_type * ghw_read_typeid (struct ghw_handler *h) { uint32_t id; if (ghw_read_uleb128 (h, &id) != 0) return NULL; return h->types[id - 1]; } union ghw_range * ghw_read_range (struct ghw_handler *h) { int t = fgetc (h->stream); if (t == EOF) return NULL; switch (t & 0x7f) { case ghdl_rtik_type_b2: { struct ghw_range_b2 *r; r = malloc (sizeof (struct ghw_range_b2)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_byte (h, &r->left) != 0) goto err_b2; if (ghw_read_byte (h, &r->right) != 0) goto err_b2; return (union ghw_range *)r; err_b2: free (r); return NULL; } case ghdl_rtik_type_e8: { struct ghw_range_e8 *r; r = malloc (sizeof (struct ghw_range_e8)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_byte (h, &r->left) != 0) goto err_e8; if (ghw_read_byte (h, &r->right) != 0) goto err_e8; return (union ghw_range *)r; err_e8: free (r); return NULL; } case ghdl_rtik_type_i32: case ghdl_rtik_type_p32: { struct ghw_range_i32 *r; r = malloc (sizeof (struct ghw_range_i32)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_sleb128 (h, &r->left) != 0) goto err_i32; if (ghw_read_sleb128 (h, &r->right) != 0) goto err_i32; return (union ghw_range *)r; err_i32: free (r); return NULL; } case ghdl_rtik_type_i64: case ghdl_rtik_type_p64: { struct ghw_range_i64 *r; r = malloc (sizeof (struct ghw_range_i64)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_lsleb128 (h, &r->left) != 0) goto err_i64; if (ghw_read_lsleb128 (h, &r->right) != 0) goto err_i64; return (union ghw_range *)r; err_i64: free (r); return NULL; } case ghdl_rtik_type_f64: { struct ghw_range_f64 *r; r = malloc (sizeof (struct ghw_range_f64)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_f64 (h, &r->left) != 0) goto err_f64; if (ghw_read_f64 (h, &r->right) != 0) goto err_f64; return (union ghw_range *)r; err_f64: free (r); return NULL; } default: fprintf (stderr, "ghw_read_range: type %d unhandled\n", t & 0x7f); return NULL; } } int ghw_read_str (struct ghw_handler *h) { unsigned char hdr[12]; unsigned i; char *p; int prev_len; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; h->nbr_str = ghw_get_i32 (h, &hdr[4]); h->nbr_str++; h->str_size = ghw_get_i32 (h, &hdr[8]); h->str_table = (char **)malloc ((h->nbr_str + 1) * sizeof (char *)); h->str_content = (char *)malloc (h->str_size + h->nbr_str + 1); if (h->flag_verbose) { printf ("Number of strings: %u\n", h->nbr_str - 1); printf ("String table size: %u\n", h->str_size); } h->str_table[0] = ""; p = h->str_content; prev_len = 0; for (i = 1; i < h->nbr_str; i++) { int j; int c; char *prev; int sh; h->str_table[i] = p; prev = h->str_table[i - 1]; for (j = 0; j < prev_len; j++) *p++ = prev[j]; while (1) { c = fgetc (h->stream); if (c == EOF) return -1; if ((c >= 0 && c <= 31) || (c >= 128 && c <= 159)) break; *p++ = c; } *p++ = 0; if (h->flag_verbose > 1) printf (" string %u (pl=%d): %s\n", i, prev_len, h->str_table[i]); prev_len = c & 0x1f; sh = 5; while (c >= 128) { c = fgetc (h->stream); if (c == EOF) return -1; prev_len |= (c & 0x1f) << sh; sh += 5; } } if (fread (hdr, 4, 1, h->stream) != 1) return -1; if (memcmp (hdr, "EOS", 4) != 0) return -1; return 0; } union ghw_type * ghw_get_base_type (union ghw_type *t) { switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: case ghdl_rtik_type_e32: case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: case ghdl_rtik_type_array: return t; case ghdl_rtik_subtype_scalar: return t->ss.base; case ghdl_rtik_subtype_array: return t->sa.base; case ghdl_rtik_subtype_unbounded_array: return t->sua.base; default: fprintf (stderr, "ghw_get_base_type: cannot handle type %d\n", t->kind); abort (); } } /* Return -1 for unbounded types. */ static int get_nbr_elements (union ghw_type *t) { switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: case ghdl_rtik_type_e32: case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: case ghdl_rtik_subtype_scalar: return 1; case ghdl_rtik_type_array: return -1; case ghdl_rtik_subtype_array: return t->sa.nbr_scalars; case ghdl_rtik_type_record: return t->rec.nbr_scalars; case ghdl_rtik_subtype_record: return t->sr.nbr_scalars; case ghdl_rtik_subtype_unbounded_record: case ghdl_rtik_subtype_unbounded_array: return -1; default: fprintf (stderr, "get_nbr_elements: unhandled type %d\n", t->kind); abort (); } } int ghw_get_range_length (union ghw_range *rng) { int res; assert (rng != NULL); switch (rng->kind) { case ghdl_rtik_type_i32: if (rng->i32.dir) res = rng->i32.left - rng->i32.right + 1; else res = rng->i32.right - rng->i32.left + 1; break; case ghdl_rtik_type_b2: if (rng->b2.dir) res = rng->b2.left - rng->b2.right + 1; else res = rng->b2.right - rng->b2.left + 1; break; case ghdl_rtik_type_e8: if (rng->e8.dir) res = rng->e8.left - rng->e8.right + 1; else res = rng->e8.right - rng->e8.left + 1; break; default: fprintf (stderr, "get_range_length: unhandled kind %d\n", rng->kind); abort (); } /* The length of a null range is 0. */ return (res <= 0) ? 0 : res; } static union ghw_type * ghw_read_type_bounds (struct ghw_handler *h, union ghw_type *base); /* Create an array subtype using BASE and ranges read from H. */ struct ghw_subtype_array * ghw_read_array_subtype (struct ghw_handler *h, union ghw_type *base) { struct ghw_type_array *arr = (struct ghw_type_array *)ghw_get_base_type (base); struct ghw_subtype_array *sa; unsigned j; int nbr_scalars; int nbr_els; sa = malloc (sizeof (struct ghw_subtype_array)); sa->kind = ghdl_rtik_subtype_array; sa->name = NULL; sa->base = base; nbr_els = get_nbr_elements (arr->el); nbr_scalars = 1; sa->rngs = malloc (arr->nbr_dim * sizeof (union ghw_range *)); for (j = 0; j < arr->nbr_dim; j++) { sa->rngs[j] = ghw_read_range (h); nbr_scalars *= ghw_get_range_length (sa->rngs[j]); } if (nbr_els >= 0) { /* Element type is bounded. */ sa->el = arr->el; } else { /* Read bounds for the elements. */ sa->el = ghw_read_type_bounds(h, arr->el); nbr_els = get_nbr_elements (sa->el); } sa->nbr_scalars = nbr_scalars * nbr_els; return sa; } struct ghw_subtype_record * ghw_read_record_subtype (struct ghw_handler *h, struct ghw_type_record *base) { struct ghw_subtype_record *sr; sr = malloc (sizeof (struct ghw_subtype_record)); sr->kind = ghdl_rtik_subtype_record; sr->name = NULL; sr->base = base; if (base->nbr_scalars >= 0) { /* Record base type is bounded. */ sr->nbr_scalars = base->nbr_scalars; sr->els = base->els; } else { /* Read subtypes. */ unsigned j; int nbr_scalars; sr->els = malloc (base->nbr_fields * sizeof (struct ghw_record_element)); nbr_scalars = 0; for (j = 0; j < base->nbr_fields; j++) { union ghw_type *btype = base->els[j].type; int el_nbr_scalars = get_nbr_elements (btype); sr->els[j].name = base->els[j].name; if (el_nbr_scalars >= 0) { /* Element is constrained. */ sr->els[j].type = btype; } else { sr->els[j].type = ghw_read_type_bounds(h, btype); el_nbr_scalars = get_nbr_elements (sr->els[j].type); } nbr_scalars += el_nbr_scalars; } sr->nbr_scalars = nbr_scalars; } return sr; } /* Read bounds for BASE and create a subtype. */ static union ghw_type * ghw_read_type_bounds (struct ghw_handler *h, union ghw_type *base) { switch (base->kind) { case ghdl_rtik_type_array: case ghdl_rtik_subtype_unbounded_array: return (union ghw_type *)ghw_read_array_subtype (h, base); break; case ghdl_rtik_type_record: case ghdl_rtik_subtype_unbounded_record: return (union ghw_type *)ghw_read_record_subtype (h, &base->rec); break; default: fprintf (stderr, "ghw_read_type_bounds: unhandled kind %d\n", base->kind); return NULL; } } int ghw_read_type (struct ghw_handler *h) { unsigned char hdr[8]; unsigned i; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; h->nbr_types = ghw_get_i32 (h, &hdr[4]); h->types = (union ghw_type **) malloc (h->nbr_types * sizeof (union ghw_type *)); for (i = 0; i < h->nbr_types; i++) { int t; t = fgetc (h->stream); if (t == EOF) return -1; if (h->flag_verbose > 2) printf ("type[%d]= %d\n", i, t); switch (t) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: { struct ghw_type_enum *e; unsigned j; e = malloc (sizeof (struct ghw_type_enum)); e->kind = t; e->wkt = ghw_wkt_unknown; e->name = ghw_read_strid (h); if (ghw_read_uleb128 (h, &e->nbr) != 0) goto err_b2; e->lits = (const char **) malloc (e->nbr * sizeof (char *)); if (h->flag_verbose > 1) printf ("enum %s:", e->name); for (j = 0; j < e->nbr; j++) { e->lits[j] = ghw_read_strid (h); if (h->flag_verbose > 1) printf (" %s", e->lits[j]); } if (h->flag_verbose > 1) printf ("\n"); h->types[i] = (union ghw_type *)e; break; err_b2: free (e); return -1; } break; case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: { struct ghw_type_scalar *sc; sc = malloc (sizeof (struct ghw_type_scalar)); sc->kind = t; sc->name = ghw_read_strid (h); if (h->flag_verbose > 1) printf ("scalar: %s\n", sc->name); h->types[i] = (union ghw_type *)sc; } break; case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: { struct ghw_type_physical *ph; ph = malloc (sizeof (struct ghw_type_physical)); ph->kind = t; ph->name = ghw_read_strid (h); ph->units = NULL; if (h->version == 0) ph->nbr_units = 0; else { unsigned j; if (ghw_read_uleb128 (h, &ph->nbr_units) != 0) goto err_p32; ph->units = malloc (ph->nbr_units * sizeof (struct ghw_unit)); for (j = 0; j < ph->nbr_units; j++) { ph->units[j].name = ghw_read_strid (h); if (ghw_read_lsleb128 (h, &ph->units[j].val) < 0) goto err_p32; } } if (h->flag_verbose > 1) printf ("physical: %s\n", ph->name); h->types[i] = (union ghw_type *)ph; break; err_p32: free (ph->units); free (ph); return -1; } break; case ghdl_rtik_subtype_scalar: { struct ghw_subtype_scalar *ss; ss = malloc (sizeof (struct ghw_subtype_scalar)); ss->kind = t; ss->name = ghw_read_strid (h); ss->base = ghw_read_typeid (h); ss->rng = ghw_read_range (h); if (h->flag_verbose > 1) printf ("subtype scalar: %s\n", ss->name); h->types[i] = (union ghw_type *)ss; } break; case ghdl_rtik_type_array: { struct ghw_type_array *arr; unsigned j; arr = malloc (sizeof (struct ghw_type_array)); arr->kind = t; arr->name = ghw_read_strid (h); arr->el = ghw_read_typeid (h); if (ghw_read_uleb128 (h, &arr->nbr_dim) != 0) goto err_array; arr->dims = (union ghw_type **) malloc (arr->nbr_dim * sizeof (union ghw_type *)); for (j = 0; j < arr->nbr_dim; j++) arr->dims[j] = ghw_read_typeid (h); if (h->flag_verbose > 1) printf ("array: %s (ndim=%u) of %s\n", arr->name, arr->nbr_dim, arr->el->common.name); h->types[i] = (union ghw_type *)arr; break; err_array: free (arr); return -1; } break; case ghdl_rtik_subtype_array: { struct ghw_subtype_array *sa; const char *name; union ghw_type *base; name = ghw_read_strid (h); base = ghw_read_typeid (h); sa = ghw_read_array_subtype (h, base); sa->name = name; h->types[i] = (union ghw_type *)sa; if (h->flag_verbose > 1) printf ("subtype array: %s (nbr_scalars=%d)\n", sa->name, sa->nbr_scalars); } break; case ghdl_rtik_subtype_unbounded_array: { struct ghw_subtype_unbounded_array *sua; sua = malloc (sizeof (struct ghw_subtype_unbounded_array)); sua->kind = t; sua->name = ghw_read_strid (h); sua->base = ghw_read_typeid (h); h->types[i] = (union ghw_type *)sua; if (h->flag_verbose > 1) printf ("subtype unbounded array: %s\n", sua->name); } break; case ghdl_rtik_type_record: { struct ghw_type_record *rec; unsigned j; int nbr_scalars; rec = malloc (sizeof (struct ghw_type_record)); rec->kind = t; rec->name = ghw_read_strid (h); rec->els = NULL; if (ghw_read_uleb128 (h, &rec->nbr_fields) != 0) goto err_record; rec->els = malloc (rec->nbr_fields * sizeof (struct ghw_record_element)); nbr_scalars = 0; for (j = 0; j < rec->nbr_fields; j++) { rec->els[j].name = ghw_read_strid (h); rec->els[j].type = ghw_read_typeid (h); if (nbr_scalars != -1) { int field_nbr_scalars = get_nbr_elements (rec->els[j].type); if (field_nbr_scalars == -1) nbr_scalars = -1; else nbr_scalars += field_nbr_scalars; } } rec->nbr_scalars = nbr_scalars; if (h->flag_verbose > 1) printf ("record type: %s (nbr_scalars=%d)\n", rec->name, rec->nbr_scalars); h->types[i] = (union ghw_type *)rec; break; err_record: free (rec->els); free (rec); return -1; } break; case ghdl_rtik_subtype_record: { struct ghw_subtype_record *sr; const char *name; struct ghw_type_record *base; name = ghw_read_strid (h); base = (struct ghw_type_record *)ghw_read_typeid (h); sr = ghw_read_record_subtype (h, base); sr->name = name; h->types[i] = (union ghw_type *)sr; if (h->flag_verbose > 1) printf ("subtype record: %s (nbr_scalars=%d)\n", sr->name, sr->nbr_scalars); } break; default: fprintf (stderr, "ghw_read_type: unknown type %d\n", t); return -1; } } if (fgetc (h->stream) != 0) return -1; return 0; } int ghw_read_wk_types (struct ghw_handler *h) { char hdr[4]; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; while (1) { int t; union ghw_type *tid; t = fgetc (h->stream); if (t == EOF) return -1; else if (t == 0) break; tid = ghw_read_typeid (h); if (tid->kind == ghdl_rtik_type_b2 || tid->kind == ghdl_rtik_type_e8) { if (h->flag_verbose > 0) printf ("%s: wkt=%d\n", tid->en.name, t); tid->en.wkt = t; } } return 0; } void ghw_disp_typename (struct ghw_handler *h, union ghw_type *t) { (void)h; printf ("%s", t->common.name); } /* Read a signal composed of severals elements. Return 0 for success. */ int ghw_read_signal (struct ghw_handler *h, unsigned int *sigs, union ghw_type *t) { switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: case ghdl_rtik_type_e32: case ghdl_rtik_subtype_scalar: { unsigned int sig_el; if (ghw_read_uleb128 (h, &sig_el) < 0) return -1; *sigs = sig_el; if (sig_el == 0 || sig_el >= h->nbr_sigs) return -1; if (h->sigs[sig_el].type == NULL) h->sigs[sig_el].type = ghw_get_base_type (t); } return 0; case ghdl_rtik_subtype_array: { int i; int stride; int len; len = t->sa.nbr_scalars; stride = get_nbr_elements (t->sa.el); for (i = 0; i < len; i += stride) if (ghw_read_signal (h, &sigs[i], t->sa.el) < 0) return -1; } return 0; case ghdl_rtik_type_record: { struct ghw_type_record *r = &t->rec; int nbr_fields = r->nbr_fields; int i; int off; off = 0; for (i = 0; i < nbr_fields; i++) { if (ghw_read_signal (h, &sigs[off], r->els[i].type) < 0) return -1; off += get_nbr_elements (r->els[i].type); } } return 0; case ghdl_rtik_subtype_record: { struct ghw_subtype_record *sr = &t->sr; int nbr_fields = sr->base->nbr_fields; int i; int off; off = 0; for (i = 0; i < nbr_fields; i++) { if (ghw_read_signal (h, &sigs[off], sr->els[i].type) < 0) return -1; off += get_nbr_elements (sr->els[i].type); } } return 0; default: fprintf (stderr, "ghw_read_signal: type kind %d unhandled\n", t->kind); abort (); } } int ghw_read_value (struct ghw_handler *h, union ghw_val *val, union ghw_type *type) { switch (ghw_get_base_type (type)->kind) { case ghdl_rtik_type_b2: { int v; v = fgetc (h->stream); if (v == EOF) return -1; val->b2 = v; } break; case ghdl_rtik_type_e8: { int v; v = fgetc (h->stream); if (v == EOF) return -1; val->e8 = v; } break; case ghdl_rtik_type_i32: case ghdl_rtik_type_p32: { int32_t v; if (ghw_read_sleb128 (h, &v) < 0) return -1; val->i32 = v; } break; case ghdl_rtik_type_f64: { double v; if (ghw_read_f64 (h, &v) < 0) return -1; val->f64 = v; } break; case ghdl_rtik_type_p64: { int64_t v; if (ghw_read_lsleb128 (h, &v) < 0) return -1; val->i64 = v; } break; default: fprintf (stderr, "read_value: cannot handle format %d\n", type->kind); abort (); } return 0; } int ghw_read_hie (struct ghw_handler *h) { unsigned char hdr[16]; int nbr_scopes; int nbr_sigs; unsigned i; struct ghw_hie *blk; struct ghw_hie **last; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; nbr_scopes = ghw_get_i32 (h, &hdr[4]); /* Number of declared signals (which may be composite). */ nbr_sigs = ghw_get_i32 (h, &hdr[8]); /* Number of basic signals. */ h->nbr_sigs = ghw_get_i32 (h, &hdr[12]); if (h->flag_verbose) printf ("%u scopes, %u signals, %u signal elements\n", nbr_scopes, nbr_sigs, h->nbr_sigs); blk = (struct ghw_hie *)malloc (sizeof (struct ghw_hie)); blk->kind = ghw_hie_design; blk->name = NULL; blk->parent = NULL; blk->brother = NULL; blk->u.blk.child = NULL; last = &blk->u.blk.child; h->hie = blk; h->nbr_sigs++; h->skip_sigs = NULL; h->flag_full_names = 0; h->sigs = (struct ghw_sig *) malloc (h->nbr_sigs * sizeof (struct ghw_sig)); memset (h->sigs, 0, h->nbr_sigs * sizeof (struct ghw_sig)); while (1) { int t; struct ghw_hie *el; unsigned int str; t = fgetc (h->stream); if (t == EOF) return -1; if (t == 0) break; if (t == ghw_hie_eos) { blk = blk->parent; if (blk->u.blk.child == NULL) last = &blk->u.blk.child; else { struct ghw_hie *l = blk->u.blk.child; while (l->brother != NULL) l = l->brother; last = &l->brother; } continue; } el = (struct ghw_hie *) malloc (sizeof (struct ghw_hie)); el->kind = t; el->parent = blk; el->brother = NULL; /* Link. */ *last = el; last = &el->brother; /* Read name. */ if (ghw_read_uleb128 (h, &str) != 0) return -1; el->name = h->str_table[str]; switch (t) { case ghw_hie_eoh: case ghw_hie_design: case ghw_hie_eos: /* Should not be here. */ abort (); case ghw_hie_process: el->u.blk.child = NULL; break; case ghw_hie_block: case ghw_hie_generate_if: case ghw_hie_generate_for: case ghw_hie_instance: case ghw_hie_generic: case ghw_hie_package: /* Create a block. */ el->u.blk.child = NULL; if (t == ghw_hie_generate_for) { el->u.blk.iter_type = ghw_read_typeid (h); el->u.blk.iter_value = malloc (sizeof (union ghw_val)); if (ghw_read_value (h, el->u.blk.iter_value, el->u.blk.iter_type) < 0) return -1; } blk = el; last = &el->u.blk.child; break; case ghw_hie_signal: case ghw_hie_port_in: case ghw_hie_port_out: case ghw_hie_port_inout: case ghw_hie_port_buffer: case ghw_hie_port_linkage: /* For a signal, read type. */ { int nbr_el; unsigned int *sigs; el->u.sig.type = ghw_read_typeid (h); nbr_el = get_nbr_elements (el->u.sig.type); if (nbr_el < 0) return -1; sigs = (unsigned int *) malloc ((nbr_el + 1) * sizeof (unsigned int)); el->u.sig.sigs = sigs; /* Last element is NULL. */ sigs[nbr_el] = 0; if (h->flag_verbose > 1) printf ("signal %s: %d el [", el->name, nbr_el); if (ghw_read_signal (h, sigs, el->u.sig.type) < 0) return -1; if (h->flag_verbose > 1) { int j; for (j = 0; j < nbr_el; j++) printf (" #%u", sigs[j]); printf ("]\n"); } } break; default: fprintf (stderr, "ghw_read_hie: unhandled kind %d\n", t); abort (); } } /* Allocate values. */ for (i = 0; i < h->nbr_sigs; i++) if (h->sigs[i].type != NULL) h->sigs[i].val = (union ghw_val *) malloc (sizeof (union ghw_val)); return 0; } const char * ghw_get_hie_name (struct ghw_hie *h) { switch (h->kind) { case ghw_hie_eoh: return "eoh"; case ghw_hie_design: return "design"; case ghw_hie_block: return "block"; case ghw_hie_generate_if: return "generate-if"; case ghw_hie_generate_for: return "generate-for"; case ghw_hie_instance: return "instance"; case ghw_hie_package: return "package"; case ghw_hie_process: return "process"; case ghw_hie_generic: return "generic"; case ghw_hie_eos: return "eos"; case ghw_hie_signal: return "signal"; case ghw_hie_port_in: return "port-in"; case ghw_hie_port_out: return "port-out"; case ghw_hie_port_inout: return "port-inout"; case ghw_hie_port_buffer: return "port-buffer"; case ghw_hie_port_linkage: return "port-linkage"; default: return "??"; } } void ghw_disp_value (union ghw_val *val, union ghw_type *type); static void print_name (struct ghw_hie *hie, int full_names) { int i; int depth; struct ghw_hie *p; struct ghw_hie **buf; struct ghw_hie **end; /* HIE must be valid. */ assert (hie->name != NULL); if (0 == full_names) { printf (" %s: ", hie->name); return; } p = hie; depth = 0; while (p && p->name) { p = p->parent; ++depth; } buf = (struct ghw_hie **) malloc (depth * sizeof (struct ghw_hie *)); p = hie; end = depth + buf; while (p && p->name) { *(--end) = p; p = p->parent; } putchar (' '); putchar ('/'); for (i = 0; i < depth; ++i) { printf ("%s%s", i ? "/" : "", buf[i]->name); if (ghw_hie_generate_for == buf[i]->kind) { putchar ('('); ghw_disp_value (buf[i]->u.blk.iter_value, buf[i]->u.blk.iter_type); putchar (')'); } } putchar (':'); putchar (' '); free (buf); } void ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top) { int i; int indent; struct ghw_hie *hie; struct ghw_hie *n; hie = top; indent = 0; while (1) { if (0 == h->flag_full_names) for (i = 0; i < indent; i++) fputc (' ', stdout); printf ("%s", ghw_get_hie_name (hie)); switch (hie->kind) { case ghw_hie_design: case ghw_hie_block: case ghw_hie_generate_if: case ghw_hie_generate_for: case ghw_hie_instance: case ghw_hie_process: case ghw_hie_package: if (hie->name) print_name (hie, h->flag_full_names); if (hie->kind == ghw_hie_generate_for) { printf ("("); ghw_disp_value (hie->u.blk.iter_value, hie->u.blk.iter_type); printf (")"); } n = hie->u.blk.child; if (n == NULL) n = hie->brother; else indent++; break; case ghw_hie_generic: case ghw_hie_eos: abort (); case ghw_hie_signal: case ghw_hie_port_in: case ghw_hie_port_out: case ghw_hie_port_inout: case ghw_hie_port_buffer: case ghw_hie_port_linkage: { unsigned int *sigs = hie->u.sig.sigs; unsigned int k, num; print_name (hie, h->flag_full_names); ghw_disp_subtype_indication (h, hie->u.sig.type); printf (":"); k = 0; /* There can be 0-length signals. */ while (sigs[k] != GHW_NO_SIG) { /* First signal of the range. */ printf (" #%u", sigs[k]); for (num = 1; sigs[k + num] != GHW_NO_SIG; num++) if (sigs[k + num] != sigs[k + num - 1] + 1) break; if (num > 1) printf ("-#%u", sigs[k + num - 1]); k += num; } n = hie->brother; } break; default: abort (); } printf ("\n"); while (n == NULL) { if (hie->parent == NULL) return; hie = hie->parent; indent--; n = hie->brother; } hie = n; } } int ghw_read_eoh (struct ghw_handler *h) { (void)h; return 0; } int ghw_read_base (struct ghw_handler *h) { unsigned char hdr[4]; int res; while (1) { if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (memcmp (hdr, "STR", 4) == 0) res = ghw_read_str (h); else if (memcmp (hdr, "HIE", 4) == 0) res = ghw_read_hie (h); else if (memcmp (hdr, "TYP", 4) == 0) res = ghw_read_type (h); else if (memcmp (hdr, "WKT", 4) == 0) res = ghw_read_wk_types (h); else if (memcmp (hdr, "EOH", 4) == 0) return 0; else { fprintf (stderr, "ghw_read_base: unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], hdr[2], hdr[3]); return -1; } if (res != 0) { fprintf (stderr, "ghw_read_base: error in section %s\n", hdr); return res; } } } int ghw_read_signal_value (struct ghw_handler *h, struct ghw_sig *s) { return ghw_read_value (h, s->val, s->type); } int ghw_read_snapshot (struct ghw_handler *h) { unsigned char hdr[12]; unsigned i; struct ghw_sig *s; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; h->snap_time = ghw_get_i64 (h, &hdr[4]); if (h->flag_verbose > 1) printf ("Time is " GHWPRI64 " fs\n", h->snap_time); for (i = 0; i < h->nbr_sigs; i++) { s = &h->sigs[i]; if (s->type != NULL) { if (h->flag_verbose > 1) printf ("read type %d for sig %u\n", s->type->kind, i); if (ghw_read_signal_value (h, s) < 0) return -1; } } if (fread (hdr, 4, 1, h->stream) != 1) return -1; if (memcmp (hdr, "ESN", 4)) return -1; return 0; } void ghw_disp_values (struct ghw_handler *h); int ghw_read_cycle_start (struct ghw_handler *h) { unsigned char hdr[8]; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; h->snap_time = ghw_get_i64 (h, hdr); return 0; } int ghw_read_cycle_cont (struct ghw_handler *h, int *list) { int i; int *list_p; i = 0; list_p = list; while (1) { uint32_t d; /* Read delta to next signal. */ if (ghw_read_uleb128 (h, &d) < 0) return -1; if (d == 0) { /* Last signal reached. */ break; } /* Find next signal. */ while (d > 0) { i++; if (h->sigs[i].type != NULL) d--; } if (ghw_read_signal_value (h, &h->sigs[i]) < 0) return -1; if (list_p) *list_p++ = i; } if (list_p) *list_p = 0; return 0; } int ghw_read_cycle_next (struct ghw_handler *h) { int64_t d_time; if (ghw_read_lsleb128 (h, &d_time) < 0) return -1; if (d_time == -1) return 0; h->snap_time += d_time; return 1; } int ghw_read_cycle_end (struct ghw_handler *h) { char hdr[4]; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (memcmp (hdr, "ECY", 4)) return -1; return 0; } static const char * ghw_get_lit (union ghw_type *type, unsigned e) { if (e >= type->en.nbr) return "??"; else return type->en.lits[e]; } static void ghw_disp_lit (union ghw_type *type, unsigned e) { printf ("%s (%u)", ghw_get_lit (type, e), e); } void ghw_disp_value (union ghw_val *val, union ghw_type *type) { switch (ghw_get_base_type (type)->kind) { case ghdl_rtik_type_b2: ghw_disp_lit (type, val->b2); break; case ghdl_rtik_type_e8: ghw_disp_lit (type, val->e8); break; case ghdl_rtik_type_i32: printf (GHWPRI32, val->i32); break; case ghdl_rtik_type_p64: printf (GHWPRI64, val->i64); break; case ghdl_rtik_type_f64: printf ("%g", val->f64); break; default: fprintf (stderr, "ghw_disp_value: cannot handle type %d\n", type->kind); abort (); } } /* Put the ASCII representation of VAL into BUF, whose size if LEN. A NUL is always written to BUF. */ void ghw_get_value (char *buf, int len, union ghw_val *val, union ghw_type *type) { union ghw_type *base = ghw_get_base_type (type); switch (base->kind) { case ghdl_rtik_type_b2: if (val->b2 <= 1) { strncpy (buf, base->en.lits[val->b2], len - 1); buf[len - 1] = 0; } else { snprintf (buf, len, "?%d", val->b2); } break; case ghdl_rtik_type_e8: if (val->b2 <= base->en.nbr) { strncpy (buf, base->en.lits[val->e8], len - 1); buf[len - 1] = 0; } else { snprintf (buf, len, "?%d", val->e8); } break; case ghdl_rtik_type_i32: snprintf (buf, len, GHWPRI32, val->i32); break; case ghdl_rtik_type_p64: snprintf (buf, len, GHWPRI64, val->i64); break; case ghdl_rtik_type_f64: snprintf (buf, len, "%g", val->f64); break; default: snprintf (buf, len, "?bad type %d?", type->kind); } } static char is_skip_signal (int *signals_to_keep, int nb_signals_to_keep, int signal) { int i; for (i = 0; i < nb_signals_to_keep; ++i) { if (signal == signals_to_keep[i]) { return 0; } } return 1; } void ghw_filter_signals (struct ghw_handler *h, int *signals_to_keep, int nb_signals_to_keep) { unsigned i; if (0 < nb_signals_to_keep && 0 != signals_to_keep) { if (0 == h->skip_sigs) { h->skip_sigs = (char *) malloc (sizeof (char) * h->nbr_sigs); } for (i = 0; i < h->nbr_sigs; ++i) { h->skip_sigs[i] = is_skip_signal (signals_to_keep, nb_signals_to_keep, i); } } else { if (0 != h->skip_sigs) { free (h->skip_sigs); h->skip_sigs = 0; } } } void ghw_disp_values (struct ghw_handler *h) { unsigned i; for (i = 0; i < h->nbr_sigs; i++) { struct ghw_sig *s = &h->sigs[i]; int skip = (0 != h->skip_sigs && (0 != h->skip_sigs[i])); if (s->type != NULL && !skip) { printf ("#%u: ", i); ghw_disp_value (s->val, s->type); printf ("\n"); } } } int ghw_read_directory (struct ghw_handler *h) { unsigned char hdr[8]; int nbr_entries; int i; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; nbr_entries = ghw_get_i32 (h, &hdr[4]); if (h->flag_verbose) printf ("Directory (%d entries):\n", nbr_entries); for (i = 0; i < nbr_entries; i++) { unsigned char ent[8]; int pos; if (fread (ent, sizeof (ent), 1, h->stream) != 1) return -1; pos = ghw_get_i32 (h, &ent[4]); if (h->flag_verbose) printf (" %s at %d\n", ent, pos); } if (fread (hdr, 4, 1, h->stream) != 1) return -1; if (memcmp (hdr, "EOD", 4)) return -1; return 0; } int ghw_read_tailer (struct ghw_handler *h) { unsigned char hdr[8]; int pos; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; pos = ghw_get_i32 (h, &hdr[4]); if (h->flag_verbose) printf ("Tailer: directory at %d\n", pos); return 0; } enum ghw_res ghw_read_sm_hdr (struct ghw_handler *h, int *list) { unsigned char hdr[4]; int res; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) { if (feof (h->stream)) return ghw_res_eof; else return ghw_res_error; } if (memcmp (hdr, "SNP", 4) == 0) { res = ghw_read_snapshot (h); if (res < 0) return res; return ghw_res_snapshot; } else if (memcmp (hdr, "CYC", 4) == 0) { res = ghw_read_cycle_start (h); if (res < 0) return res; res = ghw_read_cycle_cont (h, list); if (res < 0) return res; return ghw_res_cycle; } else if (memcmp (hdr, "DIR", 4) == 0) { res = ghw_read_directory (h); } else if (memcmp (hdr, "TAI", 4) == 0) { res = ghw_read_tailer (h); } else { fprintf (stderr, "unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], hdr[2], hdr[3]); return -1; } if (res != 0) return res; return ghw_res_other; } int ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm) { int res; while (1) { /* printf ("sm: state = %d\n", *sm); */ switch (*sm) { case ghw_sm_init: case ghw_sm_sect: res = ghw_read_sm_hdr (h, NULL); switch (res) { case ghw_res_other: break; case ghw_res_snapshot: *sm = ghw_sm_sect; return res; case ghw_res_cycle: *sm = ghw_sm_cycle; return res; default: return res; } break; case ghw_sm_cycle: if (0) printf ("Time is " GHWPRI64 " fs\n", h->snap_time); if (0) ghw_disp_values (h); res = ghw_read_cycle_next (h); if (res < 0) return res; if (res == 1) { res = ghw_read_cycle_cont (h, NULL); if (res < 0) return res; return ghw_res_cycle; } res = ghw_read_cycle_end (h); if (res < 0) return res; *sm = ghw_sm_sect; break; } } } int ghw_read_cycle (struct ghw_handler *h) { int res; res = ghw_read_cycle_start (h); if (res < 0) return res; while (1) { res = ghw_read_cycle_cont (h, NULL); if (res < 0) return res; if (0) printf ("Time is " GHWPRI64 " fs\n", h->snap_time); if (0) ghw_disp_values (h); res = ghw_read_cycle_next (h); if (res < 0) return res; if (res == 0) break; } res = ghw_read_cycle_end (h); return res; } int ghw_read_dump (struct ghw_handler *h) { unsigned char hdr[4]; int res; while (1) { if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) { if (feof (h->stream)) return 0; else return -1; } if (memcmp (hdr, "SNP", 4) == 0) { res = ghw_read_snapshot (h); if (0 && res >= 0) ghw_disp_values (h); } else if (memcmp (hdr, "CYC", 4) == 0) { res = ghw_read_cycle (h); } else if (memcmp (hdr, "DIR", 4) == 0) { res = ghw_read_directory (h); } else if (memcmp (hdr, "TAI", 4) == 0) { res = ghw_read_tailer (h); } else { fprintf (stderr, "unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], hdr[2], hdr[3]); return -1; } if (res != 0) return res; } } struct ghw_section ghw_sections[] = { { "\0\0\0", NULL }, { "STR", ghw_read_str }, { "HIE", ghw_read_hie }, { "TYP", ghw_read_type }, { "WKT", ghw_read_wk_types }, { "EOH", ghw_read_eoh }, { "SNP", ghw_read_snapshot }, { "CYC", ghw_read_cycle }, { "DIR", ghw_read_directory }, { "TAI", ghw_read_tailer } }; int ghw_read_section (struct ghw_handler *h) { unsigned char hdr[4]; unsigned i; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) { if (feof (h->stream)) return -2; else return -1; } for (i = 1; i < sizeof (ghw_sections) / sizeof (*ghw_sections); i++) if (memcmp (hdr, ghw_sections[i].name, 4) == 0) return i; fprintf (stderr, "ghw_read_section: unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], hdr[2], hdr[3]); return 0; } void ghw_close (struct ghw_handler *h) { if (h->stream) { if (h->stream_ispipe) pclose (h->stream); else fclose (h->stream); h->stream = NULL; } } const char * ghw_get_dir (int is_downto) { return is_downto ? "downto" : "to"; } void ghw_disp_range (union ghw_type *type, union ghw_range *rng) { switch (rng->kind) { case ghdl_rtik_type_b2: printf ("%s %s %s", ghw_get_lit (type, rng->b2.left), ghw_get_dir (rng->b2.dir), ghw_get_lit (type, rng->b2.right)); break; case ghdl_rtik_type_e8: printf ("%s %s %s", ghw_get_lit (type, rng->e8.left), ghw_get_dir (rng->e8.dir), ghw_get_lit (type, rng->e8.right)); break; case ghdl_rtik_type_i32: case ghdl_rtik_type_p32: printf (GHWPRI32 " %s " GHWPRI32, rng->i32.left, ghw_get_dir (rng->i32.dir), rng->i32.right); break; case ghdl_rtik_type_i64: case ghdl_rtik_type_p64: printf (GHWPRI64 " %s " GHWPRI64, rng->i64.left, ghw_get_dir (rng->i64.dir), rng->i64.right); break; case ghdl_rtik_type_f64: printf ("%g %s %g", rng->f64.left, ghw_get_dir (rng->f64.dir), rng->f64.right); break; default: printf ("?(%d)", rng->kind); } } static void ghw_disp_array_subtype_bounds (struct ghw_subtype_array *a) { unsigned i; struct ghw_type_array *base = (struct ghw_type_array *)ghw_get_base_type (a->base); printf (" ("); for (i = 0; i < base->nbr_dim; i++) { if (i != 0) printf (", "); ghw_disp_range (base->dims[i], a->rngs[i]); } printf (")"); } static void ghw_disp_record_subtype_bounds (struct ghw_subtype_record *sr) { struct ghw_type_record *base = sr->base; int is_first = 1; unsigned i; for (i = 0; i < base->nbr_fields; i++) { if (sr->els[i].type != base->els[i].type) { if (is_first) { printf ("("); is_first = 0; } else printf (", "); printf ("%s", base->els[i].name); switch (sr->els[i].type->kind) { case ghdl_rtik_subtype_array: ghw_disp_array_subtype_bounds (&sr->els[i].type->sa); break; case ghdl_rtik_subtype_record: ghw_disp_record_subtype_bounds (&sr->els[i].type->sr); break; default: printf ("??? (%d)", sr->els[i].type->kind); } } } if (!is_first) printf (")"); } static void ghw_disp_subtype_definition (struct ghw_handler *h, union ghw_type *t) { switch (t->kind) { case ghdl_rtik_subtype_scalar: { struct ghw_subtype_scalar *s = &t->ss; ghw_disp_typename (h, s->base); printf (" range "); ghw_disp_range (s->base, s->rng); } break; case ghdl_rtik_subtype_array: { struct ghw_subtype_array *a = &t->sa; ghw_disp_typename (h, (union ghw_type *)a->base); ghw_disp_array_subtype_bounds (a); } break; case ghdl_rtik_subtype_record: { struct ghw_subtype_record *sr = &t->sr; ghw_disp_typename (h, (union ghw_type *)sr->base); ghw_disp_record_subtype_bounds (sr); } break; case ghdl_rtik_subtype_unbounded_array: { struct ghw_subtype_unbounded_record *sur = &t->sur; ghw_disp_typename (h, (union ghw_type *)sur->base); } break; default: printf ("ghw_disp_subtype_definition: unhandled type kind %d\n", t->kind); } } static int ghw_is_anonymous_type (struct ghw_handler *h, union ghw_type *t) { return t->common.name == h->str_table[0]; } void ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t) { if (ghw_is_anonymous_type (h, t)) { /* Anonymous subtype. */ ghw_disp_subtype_definition (h, t); } else ghw_disp_typename (h, t); } void ghw_disp_type (struct ghw_handler *h, union ghw_type *t) { switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: { struct ghw_type_enum *e = &t->en; unsigned i; printf ("type %s is (", e->name); for (i = 0; i < e->nbr; i++) { if (i != 0) printf (", "); printf ("%s", e->lits[i]); } printf (");"); if (e->wkt != ghw_wkt_unknown) printf (" -- WKT:%d", e->wkt); printf ("\n"); } break; case ghdl_rtik_type_i32: case ghdl_rtik_type_f64: { struct ghw_type_scalar *s = &t->sc; printf ("type %s is range <>;\n", s->name); } break; case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: { unsigned i; struct ghw_type_physical *p = &t->ph; printf ("type %s is range <> units\n", p->name); for (i = 0; i < p->nbr_units; i++) { struct ghw_unit *u = &p->units[i]; printf (" %s = " GHWPRI64 " %s;\n", u->name, u->val, p->units[0].name); } printf ("end units\n"); } break; case ghdl_rtik_type_array: { struct ghw_type_array *a = &t->ar; unsigned i; printf ("type %s is array (", a->name); for (i = 0; i < a->nbr_dim; i++) { if (i != 0) printf (", "); ghw_disp_typename (h, a->dims[i]); printf (" range <>"); } printf (") of "); ghw_disp_subtype_indication (h, a->el); printf (";\n"); } break; case ghdl_rtik_type_record: { struct ghw_type_record *r = &t->rec; unsigned i; printf ("type %s is record\n", r->name); for (i = 0; i < r->nbr_fields; i++) { printf (" %s: ", r->els[i].name); ghw_disp_subtype_indication (h, r->els[i].type); printf (";\n"); } printf ("end record;\n"); } break; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_scalar: case ghdl_rtik_subtype_record: case ghdl_rtik_subtype_unbounded_array: { struct ghw_type_common *c = &t->common; printf ("subtype %s is ", c->name); ghw_disp_subtype_definition (h, t); printf (";\n"); } break; default: printf ("ghw_disp_type: unhandled type kind %d\n", t->kind); } } void ghw_disp_types (struct ghw_handler *h) { unsigned i; for (i = 0; i < h->nbr_types; i++) if (h->flag_verbose || !ghw_is_anonymous_type (h, h->types[i])) ghw_disp_type (h, h->types[i]); }