aboutsummaryrefslogtreecommitdiffstats
path: root/ghw/libghw.c
diff options
context:
space:
mode:
authorumarcor <unai.martinezcorral@ehu.eus>2021-04-23 23:22:46 +0200
committerumarcor <unai.martinezcorral@ehu.eus>2021-04-24 01:59:37 +0200
commit7ce1d1bc27999054c221fc9e97449fcb086e8e88 (patch)
tree1e7927ab1f9b93cc07c0c9cbaf88c959641fda37 /ghw/libghw.c
parentce49befde5e95066ee34469e043a48d94423c53b (diff)
downloadghdl-7ce1d1bc27999054c221fc9e97449fcb086e8e88.tar.gz
ghdl-7ce1d1bc27999054c221fc9e97449fcb086e8e88.tar.bz2
ghdl-7ce1d1bc27999054c221fc9e97449fcb086e8e88.zip
ghw: rename 'ghwlib' to 'libghw' (#1741)
Diffstat (limited to 'ghw/libghw.c')
-rw-r--r--ghw/libghw.c2240
1 files changed, 2240 insertions, 0 deletions
diff --git a/ghw/libghw.c b/ghw/libghw.c
new file mode 100644
index 000000000..eabc31cba
--- /dev/null
+++ b/ghw/libghw.c
@@ -0,0 +1,2240 @@
+/* GHDL Wavefile reader library.
+ Copyright (C) 2005 Tristan Gingold
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <gnu.org/licenses>.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libghw.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 |= ~0U << 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] = "<anon>";
+ 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 > 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;
+ 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;
+ case ghdl_rtik_subtype_unbounded_record:
+ {
+ struct ghw_subtype_unbounded_record *sur;
+
+ sur = malloc (sizeof (struct ghw_subtype_unbounded_record));
+ sur->kind = t;
+ sur->name = ghw_read_strid (h);
+ sur->base = (struct ghw_type_record *) ghw_read_typeid (h);
+ h->types[i] = (union ghw_type *) sur;
+ if (h->flag_verbose > 1)
+ printf ("subtype unbounded record: %s\n", sur->name);
+ }
+ 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:
+ case ghdl_rtik_subtype_unbounded_record:
+ {
+ 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:
+ case ghdl_rtik_subtype_unbounded_record:
+ {
+ 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]);
+}