/* $Id$
 *
 *  Glue layer between fauhdli and FAUmachine to access FAUmachine signals 
 *  from VHDL. This is the local implementation for a standalone 
 *  fauhdli interpreter. (Most callbacks simply print an info).
 *
 * Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#ifndef __GLUE_VHDL_H_INCLUDED
#define __GLUE_VHDL_H_INCLUDED

#include "fauhdli.h"

extern void *
glue_vhdl_create(void);

extern void
glue_vhdl_destroy(void *_cpssp);

/** Create a foreign component (entity).
 *  @param _cpssp glue_vhdl instance.
 *  @param type type of the component (entity name).
 *  @param name name of the instantiated unit
 *  @return unique component id.
 */
extern unsigned int
glue_vhdl_comp_create(
	void *_cpssp,
	const char *type,
	const char *name
);

/*  Create a FAUmachine signal and return its ID.
 *  @param _cpssp opaque pointer.
 *  @param type type of the signal.
 *  @param name signal name (for debugging only)
 *  @return unique signal id.
 */
extern unsigned int
glue_vhdl_create_signal(
	void *_cpssp, 
	const char *type, 
	const char *name
);

/** Initialize a foreign architecture.
 *  The foreign architecture must first have been created with
 *  glue_vhdl_arch_create and the ports must have been connected
 *  with glue_vhdl_arch_port_connect (same with generics).
 *
 *  @param _cpssp glue_vhdl instance.
 *  @param arch architecture id (cf. glue_vhdl_arch_create).
 */
extern void
glue_vhdl_arch_init(void *_cpssp, unsigned int arch);

/** set a FAUmachine signal with signal id sig_id and data data.
 *  @param _cpssp opaque pointer.
 *  @param sig_id signal id (cf. system.h)
 *  @param data data fitting to the signal. (FIXME composites)
 *  @param drv pointer to driver instance.
 */
extern void
glue_vhdl_set(
	void *_cpssp,
	unsigned int sig_id, 
	union fauhdli_value data,
	void *drv
);

/** Set a procedure call argument of a foreign procedure.
 *  @param _cpssp opaque pointer.
 *  @param proc name of the foreign procedure.
 *  @param param name of the parameter
 *  @param value parameter value. Content depending on the signature
 *         of the foreign procedure.
 *         For parameter passing mechanisms, see GenCode.cpp.
 */
extern void
glue_vhdl_proc_set(
	void *_cpssp,
	const char *proc,
	const char *param, 
	union fauhdli_value value
);

/** Call a foreign procedure.
 *  @param _cpssp opaque pointer.
 *  @param proc name of the procedure to call.
 */
extern void
glue_vhdl_proc_call(void *_cpssp, const char *proc);

/** Create a foreign architecture. A foreign architecture means, that
 *  it is really declared in VHDL, but could e.g. instantiate only 
 *  foreign entities. This is mainly a callback before the VHDL
 *  architecture gets created (but after the signals for the architecture
 *  have been created), in case of need.
 *
 *  @param _cpssp opaque pointer.
 *  @param type type of the component (entity name).
 *  @param name name of the instantiated architecture
 *  @return unique component id.
 */
extern unsigned int
glue_vhdl_arch_create(
	void *_cpssp,
	const char *type,
	const char *name
);

/** Connect a VHDL signal to a FAUmachine signal so that writes are getting
 *  forwarded to FAUmachine.
 *  This function should get called if a VHDL driver is connected to a 
 *  foreign VHDL signal.
 *  @param _cpssp opaque pointer.
 *  @param sig_id FAUmachine signal id.
 *  @param init initial driving value.
 *  @param drv corresponding driver pointer.
 */
extern void
glue_vhdl_connect_out(
	void *_cpssp,
	unsigned int sig_id,
	union fauhdli_value init,
	void *drv
);

