/*******************************************************************************
 * This file is part of the WAL library developed
 * within the EU Artemis project SMECY (Smart Multicore Embedded SYstems)
 * Artemis JU 100230 and MSMT 7H10001,             http://www.smecy.eu
 * Copyright (C) 2010, 2011 UTIA AV CR, v.v.i.     http://sp.utia.cz
 * 
 * This program is distributed WITHOUT ANY WARRANTY; without even 
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 *  PURPOSE.
 *
 * This file has been released within the SMECY project
 * consortium for the requirements of the SMECY project.
 * Any use outside the SMECY consortium and/or for any
 * developments outside the scope of the SMECY project is prohibited.
 *
 * For more details contact Roman Bartosinski <bartosr@utia.cas.cz>.
 *******************************************************************************
 * Filename  : wal.h
 * Authors   : Roman Bartosinski <bartosr@utia.cas.cz>
 * Project   : SMECY
 * Purpose   : Header file for the public API of the WAL library
 * Release   : 
 * Version   : 1.0
 * Date      : 2010/04/13
 *
 * Long Description:
 *  The common part of the WAL (Worker Abstraction Layer) library with defined
 *  types of functions, structures and values used for communication with HW
 *  accelerators. There are also implementation of common (covering) functions. 
 * 
 *******************************************************************************
 * Modifications:
 *  Date: 2010/04/16
 *  Author: Roman Bartosinski
 *  Modified: Added comments and documentations
 *  --
 *  
 ******************************************************************************/

#ifndef _WORKER_ABSTRACTION_LAYER_API_HEADER_FILE_
#define _WORKER_ABSTRACTION_LAYER_API_HEADER_FILE_

/* common files */
#include <xcope.h>

/******************************************************************************/
/*** identifications - worker classes, groups of families and families ***/

/** D
 * enum wal_worker_class_ids - List of IDs of known worker classes
 * @WAL_ID_UNKNOWN: unknown or unassigned class
 * @WAL_ID_BCE: Basic Computing Elements class
 * @WAL_ID_GCE: Graphic Computing Elements class
 * @WAL_ID_DEVEL: Special ID for a new CE under development unfiled to WAL
 *
 * This IDs identify the worker class. The (8bit) class ID is the first
 * byte (MSB) of a returned 32bit value from the wal_get_id() function.
 */
enum wal_worker_class_ids { /* defined IDs of worker classes */
	WAL_ID_UNKNOWN = 0, /* unknown or unassigned worker class */
	WAL_ID_BCE     = 1, /* Basic Computing Elements class */
	WAL_ID_GCE     = 2,	/* Graphic Computing Elements class */

	WAL_ID_DEVEL   = 0xFF /* special ID for a new CE class */
};

/** D
 * enum wal_bce_ids - List of IDs of known groups of families under the BCE class
 * @WAL_BCE_ID_UNKNOWN: unknown or unassigned group of BCE worker families
 * @WAL_BCE_ID_JK: worker group of families provided by J.Kadlec
 * @WAL_BCE_ID_HK: worker group of families provided by H.Kloub
 * @WAL_BCE_ID_RB: worker group of families provided by R.Bartosinski
 *
 * This IDs identify worker group of families in the BCE class. In this version,
 * a worker group of families implemented and provided by one author or
 * maintainer. The (8bit) ID of group of families is the second byte (big 
 * endian) of a returned 32bit value from the wal_get_id() function.
 */
enum wal_bce_ids {
	WAL_BCE_ID_UNKNOWN = 0,
	WAL_BCE_ID_JK      = 1,
	WAL_BCE_ID_HK      = 2,
	WAL_BCE_ID_RB      = 3,
};

/**
 * enum wal_gce_ids - List of IDs of known groups of families under the GCE class
 * @WAL_GCE_ID_UNKNOWN: unknown or unassigned group of GCE worker families
 */
enum wal_gce_ids {
	WAL_GCE_ID_UNKNOWN = 0,
};


#define WAL_ID_CLASS_MASK   0xff000000
#define WAL_ID_CLASS_SHIFT  24
#define WAL_ID_GROUP_MASK  0x00ff0000
#define WAL_ID_GROUP_SHIFT 16
#define WAL_ID_FAMILY_MASK    0x0000ffff
#define WAL_ID_FAMILY_SHIFT   0

