/* GHDL Wavefile reader library.
Copyright (C) 2005-2017 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>.
*/
#ifndef _LIBGHW_H_
#define _LIBGHW_H_
#include <stdio.h>
#include <stdlib.h>
/* To be libraries friendly. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* The libghw uses the standard c99 int32_t and int64_t. They are declared
in stdint.h. Header inttypes.h includes stdint.h and provides macro for
printf and co specifiers. Use it if known to be available. */
#if defined(__cplusplus) || \
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
defined(HAVE_INTTYPES_H)
/* Use C99 standard header. */
#include <inttypes.h>
#define GHWPRI64 "%" PRId64
#define GHWPRI32 "%" PRId32
#else
#include <stdint.h>
#define GHWPRI64 "%lld"
#define GHWPRI32 "%d"
#endif
enum ghdl_rtik
{
ghdl_rtik_top, /* 0 */
ghdl_rtik_library,
ghdl_rtik_package,
ghdl_rtik_package_body,
ghdl_rtik_entity,
ghdl_rtik_architecture, /* 5 */
ghdl_rtik_process,
ghdl_rtik_block,
ghdl_rtik_if_generate,
ghdl_rtik_for_generate,
ghdl_rtik_instance,
ghdl_rtik_constant,
ghdl_rtik_iterator,
ghdl_rtik_variable,
ghdl_rtik_signal,
ghdl_rtik_file,
ghdl_rtik_port,
ghdl_rtik_generic,
ghdl_rtik_alias,
ghdl_rtik_guard,
ghdl_rtik_component,
ghdl_rtik_attribute,
ghdl_rtik_type_b2, /* 22 */
ghdl_rtik_type_e8,
ghdl_rtik_type_e32,
ghdl_rtik_type_i32, /* 25 */
ghdl_rtik_type_i64,
ghdl_rtik_type_f64,
ghdl_rtik_type_p32,
ghdl_rtik_type_p64,
ghdl_rtik_type_access, /* 30 */
ghdl_rtik_type_array,
ghdl_rtik_type_record,
ghdl_rtik_type_file,
ghdl_rtik_subtype_scalar,
ghdl_rtik_subtype_array, /* 35 */
ghdl_rtik_subtype_array_ptr, /* Obsolete. */
ghdl_rtik_subtype_unbounded_array,
ghdl_rtik_subtype_record,
ghdl_rtik_subtype_unbounded_record,
#if 0
ghdl_rtik_subtype_access, /* 40 */
ghdl_rtik_type_protected,
ghdl_rtik_element,
ghdl_rtik_unit,
ghdl_rtik_attribute_transaction,
ghdl_rtik_attribute_quiet,
ghdl_rtik_attribute_stable,
#endif
ghdl_rtik_error
};
/* Well-known types. */
enum ghw_wkt_type
{
ghw_wkt_unknown,
ghw_wkt_boolean,
ghw_wkt_bit,
ghw_wkt_std_ulogic
};
struct ghw_range_b2
{
enum ghdl_rtik kind:8;
int dir:8; /* 0: to, !0: downto. */
unsigned char left;
unsigned char right;
};
struct ghw_range_e8
{
enum ghdl_rtik kind:8;
int dir:8; /* 0: to, !0: downto. */
unsigned char left;
unsigned char right;
};
struct ghw_range_i32
{
enum ghdl_rtik kind:8;
int dir:8; /* 0: to, !0: downto. */
int32_t left;
int32_t right;
};
struct ghw_range_i64
{
enum ghdl_rtik kind:8;
int dir:8;
int64_t left;
int64_t right;
};
struct ghw_range_f64
{
enum ghdl_rtik kind:8;
int dir:8;
double left;
double right;
};
union ghw_range
{
enum ghdl_rtik kind:8;
struct ghw_range_b2 b2;
struct ghw_range_e8 e8;
struct ghw_range_i32 i32;
struct ghw_range_i64 i64;
struct ghw_range_f64 f64;
};
/* Note: the first two fields must be kind and name. */
union ghw_type;
struct ghw_type_common
{
enum ghdl_rtik kind;
const char *name;
};
struct ghw_type_enum
{
enum ghdl_rtik kind;
const char *name;
enum ghw_wkt_type wkt;
unsigned int nbr;
const char **lits;
};
struct ghw_type_scalar
{
enum ghdl_rtik kind;
const char *name;
};
struct ghw_unit
{
const char *name;
int64_t val;
};
struct ghw_type_physical
{
enum ghdl_rtik kind;
const char *name;
uint32_t nbr_units;
struct ghw_unit *units;
};
struct ghw_type_array
{
enum ghdl_rtik kind;
const char *name;
unsigned int nbr_dim;
union ghw_type *el;
union ghw_type **dims;
};
struct ghw_subtype_unbounded_array
{
enum ghdl_rtik kind;
const char *name;
union ghw_type *base;
};
struct ghw_subtype_array
{
enum ghdl_rtik kind;
const char *name;
union ghw_type *base;
int nbr_scalars;
union ghw_range **rngs;
union ghw_type *el;
};
struct ghw_subtype_scalar
{
enum ghdl_rtik kind;
const char *name;
union ghw_type *base;
union ghw_range *rng;
};
struct ghw_record_element
{
const char *name;
union ghw_type *type;
};
struct ghw_type_record
{
enum ghdl_rtik kind;
const char *name;
unsigned int nbr_fields;
int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */
struct ghw_record_element *els;
};
struct ghw_subtype_record
{
enum ghdl_rtik kind;
const char *name;
struct ghw_type_record *base;
int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */
struct ghw_record_element *els;
};
struct ghw_subtype_unbounded_record
{
enum ghdl_rtik kind;
const char *name;
struct ghw_type_record *base;
};
union ghw_type
{
enum ghdl_rtik kind;
struct ghw_type_common common;
struct ghw_type_enum en;
struct ghw_type_scalar sc;
struct ghw_type_physical ph;
struct ghw_subtype_scalar ss;
struct ghw_type_array ar;
struct ghw_type_record rec;
struct ghw_subtype_array sa;
struct ghw_subtype_unbounded_array sua;
struct ghw_subtype_record sr;
struct ghw_subtype_unbounded_record sur;
};
union ghw_val
{
unsigned char b2;
unsigned char e8;
int32_t i32;
int64_t i64;
double f64;
};
/* A non-composite signal. */
struct ghw_sig
{
union ghw_type *type;
union ghw_val *val;
};
enum ghw_hie_kind
{
ghw_hie_eoh = 0,
ghw_hie_design = 1,
ghw_hie_block = 3,
ghw_hie_generate_if = 4,
ghw_hie_generate_for = 5,
ghw_hie_instance = 6,
ghw_hie_package = 7,
ghw_hie_process = 13,
ghw_hie_generic = 14,
ghw_hie_eos = 15,
ghw_hie_signal = 16,
ghw_hie_port_in = 17,
ghw_hie_port_out = 18,
ghw_hie_port_inout = 19,
ghw_hie_port_buffer = 20,
ghw_hie_port_linkage = 21
};
#define GHW_NO_SIG 0
struct ghw_hie
{
enum ghw_hie_kind kind;
struct ghw_hie *parent;
const char *name;
struct ghw_hie *brother;
union
{
struct
{
struct ghw_hie *child;
union ghw_type *iter_type;
union ghw_val *iter_value;
} blk;
struct
{
union ghw_type *type;
/* Array of signal elements.
Last element is GHW_NO_SIG (0). */
unsigned int *sigs;
} sig;
} u;
};
struct ghw_handler
{
FILE *stream;
/* True if STREAM was popen, else was fopen. */
unsigned char stream_ispipe;
/* True if words are big-endian. */
unsigned char word_be;
unsigned char word_len;
unsigned char off_len;
/* Minor version. */
int version;
/* Set by user. */
int flag_verbose;
/* String table. */
/* Number of strings. */
unsigned nbr_str;
/* Size of the strings (without nul). */
unsigned str_size;
/* String table. */
char **str_table;
/* Array containing strings. */
char *str_content;
/* Type table. */
unsigned nbr_types;
union ghw_type **types;
/* Non-composite (or basic) signals. */
unsigned nbr_sigs;
char *skip_sigs;
int flag_full_names;
struct ghw_sig *sigs;
/* Hierarchy. */
struct ghw_hie *hie;
/* Time of the next cycle. */
int64_t snap_time;
};
/* Open a GHW file with H.
Return < 0 in case of error. */
int ghw_open (struct ghw_handler *h, const char *filename);
/* Return base type of T. */
union ghw_type *ghw_get_base_type (union ghw_type *t);
/* Return length of RNG. */
int ghw_get_range_length (union ghw_range *rng);
/* 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);
const char *ghw_get_hie_name (struct ghw_hie *h);
void ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top);
int ghw_read_base (struct ghw_handler *h);
void ghw_filter_signals (struct ghw_handler *h, int *signals_to_keep,
int nb_signals_to_keep);
void ghw_disp_values (struct ghw_handler *h);
int ghw_read_cycle_start (struct ghw_handler *h);
int ghw_read_cycle_cont (struct ghw_handler *h, int *list);
int ghw_read_cycle_next (struct ghw_handler *h);
int ghw_read_cycle_end (struct ghw_handler *h);
enum ghw_sm_type
{
/* At init;
Read section name. */
ghw_sm_init = 0,
ghw_sm_sect = 1,
ghw_sm_cycle = 2
};
enum ghw_res
{
ghw_res_error = -1,
ghw_res_eof = -2,
ghw_res_ok = 0,
ghw_res_snapshot = 1,
ghw_res_cycle = 2,
ghw_res_other = 3
};
enum ghw_res ghw_read_sm_hdr (struct ghw_handler *h, int *list);
int ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm);
int ghw_read_dump (struct ghw_handler *h);
struct ghw_section
{
const char name[4];
int (*handler) (struct ghw_handler * h);
};
extern struct ghw_section ghw_sections[];
int ghw_read_section (struct ghw_handler *h);
void ghw_close (struct ghw_handler *h);
const char *ghw_get_dir (int is_downto);
void ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t);
/* Note: TYPE must be a base type (used only to display literals). */
void ghw_disp_range (union ghw_type *type, union ghw_range *rng);
void ghw_disp_type (struct ghw_handler *h, union ghw_type *t);
void ghw_disp_types (struct ghw_handler *h);
#endif /* _LIBGHW_H_ */