/** Connect a foreign signal that is read from VHDL.
 *  This function will call drv_update or in case a FAUmachine signal with 
 *  sig_id obtains a new value.
 *  @param _cpssp opaque pointer.
 *  @param sig_id unique FAUmachine signal id.
 *  @param drv driver instance that will be passed as _drv parameter for
 *  	   drv_update
 */
extern void
glue_vhdl_connect_in(
	void *_cpssp,
	unsigned int sig_id,
	void *drv
);

/** Initialize a foreign component.
 *  The foreign component must first have been created with
 *  glue_vhdl_comp_create and the ports must have been connected
 *  with glue_vhdl_comp_port_connect.
 *
 *  @param _cpssp opaque pointer.
 *  @param comp component id (cf. glue_vhdl_comp_create).
 */
extern void
glue_vhdl_comp_init(void *_cpssp, unsigned int comp);

/** connect a foreign signal to the port of a foreign component.
 *  @param _cpssp opaque pointer.
 *  @param comp unique component id (cf. glue_vhdl_comp_create, return value)
 *  @param port name of the desired port.
 *  @param sig unique signal id (cf. glue_vhdl_create_signal, return value)
 */ 
extern void
glue_vhdl_comp_port_connect(
	void *_cpssp,
	unsigned int comp, 
	const char *port, 
	unsigned int sig
);

/** connect a foreign signal to the port of a foreign component.
 *  @param _cpssp opaque pointer.
 *  @param arch unique architecture id (cf. glue_vhdl_arch_create, 
 *  	   return value)
 *  @param port name of the desired port.
 *  @param sig unique signal id (cf. glue_vhdl_create_signal, return value)
 */ 
extern void
glue_vhdl_arch_port_connect(
	void *_cpssp,
	unsigned int arch, 
	const char *port, 
	unsigned int sig
);

/** set a generic of a foreign component (which is not an array).
 *  @param _cpssp opaque pointer.
 *  @param comp unique component id (cf. glue_vhdl_comp_create, return value)
 *  @param generic name of the desired generic.
 *  @param val VHDL value (direct value for non-composites, pointer for 
 *         record types).
 *  @param type name of the corresponding VHDL type.
 */
extern void
glue_vhdl_comp_generic_nonarray_set(
	void *_cpssp,
	unsigned int comp,
	const char *generic,
	union fauhdli_value val,
	const char *type
);

/** set a generic of a foreign architecture (which is not an array).
 *  @param _cpssp opaque pointer.
 *  @param comp unique component id (cf. glue_vhdl_comp_create, return value)
 *  @param generic name of the desired generic.
 *  @param val VHDL value (direct value for non-composites, pointer for 
 *         record types).
 *  @param type name of the corresponding VHDL type.
 */
extern void
glue_vhdl_arch_generic_nonarray_set(
	void *_cpssp,
	unsigned int arch,
	const char *generic,
	union fauhdli_value val,
	const char *type
);

/** set a generic of a foreign component (which is an array).
 *  @param _cpssp opaque pointer.
 *  @param comp unique component id (cf. glue_vhdl_comp_create, return value)
 *  @param generic name of the desired generic.
 *  @param element_type type name of the element type
 *  @param base pointer to base of array.
 *  @param array_size size of array.
 */
extern void
glue_vhdl_comp_generic_array_set(
	void *_cpssp,
	unsigned int comp,
	const char *generic,
	const char *element_type,
	union fauhdli_value base,
	universal_integer array_size
);

/** set a generic of a foreign architecture (which is an array).
 *  @param _cpssp opaque pointer.
 *  @param arch unique architecture id (cf. glue_vhdl_comp_create, 
 *  	   return value)
 *  @param generic name of the desired generic.
 *  @param element_type type name of the element type
 *  @param base pointer to base of array.
 *  @param array_size size of array.
 */
extern void
glue_vhdl_arch_generic_array_set(
	void *_cpssp,
	unsigned int arch,
	const char *generic,
	const char *element_type,
	union fauhdli_value base,
	universal_integer array_size
);

#endif /* __GLUE_VHDL_H_INCLUDED */