/** D
 * define wal_id_class - macro for extracting the class ID from full ID
 * @id: full worker ID
 *
 * The macro extracts the 8bit ID of worker class from a full 32bit
 * ID returned by the wal_get_id() function.
 */
#define wal_id_class(id)	((id&WAL_ID_CLASS_MASK)>>WAL_ID_CLASS_SHIFT)
/** D
 * define wal_id_group - macro for extracting ID of group of families from full ID
 * @id: full worker ID
 *
 * The macro extracts the 8bit ID of worker group of families from a full 32bit
 * ID returned by the wal_get_id() function.
 * The family ID is dependent on the worker class.
 */
#define wal_id_group(id)	((id&WAL_ID_GROUP_MASK)>>WAL_ID_GROUP_SHIFT)
/** D
 * define wal_id_family - macro for extracting worker family(user) ID from full ID
 * @id: full worker ID
 *
 * The macro extracts the 16bit worker family/user ID from a full 32bit ID
 * returned by the wal_get_id() function. The user ID is dependent on the
 * worker class and group of families. It should contain number of SIMD for
 * dynamically allocated resources.
 */
#define wal_id_family(id)  	((id&WAL_ID_FAMILY_MASK)>>WAL_ID_FAMILY_SHIFT)


/******************************************************************************/
/**
 * enum wal_common_operation_codes - codes of operations common for all workers
 * @WAL_OP_GETID: return 32bit value with worker class, group of families
 *                and family/worker user IDs. 
 *                See to 'wal_get_id' documentation.
 * @WAL_OP_GETCAP: return the worker capabilities - bitmap dependent
 *                 on the worker group of families.
 *                 See to the 'wal_get_capabilities' documentation.
 * @WAL_OP_GETLIC: return the worker license - 32bit value dependent on worker
 *                 family. See to the 'wal_get_license' documentation.
 * @WAL_OP_FIRST_USER_CODE: auxiliary value defines where the specific
 *                          operations of the family start
 * 
 * All new worker families should support these operations (GETID and
 * GETCAP at least).
 */
enum wal_common_operation_codes {
	WAL_OP_GETID  = 0,
	WAL_OP_GETCAP = 1,
	WAL_OP_GETLIC = 2,

	WAL_OP_FIRST_USER_CODE
};


/* workers common capabilities */
#define WAL_CAP_NONE	0


/******************************************************************************/
/* WAL errors and warnings */
#define WAL_RES_OK       ( 0) /* all is OK */
/* warnings */
#define WAL_RES_WNULL    ( 1) /* argument is a NULL */
/* errors */
#define WAL_RES_ERR      (-1) /* generic error */
#define WAL_RES_ENOINIT  (-2) /* not initiated */
#define WAL_RES_ENULL    (-3) /* null pointer */
#define WAL_RES_ERUNNING (-4) /* worker is running */
#define WAL_RES_ERANGE   (-5) /* index/value is out of range */

/******************************************************************************/
/* wal_ctrl_memories and wal_ctrl_memories_names must correspond */
/** D
 * enum wal_ctrl_memories_indicies - list of the control memories of the worker
 * @WAL_CMEM_MB2PB: index to MB2PB control memory (the control register
 *                  of the worker)
 * @WAL_CMEM_PB2MB: index to PB2MB control memory (the status register
 *                  of the worker)
 * @WAL_CMEM_P0: index to P0 control memory (PicoBlaze program memory 1)
 * @WAL_CMEM_P1: index to P1 control memory (PicoBlaze program memory 2)
 * @WAL_CMEM_NUM_MEMORIES: number of all defined control memories
 *
 * These indices correspond to an array of names of the control memories. Each
 * family and its members can define their own control memories and
 * their names in the family description structure.
 */
enum wal_ctrl_memories_indicies {
	WAL_CMEM_MB2PB = 0,
	WAL_CMEM_PB2MB,
	WAL_CMEM_P0,
	WAL_CMEM_P1,
	WAL_CMEM_NUM_MEMORIES
};

extern const char *wal_ctrl_memories_names[WAL_CMEM_NUM_MEMORIES];

