#ifndef _GHDL_SHIM_H_
#define _GHDL_SHIM_H_

/* This is the interface definition file for the shim code (ghdl_shim.c)
 * and associated Verilog VPI module (ghdl_shim.vpi).
 *
 * This software allows execution of VHDL code generated by the GHDL compiler
 * inside a SPICE simulation performed by ngspice.
 *
 * Use of these components starts with a SPICE netlist containing an A-device
 * (XSPICE device) whose model card specifies the d_cosim code model and
 * parameter 'simulation="some_path/entity_name.so"', where "entity_name"
 * represents a top-level entity defined in VHDL.  The shared library
 * (or DLL) named is built by the "ghdl -e" command using output from
 * a VHDL compilation ("ghdl -a") and the provided ghdl_shim.c file.
 *
 * The VPI module ghdl_vpi.c is called on loading: its first task is to obtain
 * the list of ports for the top-level VHDL entity.  After that the VPI code
 * controls the execution of the VHDL code by blocking execution until
 * commanded to proceed by the d_cosim instance, always regaining control
 * via a VPI callback before the VHDL code moves ahead of the SPICE simulation.
 */

typedef uint32_t __vpiHandle;           // Compatible with GHDL's vpi_user.h

/* Data stored for each port. */

struct ngvp_port {
    uint16_t            bits;           // How many bits?
    uint16_t            flags;          // I/O pending.
    uint32_t            position;       // Number of bits before this port.
    struct {                            // Like struct t_vpi_vecval.
        int32_t           aval;
        int32_t           bval;
    }                   previous, new;  // Previous and new values.
    __vpiHandle        *handle;         // Handle to the port's variable.
    struct ng_ghdl     *ctx;            // Pointer back to parent.
};

#define IN_PENDING  1
#define OUT_PENDING 2

/* Data strucure used to share context between the ngspice and GHDL threads. */

struct ng_ghdl {
    struct cr_ctx       cr_ctx;         // Coroutine context.
    int                 stop;           // Indicates simulation is over.
    struct co_info     *cosim_context;
    uint32_t            ins;            // Port counts by type.
    uint32_t            outs;
    uint32_t            inouts;
    double              base_time;      // SPICE time on entry.
    double              tick_length;    // GHDL's time unit.
    __vpiHandle        *stop_cb;        // Handle to end-of-tick callback.
    volatile uint32_t   in_pending;     // Counts of changed ports.
    volatile uint32_t   out_pending;
    struct ngvp_port   *ports;          // Port information array.
};

/* The VPI module, ghdlng.vpi, contains a global variable with this name,
 * used during initialisation.
 */

#define CTX_VAR GHDLNG_VPI_context
#define STR(s) #s
#define XSTR(s) STR(s) // Puts quotes on its argument.
#define CTX_VAR_NAME XSTR(CTX_VAR)
#endif // _GHDL_SHIM_H_
