/* 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" 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 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) { unsigned int 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) { unsigned int 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) { unsigned int 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) return NULL; if (ghw_read_byte (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } 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) return NULL; if (ghw_read_byte (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } 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) return NULL; if (ghw_read_sleb128 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } 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) return NULL; if (ghw_read_lsleb128 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } 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) return NULL; if (ghw_read_f64 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } 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]; int 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: %d\n", h->nbr_str - 1); printf ("String table size: %d\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 %d (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: return t; case ghdl_rtik_subtype_scalar: return t->ss.base; case ghdl_rtik_subtype_array: return (union ghw_type*)(t->sa.base); default: fprintf (stderr, "ghw_get_base_type: cannot handle type %d\n", t->kind); abort (); } } 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_subtype_array: case ghdl_rtik_subtype_array_ptr: return t->sa.nbr_el; case ghdl_rtik_type_record: return t->rec.nbr_el; default: fprintf (stderr, "get_nbr_elements: unhandled type %d\n", t->kind); abort (); } } int get_range_length (union ghw_range *rng) { switch (rng->kind) { case ghdl_rtik_type_i32: if (rng->i32.dir) return (rng->i32.left - rng->i32.right + 1); else return (rng->i32.right - rng->i32.left + 1); case ghdl_rtik_type_b2: if (rng->b2.dir) return (rng->b2.left - rng->b2.right + 1); else return (rng->b2.right - rng->b2.left + 1); case ghdl_rtik_type_e8: if (rng->e8.dir) return (rng->e8.left - rng->e8.right + 1); else return (rng->e8.right - rng->e8.left + 1); default: fprintf (stderr, "get_range_length: unhandled kind %d\n", rng->kind); abort (); } } int ghw_read_type (struct ghw_handler *h) { unsigned char hdr[8]; int 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; /* printf ("type[%d]= %d\n", i, t); */ switch (t) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: { struct ghw_type_enum *e; int 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) return -1; 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; 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); if (h->version == 0) ph->nbr_units = 0; else { int i; if (ghw_read_uleb128 (h, &ph->nbr_units) != 0) return -1; ph->units = malloc (ph->nbr_units * sizeof (struct ghw_unit)); for (i = 0; i < ph->nbr_units; i++) { ph->units[i].name = ghw_read_strid (h); if (ghw_read_lsleb128 (h, &ph->units[i].val) < 0) return -1; } } if (h->flag_verbose > 1) printf ("physical: %s\n", ph->name); h->types[i] = (union ghw_type *)ph; } 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; int 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) return -1; 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\n", arr->name); h->types[i] = (union ghw_type *)arr; } break; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_array_ptr: { struct ghw_subtype_array *sa; int j; int nbr_el; sa = malloc (sizeof (struct ghw_subtype_array)); sa->kind = t; sa->name = ghw_read_strid (h); sa->base = (struct ghw_type_array *)ghw_read_typeid (h); nbr_el = get_nbr_elements (sa->base->el); sa->rngs = malloc (sa->base->nbr_dim * sizeof (union ghw_range *)); for (j = 0; j < sa->base->nbr_dim; j++) { sa->rngs[j] = ghw_read_range (h); nbr_el *= get_range_length (sa->rngs[j]); } sa->nbr_el = nbr_el; if (h->flag_verbose > 1) printf ("subtype array: %s (nbr_el=%d)\n", sa->name, sa->nbr_el); h->types[i] = (union ghw_type *)sa; } break; case ghdl_rtik_type_record: { struct ghw_type_record *rec; int j; int nbr_el; rec = malloc (sizeof (struct ghw_type_record)); rec->kind = t; rec->name = ghw_read_strid (h); if (ghw_read_uleb128 (h, &rec->nbr_fields) != 0) return -1; rec->el = malloc (rec->nbr_fields * sizeof (struct ghw_record_element)); nbr_el = 0; for (j = 0; j < rec->nbr_fields; j++) { rec->el[j].name = ghw_read_strid (h); rec->el[j].type = ghw_read_typeid (h); nbr_el += get_nbr_elements (rec->el[j].type); } rec->nbr_el = nbr_el; if (h->flag_verbose > 1) printf ("record type: %s (nbr_el=%d)\n", rec->name, rec->nbr_el); h->types[i] = (union ghw_type *)rec; } 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) { 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) abort (); if (h->sigs[sig_el].type == NULL) h->sigs[sig_el].type = ghw_get_base_type (t); } return 0; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_array_ptr: { int i; int stride; int len; len = t->sa.nbr_el; stride = get_nbr_elements (t->sa.base->el); for (i = 0; i < len; i += stride) if (ghw_read_signal (h, &sigs[i], t->sa.base->el) < 0) return -1; } return 0; case ghdl_rtik_type_record: { int i; int off; off = 0; for (i = 0; i < t->rec.nbr_fields; i++) { if (ghw_read_signal (h, &sigs[off], t->rec.el[i].type) < 0) return -1; off += get_nbr_elements (t->rec.el[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; int 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 ("%d scopes, %d signals, %d 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->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: 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); 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 i; for (i = 0; i < nbr_el; i++) printf (" #%u", sigs[i]); 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); 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) { 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) printf (" %s", hie->name); 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; printf (" %s: ", hie->name); ghw_disp_subtype_indication (h, hie->u.sig.type); printf (":"); k = 0; assert (sigs[0] != GHW_NO_SIG); while (1) { /* 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; /* End of signals ? */ if (sigs[k] == GHW_NO_SIG) break; } 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) { 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]; int 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 %lld 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 %d\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, int e) { if (e >= type->en.nbr || e < 0) return "??"; else return type->en.lits[e]; } static void ghw_disp_lit (union ghw_type *type, int e) { printf ("%s (%d)", 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 ("%d", val->i32); break; case ghdl_rtik_type_p64: printf ("%lld", 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) { switch (ghw_get_base_type (type)->kind) { case ghdl_rtik_type_b2: if (val->b2 <= 1) { strncpy (buf, type->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 <= type->en.nbr) { strncpy (buf, type->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, "%d", val->i32); break; case ghdl_rtik_type_p64: snprintf (buf, len, "%lld", val->i64); break; case ghdl_rtik_type_f64: snprintf (buf, len, "%g", val->f64); break; default: snprintf (buf, len, "?bad type %d?", type->kind); } } void ghw_disp_values (struct ghw_handler *h) { int i; for (i = 0; i < h->nbr_sigs; i++) { struct ghw_sig *s = &h->sigs[i]; if (s->type != NULL) { printf ("#%d: ", 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 %lld 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 %lld 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]; int 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) { 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 ("%d %s %d", rng->i32.left, ghw_get_dir (rng->i32.dir), rng->i32.right); break; case ghdl_rtik_type_i64: case ghdl_rtik_type_p64: printf ("%lld %s %lld", 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_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: case ghdl_rtik_subtype_array_ptr: { struct ghw_subtype_array *a = &t->sa; int i; ghw_disp_typename (h, (union ghw_type *)a->base); printf (" ("); for (i = 0; i < a->base->nbr_dim; i++) { if (i != 0) printf (", "); ghw_disp_range (a->base->dims[i], a->rngs[i]); } printf (")"); } 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; int 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: { int 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 = %lld %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; int 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; int i; printf ("type %s is record\n", r->name); for (i = 0; i < r->nbr_fields; i++) { printf (" %s: ", r->el[i].name); ghw_disp_subtype_indication (h, r->el[i].type); printf (";\n"); } printf ("end record;\n"); } break; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_array_ptr: case ghdl_rtik_subtype_scalar: { 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) { int 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]); }