/** D
 * enum wal_picoblaze_indices - list of indices of the PicoBlaze firmwares
 * @WAL_PBID_P0: index of the PicoBlaze firmware 0
 * @WAL_PBID_P1: index of the PicoBlaze firmware 1
 * @WAL_PBID_NUM: number of all defined PB firmwares
 *
 * These indices are used as one parameter in some wal functions, where
 * PB firmware must be select (e.g. wal_set_firmware() ).
 */
enum wal_picoblaze_indices {
	WAL_PBID_P0 = 0,
	WAL_PBID_P1,
	WAL_PBID_NUM,
};

#define WAL_FW_FULL_SIZE	1024

/******************************************************************************/
/* link to worker family description */
struct wal_family_desc;

/** D
 * struct wal_worker - structure describes instance of a worker family
 * @struct_ver: version of the worker description structure - should be set when
 *              structure is created (registered) (the current version is
 *              WAL_DESC_STRUCT_VERSION_1)
 * @name: name of worker instance
 * @fm_desc: pointer to worker family description structure
 * @inst_cfg_tbl: pointer to worker IPcore instance config table - must be set 
 *                before calling init function
 * @inst_iface: pointer to xc interface - it is obtained in the init function 
 *              from config table
 * @ctrl_mems: pointer to an array of pointers to shared memories for control 
 *             and support memories
 * @data_mems: pointer to on array of pointers to shared memories for data
 * @num_simd: number of used SIMD in the worker instance (the value cannot be
 *            greater than @fm_desc->@nmax_simd.
 * @num_smems: number of support memories used in the worker instance (the value
 *             cannot be greater than @fm_desc->@nmax_supp_mems ).
 * @op_state: the current state of operation in the instance
 * @op_runmode: HW runmode used in the current operation (automatically saved
 *              by the start_op() function and cleared in end_op() function)
 * @userdata: pointer to a user data or NULL
 * 
 * The worker structure describes instance of a worker family. It interconnect
 * worker family description structure (description of shared memories and 
 * control functions) with IPcore configuration table (description of hardware)
 * and arrays of pointers to initiated shared memories.
 */
struct wal_worker {
	int struct_ver;
   /*int id_worker;*/
	const char *name;                    /* name of worker */
	const struct wal_family_desc *fm_desc;      /* pointer to CE description structure */

	void                  *inst_cfg_tbl; /* pointer to IPcore config table */
	xc_iface_t            *inst_iface;   /* pointer to xc interface */
	xc_shram_t           **ctrl_mems;    /* pointers to control and support memories */
	xc_shram_t           **data_mems;    /* pointers to data memories */
	int                    num_simd;     /* number of SIMD actually used in worker instence */
	int                    num_smems;    /* number of supporting memories really used in worker instance */

	unsigned int           op_state;     /* state of the current operation */
	int                    op_runmode;   /* index of the PB memory used with the current operation */

	void                  *userdata;     /* pointer to worker user data */
};
typedef struct wal_worker wal_worker_t;

/* the current version of the worker description structure */
#define WAL_DESC_STRUCT_VERSION_1 1

/**
 * enum wal_worker_op_states - IDs of the current state of the worker
 * @WAL_WRK_STATE_IDLE: worker is in idle state, no operation is running
 * @WAL_WRK_STATE_START: worker is starting a new operation
 * @WAL_WRK_STATE_PROCESS: worker is processing operation
 * @WAL_WRK_STATE_ERROR: worker is in the error state (something hasn't been
 *                       finished correctly)
 * 
 * These values are used to control state of worker and they are set to the 
 * worker structure into the 'op_state' item.
 */
enum wal_worker_op_states {
	WAL_WRK_STATE_IDLE,
	WAL_WRK_STATE_START,
/*	WAL_WRK_STATE_WRITEDATA, */
	WAL_WRK_STATE_PROCESS,
/*	WAL_WRK_STATE_READDATA, */
/*	WAL_WRK_STATE_END, */
	WAL_WRK_STATE_ERROR,
};

/******************************************************************************/
/*** common API of the WAL library ***/
int wal_init_worker(struct wal_worker *wrk);
int wal_done_worker(struct wal_worker *wrk);

