/* 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 . */ #include #include #include #include #include #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] = ""; 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 ((
--  Global flags.
--  Copyright (C) 2002, 2003, 2004, 2005, 2008 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 GHDL; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.

--  All the variables declared in this package are set by Parse_Option function
--  and can by read as soon as the command line is parsed.
--
--  Since the names are not prefixed, this package is expected to be with'ed
--  but not to be use'd.

package Flags is
   --  List of vhdl standards.
   --  VHDL_93c is vhdl_93 with backward compatibility with 87 (file).
   type Vhdl_Std_Type is
     (Vhdl_87, Vhdl_93c, Vhdl_93, Vhdl_00, Vhdl_02, Vhdl_08);

   --  Standard accepted.
   Vhdl_Std: Vhdl_Std_Type := Vhdl_93c;

   --  Enable AMS-VHDL extensions.
   AMS_Vhdl : Boolean := False;

   --  Some flags (such as vhdl version) must be the same for every design
   --  units of a hierarchy.
   --  The Flag_String is a signature of all these flags.
   --  Note: Flag_String (5) (time resolution) is directly overwritten in
   --   ghdlrun.
   Flag_String : String (1 .. 5);
   procedure Create_Flag_String;

   -- If set, a multi-bytes sequence can appear in a comment, ie, all
   -- characters except VT, CR, LF and FF are allowed in a comment.
   -- Set by -C and --mb-comments
   Mb_Comment: Boolean := False;

   -- If set, relax rules about std library: working library can be std.
   Bootstrap : Boolean := False;

   --  Options -dX
   --  -dp: disp tree after parsing
   Dump_Parse: Boolean := False;

   --  -ds: disp tree after semantic
   Dump_Sem: Boolean := False;

   --  -dc: disp tree after canon
   Dump_Canon : Boolean := False;

   --  -da: disp tree after annotation
   Dump_Annotate: Boolean := False;

   --  -do: don't dump origin expression but evaluated expressions.
   Dump_Origin_Flag : Boolean := True;

   --  --dall: makes -dX options to apply to all files.
   Dump_All: Boolean := False;

   --  -dstats: disp statistics.
   Dump_Stats : Boolean := False;

   --  If not 0, do internal consistency and leaks check on the AST after
   --  analysis.
   Check_Ast_Level : Natural := 0;

   -- -lX options: list tree as a vhdl file.

   -- --lall option: makes -lX options to apply to all files
   List_All: Boolean := False;

   -- -lv: list verbose
   List_Verbose: Boolean := False;

   -- -ls: list tree after semantic.
   List_Sem: Boolean := False;

   -- -lc: list tree after canon.
   List_Canon: Boolean := False;

   -- -la: list tree after back-end annotation.
   List_Annotate: Boolean := False;

   -- -v: disp phase of compilation.
   Verbose : Boolean := False;

   --  If set to true, the parser builds extended locations (defined in
   --  package elocations).  This saves possibly many locations per node, so
   --  it uses more memory.  Useful when a tool (like a style checker) wants
   --  to know the precise layout.  Not used to report errors.
   Flag_Elocations : Boolean := False;

   --  If set to true, it means that analyze is done for elaboration.
   --  The purpose is to avoid spurious warning "will be checked
   --  at elaboration".  It will also create default binding.
   Flag_Elaborate : Boolean := False;

   --  If set, a default aspect entity aspect might be an outdated unit.
   --  Used by ghdldrv.
   Flag_Elaborate_With_Outdated : Boolean := False;

   --  Do not display parse and sem warnings.  Used during elaboration.
   Flag_Only_Elab_Warnings : Boolean := False;

   --  If set, explicit subprogram declarations take precedence over
   --  implicit declarations, even through use clauses.
   Flag_Explicit : Boolean := False;

   --  If set, use 'L.C' rule from VHDL02 to do default component binding.
   Flag_Syn_Binding : Boolean := False;

   --  If set, performs VITAL checks.
   Flag_Vital_Checks : Boolean := True;

   --  Set if analysis is done even after parsing errors.  The analysis code
   --  that handles and tolerates incorrect parse tree should check that this
   --  flag is set.
   Flag_Force_Analysis : Boolean := False;

   --  Integer and time types can be either 32 bits or 64 bits values.
   --  The default is 32 bits for Integer and 64 bits for Time.
   --  Be very careful: if you don't use the default sizes, you may have to
   --  change other parts of your systems (such as GRT).
   Flag_Integer_64 : Boolean := False;
   Flag_Time_64 : Boolean := True;

   --  If set, generate cross-references during sem.
   Flag_Xref : Boolean := False;

   --  If set, all the design units are analyzed in whole to do the simulation.
   Flag_Whole_Analyze : Boolean := False;

   --  If true, relax some rules:
   --  * the scope of an object declaration names start after the declaration,
   --    so that it is possible to use the old name in the default expression:
   --    constant x : xtype := x;
   Flag_Relaxed_Rules : Boolean := False;

   -- --warn-undriven
   --Warn_Undriven : Boolean := False;

   --  If True, disp original source line and a caret indicating the column.
   Flag_Caret_Diagnostics : Boolean := False;

   type On_Off_Auto_Type is (On, Off, Auto);

   --  -fcolor-diagnostics
   --  -fno-color-diagnostics
   --  Enable colors in diagnostic messages.  The default is auto, which turns
   --  on when a terminal is detected on the standard error.
   Flag_Color_Diagnostics : On_Off_Auto_Type := Auto;

   --  -fdiagnostics-show-option
   Flag_Diagnostics_Show_Option : Boolean := True;
end Flags;
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]); }