int wal_reset_worker(struct wal_worker *wrk);
int wal_start_operation(struct wal_worker *wrk, unsigned int pbid);
int wal_end_operation(struct wal_worker *wrk);
int wal_mb2pb(struct wal_worker *wrk, const uint32_t data);
int wal_pb2mb(struct wal_worker *wrk, uint32_t *data);
int wal_mb2cmem(struct wal_worker *wrk, unsigned int memid,
                unsigned int memoffs, const uint32_t *outbuf, unsigned int len);
int wal_cmem2mb(struct wal_worker *wrk, unsigned int memid, 
                unsigned int memoffs, uint32_t *inbuf, unsigned int len);
int wal_mb2dmem(struct wal_worker *wrk, unsigned int simdid, unsigned int memid,
                unsigned int memoffs, const void *outbuf, unsigned int len);
int wal_dmem2mb(struct wal_worker *wrk, unsigned int simdid, unsigned int memid,
                unsigned int memoffs, void *inbuf, unsigned int len);

int wal_set_firmware(struct wal_worker *wrk, int pbid,
                     const unsigned int *fwbuf, int fwsize);
int wal_get_id(struct wal_worker *wrk, int pbid, unsigned int *outval);
int wal_get_capabilities(struct wal_worker *wrk, int pbid, unsigned int *outval);
int wal_get_license(struct wal_worker *wrk, int pbid, unsigned int *outval);

/* define constant for set_firmware */
#define WAL_FW_WHOLE		-1


/******************************************************************************/
/*** Macros ***/

/** D
 * WAL_REGISTER_WORKER - macro for statical registering worker instance
 * @wname: name of a new worker (and name of the worker structure
 * @wtype: type of worker - part of name used to identify worker family descriptions
 *         the following values and structure must be defined:
 *         WAL_<wtype>_MAX_SIMD
 *         WAL_<wtype>_DMEM_NUM_MEMORIES
 *         WAL_<wtype>_CMEM_NUM_MEMORIES
 *         WAL_<wtype>_SMEM_NUM_MEMORIES
 *         wal_<wtype>_description_structure
 * @wcfgtbl: name of IPcore config table (only name without index)
 * @winstidx: value of instance (used as index to IPcore config table)
 * @wsimd_num: number of SIMD used in the worker
 * @wnum_smems: number of support memories used in the worker
 * 
 * The macro declares all required shared memories and prepares structure of the
 * worker instance and pointer to the structure with specified name @wname.
 */
#define WAL_REGISTER_WORKER(wname, wtype, wcfgtbl, winstidx, wsimd_num, wnum_smems) \
	xc_shram_t *wname##_##wtype##_##wcfgtbl##_##winstidx##_data_memories[((wsimd_num>WAL_##wtype##_MAX_SIMD) ? WAL_##wtype##_MAX_SIMD : wsimd_num) * WAL_##wtype##_DMEM_NUM_MEMORIES]; \
	xc_shram_t *wname##_##wtype##_##wcfgtbl##_##winstidx##_ctrl_memories[WAL_##wtype##_CMEM_NUM_MEMORIES + ((wnum_smems>WAL_##wtype##_SMEM_NUM_MEMORIES) ? WAL_##wtype##_SMEM_NUM_MEMORIES : wnum_smems)]; \
	wal_worker_t wname##_data_structure = { \
		.struct_ver = WAL_DESC_STRUCT_VERSION_1, \
		.name = #wname, \
		.fm_desc = &wal_##wtype##_description_structure, \
		.inst_cfg_tbl = (void *)&wcfgtbl[winstidx], \
		.inst_iface = NULL, \
		.ctrl_mems = wname##_##wtype##_##wcfgtbl##_##winstidx##_ctrl_memories, \
		.data_mems = wname##_##wtype##_##wcfgtbl##_##winstidx##_data_memories, \
		.num_simd = (wsimd_num>WAL_##wtype##_MAX_SIMD) ? WAL_##wtype##_MAX_SIMD : wsimd_num, \
		.num_smems = ((wnum_smems>WAL_##wtype##_SMEM_NUM_MEMORIES) ? WAL_##wtype##_SMEM_NUM_MEMORIES : wnum_smems), \
		.op_state = WAL_WRK_STATE_IDLE, \
		.op_runmode = 0, \
		.userdata = NULL }; \
	wal_worker_t *wname = &wname##_data_structure


#endif /* _WORKER_ABSTRACTION_LAYER_API_HEADER_FILE_ */
